Home | History | Annotate | Line # | Download | only in namespace
nsconvert.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: nsconvert - Object conversions for objects returned by
      4  *                          predefined methods
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2015, 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 #include "acpi.h"
     46 #include "accommon.h"
     47 #include "acnamesp.h"
     48 #include "acinterp.h"
     49 #include "acpredef.h"
     50 #include "amlresrc.h"
     51 
     52 #define _COMPONENT          ACPI_NAMESPACE
     53         ACPI_MODULE_NAME    ("nsconvert")
     54 
     55 
     56 /*******************************************************************************
     57  *
     58  * FUNCTION:    AcpiNsConvertToInteger
     59  *
     60  * PARAMETERS:  OriginalObject      - Object to be converted
     61  *              ReturnObject        - Where the new converted object is returned
     62  *
     63  * RETURN:      Status. AE_OK if conversion was successful.
     64  *
     65  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
     66  *
     67  ******************************************************************************/
     68 
     69 ACPI_STATUS
     70 AcpiNsConvertToInteger (
     71     ACPI_OPERAND_OBJECT     *OriginalObject,
     72     ACPI_OPERAND_OBJECT     **ReturnObject)
     73 {
     74     ACPI_OPERAND_OBJECT     *NewObject;
     75     ACPI_STATUS             Status;
     76     UINT64                  Value = 0;
     77     UINT32                  i;
     78 
     79 
     80     switch (OriginalObject->Common.Type)
     81     {
     82     case ACPI_TYPE_STRING:
     83 
     84         /* String-to-Integer conversion */
     85 
     86         Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer,
     87                     ACPI_ANY_BASE, &Value);
     88         if (ACPI_FAILURE (Status))
     89         {
     90             return (Status);
     91         }
     92         break;
     93 
     94     case ACPI_TYPE_BUFFER:
     95 
     96         /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
     97 
     98         if (OriginalObject->Buffer.Length > 8)
     99         {
    100             return (AE_AML_OPERAND_TYPE);
    101         }
    102 
    103         /* Extract each buffer byte to create the integer */
    104 
    105         for (i = 0; i < OriginalObject->Buffer.Length; i++)
    106         {
    107             Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8));
    108         }
    109         break;
    110 
    111     default:
    112 
    113         return (AE_AML_OPERAND_TYPE);
    114     }
    115 
    116     NewObject = AcpiUtCreateIntegerObject (Value);
    117     if (!NewObject)
    118     {
    119         return (AE_NO_MEMORY);
    120     }
    121 
    122     *ReturnObject = NewObject;
    123     return (AE_OK);
    124 }
    125 
    126 
    127 /*******************************************************************************
    128  *
    129  * FUNCTION:    AcpiNsConvertToString
    130  *
    131  * PARAMETERS:  OriginalObject      - Object to be converted
    132  *              ReturnObject        - Where the new converted object is returned
    133  *
    134  * RETURN:      Status. AE_OK if conversion was successful.
    135  *
    136  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
    137  *
    138  ******************************************************************************/
    139 
    140 ACPI_STATUS
    141 AcpiNsConvertToString (
    142     ACPI_OPERAND_OBJECT     *OriginalObject,
    143     ACPI_OPERAND_OBJECT     **ReturnObject)
    144 {
    145     ACPI_OPERAND_OBJECT     *NewObject;
    146     ACPI_SIZE               Length;
    147     ACPI_STATUS             Status;
    148 
    149 
    150     switch (OriginalObject->Common.Type)
    151     {
    152     case ACPI_TYPE_INTEGER:
    153         /*
    154          * Integer-to-String conversion. Commonly, convert
    155          * an integer of value 0 to a NULL string. The last element of
    156          * _BIF and _BIX packages occasionally need this fix.
    157          */
    158         if (OriginalObject->Integer.Value == 0)
    159         {
    160             /* Allocate a new NULL string object */
    161 
    162             NewObject = AcpiUtCreateStringObject (0);
    163             if (!NewObject)
    164             {
    165                 return (AE_NO_MEMORY);
    166             }
    167         }
    168         else
    169         {
    170             Status = AcpiExConvertToString (OriginalObject, &NewObject,
    171                         ACPI_IMPLICIT_CONVERT_HEX);
    172             if (ACPI_FAILURE (Status))
    173             {
    174                 return (Status);
    175             }
    176         }
    177         break;
    178 
    179     case ACPI_TYPE_BUFFER:
    180         /*
    181          * Buffer-to-String conversion. Use a ToString
    182          * conversion, no transform performed on the buffer data. The best
    183          * example of this is the _BIF method, where the string data from
    184          * the battery is often (incorrectly) returned as buffer object(s).
    185          */
    186         Length = 0;
    187         while ((Length < OriginalObject->Buffer.Length) &&
    188                 (OriginalObject->Buffer.Pointer[Length]))
    189         {
    190             Length++;
    191         }
    192 
    193         /* Allocate a new string object */
    194 
    195         NewObject = AcpiUtCreateStringObject (Length);
    196         if (!NewObject)
    197         {
    198             return (AE_NO_MEMORY);
    199         }
    200 
    201         /*
    202          * Copy the raw buffer data with no transform. String is already NULL
    203          * terminated at Length+1.
    204          */
    205         ACPI_MEMCPY (NewObject->String.Pointer,
    206             OriginalObject->Buffer.Pointer, Length);
    207         break;
    208 
    209     default:
    210 
    211         return (AE_AML_OPERAND_TYPE);
    212     }
    213 
    214     *ReturnObject = NewObject;
    215     return (AE_OK);
    216 }
    217 
    218 
    219 /*******************************************************************************
    220  *
    221  * FUNCTION:    AcpiNsConvertToBuffer
    222  *
    223  * PARAMETERS:  OriginalObject      - Object to be converted
    224  *              ReturnObject        - Where the new converted object is returned
    225  *
    226  * RETURN:      Status. AE_OK if conversion was successful.
    227  *
    228  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
    229  *
    230  ******************************************************************************/
    231 
    232 ACPI_STATUS
    233 AcpiNsConvertToBuffer (
    234     ACPI_OPERAND_OBJECT     *OriginalObject,
    235     ACPI_OPERAND_OBJECT     **ReturnObject)
    236 {
    237     ACPI_OPERAND_OBJECT     *NewObject;
    238     ACPI_STATUS             Status;
    239     ACPI_OPERAND_OBJECT     **Elements;
    240     UINT32                  *DwordBuffer;
    241     UINT32                  Count;
    242     UINT32                  i;
    243 
    244 
    245     switch (OriginalObject->Common.Type)
    246     {
    247     case ACPI_TYPE_INTEGER:
    248         /*
    249          * Integer-to-Buffer conversion.
    250          * Convert the Integer to a packed-byte buffer. _MAT and other
    251          * objects need this sometimes, if a read has been performed on a
    252          * Field object that is less than or equal to the global integer
    253          * size (32 or 64 bits).
    254          */
    255         Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
    256         if (ACPI_FAILURE (Status))
    257         {
    258             return (Status);
    259         }
    260         break;
    261 
    262     case ACPI_TYPE_STRING:
    263 
    264         /* String-to-Buffer conversion. Simple data copy */
    265 
    266         NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length);
    267         if (!NewObject)
    268         {
    269             return (AE_NO_MEMORY);
    270         }
    271 
    272         ACPI_MEMCPY (NewObject->Buffer.Pointer,
    273             OriginalObject->String.Pointer, OriginalObject->String.Length);
    274         break;
    275 
    276     case ACPI_TYPE_PACKAGE:
    277         /*
    278          * This case is often seen for predefined names that must return a
    279          * Buffer object with multiple DWORD integers within. For example,
    280          * _FDE and _GTM. The Package can be converted to a Buffer.
    281          */
    282 
    283         /* All elements of the Package must be integers */
    284 
    285         Elements = OriginalObject->Package.Elements;
    286         Count = OriginalObject->Package.Count;
    287 
    288         for (i = 0; i < Count; i++)
    289         {
    290             if ((!*Elements) ||
    291                 ((*Elements)->Common.Type != ACPI_TYPE_INTEGER))
    292             {
    293                 return (AE_AML_OPERAND_TYPE);
    294             }
    295             Elements++;
    296         }
    297 
    298         /* Create the new buffer object to replace the Package */
    299 
    300         NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count));
    301         if (!NewObject)
    302         {
    303             return (AE_NO_MEMORY);
    304         }
    305 
    306         /* Copy the package elements (integers) to the buffer as DWORDs */
    307 
    308         Elements = OriginalObject->Package.Elements;
    309         DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer);
    310 
    311         for (i = 0; i < Count; i++)
    312         {
    313             *DwordBuffer = (UINT32) (*Elements)->Integer.Value;
    314             DwordBuffer++;
    315             Elements++;
    316         }
    317         break;
    318 
    319     default:
    320 
    321         return (AE_AML_OPERAND_TYPE);
    322     }
    323 
    324     *ReturnObject = NewObject;
    325     return (AE_OK);
    326 }
    327 
    328 
    329 /*******************************************************************************
    330  *
    331  * FUNCTION:    AcpiNsConvertToUnicode
    332  *
    333  * PARAMETERS:  OriginalObject      - ASCII String Object to be converted
    334  *              ReturnObject        - Where the new converted object is returned
    335  *
    336  * RETURN:      Status. AE_OK if conversion was successful.
    337  *
    338  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
    339  *
    340  ******************************************************************************/
    341 
    342 ACPI_STATUS
    343 AcpiNsConvertToUnicode (
    344     ACPI_OPERAND_OBJECT     *OriginalObject,
    345     ACPI_OPERAND_OBJECT     **ReturnObject)
    346 {
    347     ACPI_OPERAND_OBJECT     *NewObject;
    348     char                    *AsciiString;
    349     UINT16                  *UnicodeBuffer;
    350     UINT32                  UnicodeLength;
    351     UINT32                  i;
    352 
    353 
    354     if (!OriginalObject)
    355     {
    356         return (AE_OK);
    357     }
    358 
    359     /* If a Buffer was returned, it must be at least two bytes long */
    360 
    361     if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER)
    362     {
    363         if (OriginalObject->Buffer.Length < 2)
    364         {
    365             return (AE_AML_OPERAND_VALUE);
    366         }
    367 
    368         *ReturnObject = NULL;
    369         return (AE_OK);
    370     }
    371 
    372     /*
    373      * The original object is an ASCII string. Convert this string to
    374      * a unicode buffer.
    375      */
    376     AsciiString = OriginalObject->String.Pointer;
    377     UnicodeLength = (OriginalObject->String.Length * 2) + 2;
    378 
    379     /* Create a new buffer object for the Unicode data */
    380 
    381     NewObject = AcpiUtCreateBufferObject (UnicodeLength);
    382     if (!NewObject)
    383     {
    384         return (AE_NO_MEMORY);
    385     }
    386 
    387     UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer);
    388 
    389     /* Convert ASCII to Unicode */
    390 
    391     for (i = 0; i < OriginalObject->String.Length; i++)
    392     {
    393         UnicodeBuffer[i] = (UINT16) AsciiString[i];
    394     }
    395 
    396     *ReturnObject = NewObject;
    397     return (AE_OK);
    398 }
    399 
    400 
    401 /*******************************************************************************
    402  *
    403  * FUNCTION:    AcpiNsConvertToResource
    404  *
    405  * PARAMETERS:  OriginalObject      - Object to be converted
    406  *              ReturnObject        - Where the new converted object is returned
    407  *
    408  * RETURN:      Status. AE_OK if conversion was successful
    409  *
    410  * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate
    411  *              Buffer.
    412  *
    413  ******************************************************************************/
    414 
    415 ACPI_STATUS
    416 AcpiNsConvertToResource (
    417     ACPI_OPERAND_OBJECT     *OriginalObject,
    418     ACPI_OPERAND_OBJECT     **ReturnObject)
    419 {
    420     ACPI_OPERAND_OBJECT     *NewObject;
    421     UINT8                   *Buffer;
    422 
    423 
    424     /*
    425      * We can fix the following cases for an expected resource template:
    426      * 1. No return value (interpreter slack mode is disabled)
    427      * 2. A "Return (Zero)" statement
    428      * 3. A "Return empty buffer" statement
    429      *
    430      * We will return a buffer containing a single EndTag
    431      * resource descriptor.
    432      */
    433     if (OriginalObject)
    434     {
    435         switch (OriginalObject->Common.Type)
    436         {
    437         case ACPI_TYPE_INTEGER:
    438 
    439             /* We can only repair an Integer==0 */
    440 
    441             if (OriginalObject->Integer.Value)
    442             {
    443                 return (AE_AML_OPERAND_TYPE);
    444             }
    445             break;
    446 
    447         case ACPI_TYPE_BUFFER:
    448 
    449             if (OriginalObject->Buffer.Length)
    450             {
    451                 /* Additional checks can be added in the future */
    452 
    453                 *ReturnObject = NULL;
    454                 return (AE_OK);
    455             }
    456             break;
    457 
    458         case ACPI_TYPE_STRING:
    459         default:
    460 
    461             return (AE_AML_OPERAND_TYPE);
    462         }
    463     }
    464 
    465     /* Create the new buffer object for the resource descriptor */
    466 
    467     NewObject = AcpiUtCreateBufferObject (2);
    468     if (!NewObject)
    469     {
    470         return (AE_NO_MEMORY);
    471     }
    472 
    473     Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer);
    474 
    475     /* Initialize the Buffer with a single EndTag descriptor */
    476 
    477     Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
    478     Buffer[1] = 0x00;
    479 
    480     *ReturnObject = NewObject;
    481     return (AE_OK);
    482 }
    483