1/******************************************************************************
2 *
3 * Module Name: nsconvert - Object conversions for objects returned by
4 *                          predefined methods
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2013, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions, and the following disclaimer,
17 *    without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 *    substantially similar to the "NO WARRANTY" disclaimer below
20 *    ("Disclaimer") and any redistribution must be conditioned upon
21 *    including a substantially similar Disclaimer requirement for further
22 *    binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 *    of any contributors may be used to endorse or promote products derived
25 *    from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#define __NSCONVERT_C__
46
47#include <contrib/dev/acpica/include/acpi.h>
48#include <contrib/dev/acpica/include/accommon.h>
49#include <contrib/dev/acpica/include/acnamesp.h>
50#include <contrib/dev/acpica/include/acinterp.h>
51#include <contrib/dev/acpica/include/acpredef.h>
52#include <contrib/dev/acpica/include/amlresrc.h>
53
54#define _COMPONENT          ACPI_NAMESPACE
55        ACPI_MODULE_NAME    ("nsconvert")
56
57
58/*******************************************************************************
59 *
60 * FUNCTION:    AcpiNsConvertToInteger
61 *
62 * PARAMETERS:  OriginalObject      - Object to be converted
63 *              ReturnObject        - Where the new converted object is returned
64 *
65 * RETURN:      Status. AE_OK if conversion was successful.
66 *
67 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
68 *
69 ******************************************************************************/
70
71ACPI_STATUS
72AcpiNsConvertToInteger (
73    ACPI_OPERAND_OBJECT     *OriginalObject,
74    ACPI_OPERAND_OBJECT     **ReturnObject)
75{
76    ACPI_OPERAND_OBJECT     *NewObject;
77    ACPI_STATUS             Status;
78    UINT64                  Value = 0;
79    UINT32                  i;
80
81
82    switch (OriginalObject->Common.Type)
83    {
84    case ACPI_TYPE_STRING:
85
86        /* String-to-Integer conversion */
87
88        Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer,
89                    ACPI_ANY_BASE, &Value);
90        if (ACPI_FAILURE (Status))
91        {
92            return (Status);
93        }
94        break;
95
96    case ACPI_TYPE_BUFFER:
97
98        /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
99
100        if (OriginalObject->Buffer.Length > 8)
101        {
102            return (AE_AML_OPERAND_TYPE);
103        }
104
105        /* Extract each buffer byte to create the integer */
106
107        for (i = 0; i < OriginalObject->Buffer.Length; i++)
108        {
109            Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8));
110        }
111        break;
112
113    default:
114
115        return (AE_AML_OPERAND_TYPE);
116    }
117
118    NewObject = AcpiUtCreateIntegerObject (Value);
119    if (!NewObject)
120    {
121        return (AE_NO_MEMORY);
122    }
123
124    *ReturnObject = NewObject;
125    return (AE_OK);
126}
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    AcpiNsConvertToString
132 *
133 * PARAMETERS:  OriginalObject      - Object to be converted
134 *              ReturnObject        - Where the new converted object is returned
135 *
136 * RETURN:      Status. AE_OK if conversion was successful.
137 *
138 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
139 *
140 ******************************************************************************/
141
142ACPI_STATUS
143AcpiNsConvertToString (
144    ACPI_OPERAND_OBJECT     *OriginalObject,
145    ACPI_OPERAND_OBJECT     **ReturnObject)
146{
147    ACPI_OPERAND_OBJECT     *NewObject;
148    ACPI_SIZE               Length;
149    ACPI_STATUS             Status;
150
151
152    switch (OriginalObject->Common.Type)
153    {
154    case ACPI_TYPE_INTEGER:
155        /*
156         * Integer-to-String conversion. Commonly, convert
157         * an integer of value 0 to a NULL string. The last element of
158         * _BIF and _BIX packages occasionally need this fix.
159         */
160        if (OriginalObject->Integer.Value == 0)
161        {
162            /* Allocate a new NULL string object */
163
164            NewObject = AcpiUtCreateStringObject (0);
165            if (!NewObject)
166            {
167                return (AE_NO_MEMORY);
168            }
169        }
170        else
171        {
172            Status = AcpiExConvertToString (OriginalObject, &NewObject,
173                        ACPI_IMPLICIT_CONVERT_HEX);
174            if (ACPI_FAILURE (Status))
175            {
176                return (Status);
177            }
178        }
179        break;
180
181    case ACPI_TYPE_BUFFER:
182        /*
183         * Buffer-to-String conversion. Use a ToString
184         * conversion, no transform performed on the buffer data. The best
185         * example of this is the _BIF method, where the string data from
186         * the battery is often (incorrectly) returned as buffer object(s).
187         */
188        Length = 0;
189        while ((Length < OriginalObject->Buffer.Length) &&
190                (OriginalObject->Buffer.Pointer[Length]))
191        {
192            Length++;
193        }
194
195        /* Allocate a new string object */
196
197        NewObject = AcpiUtCreateStringObject (Length);
198        if (!NewObject)
199        {
200            return (AE_NO_MEMORY);
201        }
202
203        /*
204         * Copy the raw buffer data with no transform. String is already NULL
205         * terminated at Length+1.
206         */
207        ACPI_MEMCPY (NewObject->String.Pointer,
208            OriginalObject->Buffer.Pointer, Length);
209        break;
210
211    default:
212
213        return (AE_AML_OPERAND_TYPE);
214    }
215
216    *ReturnObject = NewObject;
217    return (AE_OK);
218}
219
220
221/*******************************************************************************
222 *
223 * FUNCTION:    AcpiNsConvertToBuffer
224 *
225 * PARAMETERS:  OriginalObject      - Object to be converted
226 *              ReturnObject        - Where the new converted object is returned
227 *
228 * RETURN:      Status. AE_OK if conversion was successful.
229 *
230 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
231 *
232 ******************************************************************************/
233
234ACPI_STATUS
235AcpiNsConvertToBuffer (
236    ACPI_OPERAND_OBJECT     *OriginalObject,
237    ACPI_OPERAND_OBJECT     **ReturnObject)
238{
239    ACPI_OPERAND_OBJECT     *NewObject;
240    ACPI_STATUS             Status;
241    ACPI_OPERAND_OBJECT     **Elements;
242    UINT32                  *DwordBuffer;
243    UINT32                  Count;
244    UINT32                  i;
245
246
247    switch (OriginalObject->Common.Type)
248    {
249    case ACPI_TYPE_INTEGER:
250        /*
251         * Integer-to-Buffer conversion.
252         * Convert the Integer to a packed-byte buffer. _MAT and other
253         * objects need this sometimes, if a read has been performed on a
254         * Field object that is less than or equal to the global integer
255         * size (32 or 64 bits).
256         */
257        Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
258        if (ACPI_FAILURE (Status))
259        {
260            return (Status);
261        }
262        break;
263
264    case ACPI_TYPE_STRING:
265
266        /* String-to-Buffer conversion. Simple data copy */
267
268        NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length);
269        if (!NewObject)
270        {
271            return (AE_NO_MEMORY);
272        }
273
274        ACPI_MEMCPY (NewObject->Buffer.Pointer,
275            OriginalObject->String.Pointer, OriginalObject->String.Length);
276        break;
277
278    case ACPI_TYPE_PACKAGE:
279        /*
280         * This case is often seen for predefined names that must return a
281         * Buffer object with multiple DWORD integers within. For example,
282         * _FDE and _GTM. The Package can be converted to a Buffer.
283         */
284
285        /* All elements of the Package must be integers */
286
287        Elements = OriginalObject->Package.Elements;
288        Count = OriginalObject->Package.Count;
289
290        for (i = 0; i < Count; i++)
291        {
292            if ((!*Elements) ||
293                ((*Elements)->Common.Type != ACPI_TYPE_INTEGER))
294            {
295                return (AE_AML_OPERAND_TYPE);
296            }
297            Elements++;
298        }
299
300        /* Create the new buffer object to replace the Package */
301
302        NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count));
303        if (!NewObject)
304        {
305            return (AE_NO_MEMORY);
306        }
307
308        /* Copy the package elements (integers) to the buffer as DWORDs */
309
310        Elements = OriginalObject->Package.Elements;
311        DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer);
312
313        for (i = 0; i < Count; i++)
314        {
315            *DwordBuffer = (UINT32) (*Elements)->Integer.Value;
316            DwordBuffer++;
317            Elements++;
318        }
319        break;
320
321    default:
322
323        return (AE_AML_OPERAND_TYPE);
324    }
325
326    *ReturnObject = NewObject;
327    return (AE_OK);
328}
329
330
331/*******************************************************************************
332 *
333 * FUNCTION:    AcpiNsConvertToUnicode
334 *
335 * PARAMETERS:  OriginalObject      - ASCII String Object to be converted
336 *              ReturnObject        - Where the new converted object is returned
337 *
338 * RETURN:      Status. AE_OK if conversion was successful.
339 *
340 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
341 *
342 ******************************************************************************/
343
344ACPI_STATUS
345AcpiNsConvertToUnicode (
346    ACPI_OPERAND_OBJECT     *OriginalObject,
347    ACPI_OPERAND_OBJECT     **ReturnObject)
348{
349    ACPI_OPERAND_OBJECT     *NewObject;
350    char                    *AsciiString;
351    UINT16                  *UnicodeBuffer;
352    UINT32                  UnicodeLength;
353    UINT32                  i;
354
355
356    if (!OriginalObject)
357    {
358        return (AE_OK);
359    }
360
361    /* If a Buffer was returned, it must be at least two bytes long */
362
363    if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER)
364    {
365        if (OriginalObject->Buffer.Length < 2)
366        {
367            return (AE_AML_OPERAND_VALUE);
368        }
369
370        *ReturnObject = NULL;
371        return (AE_OK);
372    }
373
374    /*
375     * The original object is an ASCII string. Convert this string to
376     * a unicode buffer.
377     */
378    AsciiString = OriginalObject->String.Pointer;
379    UnicodeLength = (OriginalObject->String.Length * 2) + 2;
380
381    /* Create a new buffer object for the Unicode data */
382
383    NewObject = AcpiUtCreateBufferObject (UnicodeLength);
384    if (!NewObject)
385    {
386        return (AE_NO_MEMORY);
387    }
388
389    UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer);
390
391    /* Convert ASCII to Unicode */
392
393    for (i = 0; i < OriginalObject->String.Length; i++)
394    {
395        UnicodeBuffer[i] = (UINT16) AsciiString[i];
396    }
397
398    *ReturnObject = NewObject;
399    return (AE_OK);
400}
401
402
403/*******************************************************************************
404 *
405 * FUNCTION:    AcpiNsConvertToResource
406 *
407 * PARAMETERS:  OriginalObject      - Object to be converted
408 *              ReturnObject        - Where the new converted object is returned
409 *
410 * RETURN:      Status. AE_OK if conversion was successful
411 *
412 * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate
413 *              Buffer.
414 *
415 ******************************************************************************/
416
417ACPI_STATUS
418AcpiNsConvertToResource (
419    ACPI_OPERAND_OBJECT     *OriginalObject,
420    ACPI_OPERAND_OBJECT     **ReturnObject)
421{
422    ACPI_OPERAND_OBJECT     *NewObject;
423    UINT8                   *Buffer;
424
425
426    /*
427     * We can fix the following cases for an expected resource template:
428     * 1. No return value (interpreter slack mode is disabled)
429     * 2. A "Return (Zero)" statement
430     * 3. A "Return empty buffer" statement
431     *
432     * We will return a buffer containing a single EndTag
433     * resource descriptor.
434     */
435    if (OriginalObject)
436    {
437        switch (OriginalObject->Common.Type)
438        {
439        case ACPI_TYPE_INTEGER:
440
441            /* We can only repair an Integer==0 */
442
443            if (OriginalObject->Integer.Value)
444            {
445                return (AE_AML_OPERAND_TYPE);
446            }
447            break;
448
449        case ACPI_TYPE_BUFFER:
450
451            if (OriginalObject->Buffer.Length)
452            {
453                /* Additional checks can be added in the future */
454
455                *ReturnObject = NULL;
456                return (AE_OK);
457            }
458            break;
459
460        case ACPI_TYPE_STRING:
461        default:
462
463            return (AE_AML_OPERAND_TYPE);
464        }
465    }
466
467    /* Create the new buffer object for the resource descriptor */
468
469    NewObject = AcpiUtCreateBufferObject (2);
470    if (!NewObject)
471    {
472        return (AE_NO_MEMORY);
473    }
474
475    Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer);
476
477    /* Initialize the Buffer with a single EndTag descriptor */
478
479    Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
480    Buffer[1] = 0x00;
481
482    *ReturnObject = NewObject;
483    return (AE_OK);
484}
485