Home | History | Annotate | Line # | Download | only in namespace
nsconvert.c revision 1.1
      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 "acpi.h"
     48 #include "accommon.h"
     49 #include "acnamesp.h"
     50 #include "acinterp.h"
     51 #include "acpredef.h"
     52 #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 
     71 ACPI_STATUS
     72 AcpiNsConvertToInteger (
     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 
    142 ACPI_STATUS
    143 AcpiNsConvertToString (
    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 
    234 ACPI_STATUS
    235 AcpiNsConvertToBuffer (
    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 
    344 ACPI_STATUS
    345 AcpiNsConvertToUnicode (
    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 
    417 ACPI_STATUS
    418 AcpiNsConvertToResource (
    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