Home | History | Annotate | Line # | Download | only in namespace
nsconvert.c revision 1.1.1.8
      1 /******************************************************************************
      2  *
      3  * Module Name: nsconvert - Object conversions for objects returned by
      4  *                          predefined methods
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2017, 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             AcpiGbl_IntegerByteWidth, &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)
    108                 OriginalObject->Buffer.Pointer[i] << (i * 8));
    109         }
    110         break;
    111 
    112     default:
    113 
    114         return (AE_AML_OPERAND_TYPE);
    115     }
    116 
    117     NewObject = AcpiUtCreateIntegerObject (Value);
    118     if (!NewObject)
    119     {
    120         return (AE_NO_MEMORY);
    121     }
    122 
    123     *ReturnObject = NewObject;
    124     return (AE_OK);
    125 }
    126 
    127 
    128 /*******************************************************************************
    129  *
    130  * FUNCTION:    AcpiNsConvertToString
    131  *
    132  * PARAMETERS:  OriginalObject      - Object to be converted
    133  *              ReturnObject        - Where the new converted object is returned
    134  *
    135  * RETURN:      Status. AE_OK if conversion was successful.
    136  *
    137  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
    138  *
    139  ******************************************************************************/
    140 
    141 ACPI_STATUS
    142 AcpiNsConvertToString (
    143     ACPI_OPERAND_OBJECT     *OriginalObject,
    144     ACPI_OPERAND_OBJECT     **ReturnObject)
    145 {
    146     ACPI_OPERAND_OBJECT     *NewObject;
    147     ACPI_SIZE               Length;
    148     ACPI_STATUS             Status;
    149 
    150 
    151     switch (OriginalObject->Common.Type)
    152     {
    153     case ACPI_TYPE_INTEGER:
    154         /*
    155          * Integer-to-String conversion. Commonly, convert
    156          * an integer of value 0 to a NULL string. The last element of
    157          * _BIF and _BIX packages occasionally need this fix.
    158          */
    159         if (OriginalObject->Integer.Value == 0)
    160         {
    161             /* Allocate a new NULL string object */
    162 
    163             NewObject = AcpiUtCreateStringObject (0);
    164             if (!NewObject)
    165             {
    166                 return (AE_NO_MEMORY);
    167             }
    168         }
    169         else
    170         {
    171             Status = AcpiExConvertToString (OriginalObject,
    172                 &NewObject, ACPI_IMPLICIT_CONVERT_HEX);
    173             if (ACPI_FAILURE (Status))
    174             {
    175                 return (Status);
    176             }
    177         }
    178         break;
    179 
    180     case ACPI_TYPE_BUFFER:
    181         /*
    182          * Buffer-to-String conversion. Use a ToString
    183          * conversion, no transform performed on the buffer data. The best
    184          * example of this is the _BIF method, where the string data from
    185          * the battery is often (incorrectly) returned as buffer object(s).
    186          */
    187         Length = 0;
    188         while ((Length < OriginalObject->Buffer.Length) &&
    189                 (OriginalObject->Buffer.Pointer[Length]))
    190         {
    191             Length++;
    192         }
    193 
    194         /* Allocate a new string object */
    195 
    196         NewObject = AcpiUtCreateStringObject (Length);
    197         if (!NewObject)
    198         {
    199             return (AE_NO_MEMORY);
    200         }
    201 
    202         /*
    203          * Copy the raw buffer data with no transform. String is already NULL
    204          * terminated at Length+1.
    205          */
    206         memcpy (NewObject->String.Pointer,
    207             OriginalObject->Buffer.Pointer, Length);
    208         break;
    209 
    210     default:
    211 
    212         return (AE_AML_OPERAND_TYPE);
    213     }
    214 
    215     *ReturnObject = NewObject;
    216     return (AE_OK);
    217 }
    218 
    219 
    220 /*******************************************************************************
    221  *
    222  * FUNCTION:    AcpiNsConvertToBuffer
    223  *
    224  * PARAMETERS:  OriginalObject      - Object to be converted
    225  *              ReturnObject        - Where the new converted object is returned
    226  *
    227  * RETURN:      Status. AE_OK if conversion was successful.
    228  *
    229  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
    230  *
    231  ******************************************************************************/
    232 
    233 ACPI_STATUS
    234 AcpiNsConvertToBuffer (
    235     ACPI_OPERAND_OBJECT     *OriginalObject,
    236     ACPI_OPERAND_OBJECT     **ReturnObject)
    237 {
    238     ACPI_OPERAND_OBJECT     *NewObject;
    239     ACPI_STATUS             Status;
    240     ACPI_OPERAND_OBJECT     **Elements;
    241     UINT32                  *DwordBuffer;
    242     UINT32                  Count;
    243     UINT32                  i;
    244 
    245 
    246     switch (OriginalObject->Common.Type)
    247     {
    248     case ACPI_TYPE_INTEGER:
    249         /*
    250          * Integer-to-Buffer conversion.
    251          * Convert the Integer to a packed-byte buffer. _MAT and other
    252          * objects need this sometimes, if a read has been performed on a
    253          * Field object that is less than or equal to the global integer
    254          * size (32 or 64 bits).
    255          */
    256         Status = AcpiExConvertToBuffer (OriginalObject, &NewObject);
    257         if (ACPI_FAILURE (Status))
    258         {
    259             return (Status);
    260         }
    261         break;
    262 
    263     case ACPI_TYPE_STRING:
    264 
    265         /* String-to-Buffer conversion. Simple data copy */
    266 
    267         NewObject = AcpiUtCreateBufferObject
    268             (OriginalObject->String.Length);
    269         if (!NewObject)
    270         {
    271             return (AE_NO_MEMORY);
    272         }
    273 
    274         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:  Scope               - Namespace node for the method/object
    336  *              OriginalObject      - ASCII String Object to be converted
    337  *              ReturnObject        - Where the new converted object is returned
    338  *
    339  * RETURN:      Status. AE_OK if conversion was successful.
    340  *
    341  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
    342  *
    343  ******************************************************************************/
    344 
    345 ACPI_STATUS
    346 AcpiNsConvertToUnicode (
    347     ACPI_NAMESPACE_NODE     *Scope,
    348     ACPI_OPERAND_OBJECT     *OriginalObject,
    349     ACPI_OPERAND_OBJECT     **ReturnObject)
    350 {
    351     ACPI_OPERAND_OBJECT     *NewObject;
    352     char                    *AsciiString;
    353     UINT16                  *UnicodeBuffer;
    354     UINT32                  UnicodeLength;
    355     UINT32                  i;
    356 
    357 
    358     if (!OriginalObject)
    359     {
    360         return (AE_OK);
    361     }
    362 
    363     /* If a Buffer was returned, it must be at least two bytes long */
    364 
    365     if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER)
    366     {
    367         if (OriginalObject->Buffer.Length < 2)
    368         {
    369             return (AE_AML_OPERAND_VALUE);
    370         }
    371 
    372         *ReturnObject = NULL;
    373         return (AE_OK);
    374     }
    375 
    376     /*
    377      * The original object is an ASCII string. Convert this string to
    378      * a unicode buffer.
    379      */
    380     AsciiString = OriginalObject->String.Pointer;
    381     UnicodeLength = (OriginalObject->String.Length * 2) + 2;
    382 
    383     /* Create a new buffer object for the Unicode data */
    384 
    385     NewObject = AcpiUtCreateBufferObject (UnicodeLength);
    386     if (!NewObject)
    387     {
    388         return (AE_NO_MEMORY);
    389     }
    390 
    391     UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer);
    392 
    393     /* Convert ASCII to Unicode */
    394 
    395     for (i = 0; i < OriginalObject->String.Length; i++)
    396     {
    397         UnicodeBuffer[i] = (UINT16) AsciiString[i];
    398     }
    399 
    400     *ReturnObject = NewObject;
    401     return (AE_OK);
    402 }
    403 
    404 
    405 /*******************************************************************************
    406  *
    407  * FUNCTION:    AcpiNsConvertToResource
    408  *
    409  * PARAMETERS:  Scope               - Namespace node for the method/object
    410  *              OriginalObject      - Object to be converted
    411  *              ReturnObject        - Where the new converted object is returned
    412  *
    413  * RETURN:      Status. AE_OK if conversion was successful
    414  *
    415  * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate
    416  *              Buffer.
    417  *
    418  ******************************************************************************/
    419 
    420 ACPI_STATUS
    421 AcpiNsConvertToResource (
    422     ACPI_NAMESPACE_NODE     *Scope,
    423     ACPI_OPERAND_OBJECT     *OriginalObject,
    424     ACPI_OPERAND_OBJECT     **ReturnObject)
    425 {
    426     ACPI_OPERAND_OBJECT     *NewObject;
    427     UINT8                   *Buffer;
    428 
    429 
    430     /*
    431      * We can fix the following cases for an expected resource template:
    432      * 1. No return value (interpreter slack mode is disabled)
    433      * 2. A "Return (Zero)" statement
    434      * 3. A "Return empty buffer" statement
    435      *
    436      * We will return a buffer containing a single EndTag
    437      * resource descriptor.
    438      */
    439     if (OriginalObject)
    440     {
    441         switch (OriginalObject->Common.Type)
    442         {
    443         case ACPI_TYPE_INTEGER:
    444 
    445             /* We can only repair an Integer==0 */
    446 
    447             if (OriginalObject->Integer.Value)
    448             {
    449                 return (AE_AML_OPERAND_TYPE);
    450             }
    451             break;
    452 
    453         case ACPI_TYPE_BUFFER:
    454 
    455             if (OriginalObject->Buffer.Length)
    456             {
    457                 /* Additional checks can be added in the future */
    458 
    459                 *ReturnObject = NULL;
    460                 return (AE_OK);
    461             }
    462             break;
    463 
    464         case ACPI_TYPE_STRING:
    465         default:
    466 
    467             return (AE_AML_OPERAND_TYPE);
    468         }
    469     }
    470 
    471     /* Create the new buffer object for the resource descriptor */
    472 
    473     NewObject = AcpiUtCreateBufferObject (2);
    474     if (!NewObject)
    475     {
    476         return (AE_NO_MEMORY);
    477     }
    478 
    479     Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer);
    480 
    481     /* Initialize the Buffer with a single EndTag descriptor */
    482 
    483     Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
    484     Buffer[1] = 0x00;
    485 
    486     *ReturnObject = NewObject;
    487     return (AE_OK);
    488 }
    489 
    490 
    491 /*******************************************************************************
    492  *
    493  * FUNCTION:    AcpiNsConvertToReference
    494  *
    495  * PARAMETERS:  Scope               - Namespace node for the method/object
    496  *              OriginalObject      - Object to be converted
    497  *              ReturnObject        - Where the new converted object is returned
    498  *
    499  * RETURN:      Status. AE_OK if conversion was successful
    500  *
    501  * DESCRIPTION: Attempt to convert a Integer object to a ObjectReference.
    502  *              Buffer.
    503  *
    504  ******************************************************************************/
    505 
    506 ACPI_STATUS
    507 AcpiNsConvertToReference (
    508     ACPI_NAMESPACE_NODE     *Scope,
    509     ACPI_OPERAND_OBJECT     *OriginalObject,
    510     ACPI_OPERAND_OBJECT     **ReturnObject)
    511 {
    512     ACPI_OPERAND_OBJECT     *NewObject = NULL;
    513     ACPI_STATUS             Status;
    514     ACPI_NAMESPACE_NODE     *Node;
    515     ACPI_GENERIC_STATE      ScopeInfo;
    516     char                    *Name;
    517 
    518 
    519     ACPI_FUNCTION_NAME (NsConvertToReference);
    520 
    521 
    522     /* Convert path into internal presentation */
    523 
    524     Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name);
    525     if (ACPI_FAILURE (Status))
    526     {
    527         return_ACPI_STATUS (Status);
    528     }
    529 
    530     /* Find the namespace node */
    531 
    532     ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope);
    533     Status = AcpiNsLookup (&ScopeInfo, Name,
    534         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
    535         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node);
    536     if (ACPI_FAILURE (Status))
    537     {
    538         /* Check if we are resolving a named reference within a package */
    539 
    540         ACPI_ERROR_NAMESPACE (OriginalObject->String.Pointer, Status);
    541         goto ErrorExit;
    542     }
    543 
    544     /* Create and init a new internal ACPI object */
    545 
    546     NewObject = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
    547     if (!NewObject)
    548     {
    549         Status = AE_NO_MEMORY;
    550         goto ErrorExit;
    551     }
    552     NewObject->Reference.Node = Node;
    553     NewObject->Reference.Object = Node->Object;
    554     NewObject->Reference.Class = ACPI_REFCLASS_NAME;
    555 
    556     /*
    557      * Increase reference of the object if needed (the object is likely a
    558      * null for device nodes).
    559      */
    560     AcpiUtAddReference (Node->Object);
    561 
    562 ErrorExit:
    563     ACPI_FREE (Name);
    564     *ReturnObject = NewObject;
    565     return (AE_OK);
    566 }
    567