Home | History | Annotate | Line # | Download | only in namespace
nsconvert.c revision 1.1.1.13
      1 /******************************************************************************
      2  *
      3  * Module Name: nsconvert - Object conversions for objects returned by
      4  *                          predefined methods
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2019, 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, &Value);
     87         if (ACPI_FAILURE (Status))
     88         {
     89             return (Status);
     90         }
     91         break;
     92 
     93     case ACPI_TYPE_BUFFER:
     94 
     95         /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
     96 
     97         if (OriginalObject->Buffer.Length > 8)
     98         {
     99             return (AE_AML_OPERAND_TYPE);
    100         }
    101 
    102         /* Extract each buffer byte to create the integer */
    103 
    104         for (i = 0; i < OriginalObject->Buffer.Length; i++)
    105         {
    106             Value |= ((UINT64)
    107                 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,
    171                 &NewObject, 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         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
    267             (OriginalObject->String.Length);
    268         if (!NewObject)
    269         {
    270             return (AE_NO_MEMORY);
    271         }
    272 
    273         memcpy (NewObject->Buffer.Pointer,
    274             OriginalObject->String.Pointer, OriginalObject->String.Length);
    275         break;
    276 
    277     case ACPI_TYPE_PACKAGE:
    278         /*
    279          * This case is often seen for predefined names that must return a
    280          * Buffer object with multiple DWORD integers within. For example,
    281          * _FDE and _GTM. The Package can be converted to a Buffer.
    282          */
    283 
    284         /* All elements of the Package must be integers */
    285 
    286         Elements = OriginalObject->Package.Elements;
    287         Count = OriginalObject->Package.Count;
    288 
    289         for (i = 0; i < Count; i++)
    290         {
    291             if ((!*Elements) ||
    292                 ((*Elements)->Common.Type != ACPI_TYPE_INTEGER))
    293             {
    294                 return (AE_AML_OPERAND_TYPE);
    295             }
    296             Elements++;
    297         }
    298 
    299         /* Create the new buffer object to replace the Package */
    300 
    301         NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count));
    302         if (!NewObject)
    303         {
    304             return (AE_NO_MEMORY);
    305         }
    306 
    307         /* Copy the package elements (integers) to the buffer as DWORDs */
    308 
    309         Elements = OriginalObject->Package.Elements;
    310         DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer);
    311 
    312         for (i = 0; i < Count; i++)
    313         {
    314             *DwordBuffer = (UINT32) (*Elements)->Integer.Value;
    315             DwordBuffer++;
    316             Elements++;
    317         }
    318         break;
    319 
    320     default:
    321 
    322         return (AE_AML_OPERAND_TYPE);
    323     }
    324 
    325     *ReturnObject = NewObject;
    326     return (AE_OK);
    327 }
    328 
    329 
    330 /*******************************************************************************
    331  *
    332  * FUNCTION:    AcpiNsConvertToUnicode
    333  *
    334  * PARAMETERS:  Scope               - Namespace node for the method/object
    335  *              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_NAMESPACE_NODE     *Scope,
    347     ACPI_OPERAND_OBJECT     *OriginalObject,
    348     ACPI_OPERAND_OBJECT     **ReturnObject)
    349 {
    350     ACPI_OPERAND_OBJECT     *NewObject;
    351     char                    *AsciiString;
    352     UINT16                  *UnicodeBuffer;
    353     UINT32                  UnicodeLength;
    354     UINT32                  i;
    355 
    356 
    357     if (!OriginalObject)
    358     {
    359         return (AE_OK);
    360     }
    361 
    362     /* If a Buffer was returned, it must be at least two bytes long */
    363 
    364     if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER)
    365     {
    366         if (OriginalObject->Buffer.Length < 2)
    367         {
    368             return (AE_AML_OPERAND_VALUE);
    369         }
    370 
    371         *ReturnObject = NULL;
    372         return (AE_OK);
    373     }
    374 
    375     /*
    376      * The original object is an ASCII string. Convert this string to
    377      * a unicode buffer.
    378      */
    379     AsciiString = OriginalObject->String.Pointer;
    380     UnicodeLength = (OriginalObject->String.Length * 2) + 2;
    381 
    382     /* Create a new buffer object for the Unicode data */
    383 
    384     NewObject = AcpiUtCreateBufferObject (UnicodeLength);
    385     if (!NewObject)
    386     {
    387         return (AE_NO_MEMORY);
    388     }
    389 
    390     UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer);
    391 
    392     /* Convert ASCII to Unicode */
    393 
    394     for (i = 0; i < OriginalObject->String.Length; i++)
    395     {
    396         UnicodeBuffer[i] = (UINT16) AsciiString[i];
    397     }
    398 
    399     *ReturnObject = NewObject;
    400     return (AE_OK);
    401 }
    402 
    403 
    404 /*******************************************************************************
    405  *
    406  * FUNCTION:    AcpiNsConvertToResource
    407  *
    408  * PARAMETERS:  Scope               - Namespace node for the method/object
    409  *              OriginalObject      - Object to be converted
    410  *              ReturnObject        - Where the new converted object is returned
    411  *
    412  * RETURN:      Status. AE_OK if conversion was successful
    413  *
    414  * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate
    415  *              Buffer.
    416  *
    417  ******************************************************************************/
    418 
    419 ACPI_STATUS
    420 AcpiNsConvertToResource (
    421     ACPI_NAMESPACE_NODE     *Scope,
    422     ACPI_OPERAND_OBJECT     *OriginalObject,
    423     ACPI_OPERAND_OBJECT     **ReturnObject)
    424 {
    425     ACPI_OPERAND_OBJECT     *NewObject;
    426     UINT8                   *Buffer;
    427 
    428 
    429     /*
    430      * We can fix the following cases for an expected resource template:
    431      * 1. No return value (interpreter slack mode is disabled)
    432      * 2. A "Return (Zero)" statement
    433      * 3. A "Return empty buffer" statement
    434      *
    435      * We will return a buffer containing a single EndTag
    436      * resource descriptor.
    437      */
    438     if (OriginalObject)
    439     {
    440         switch (OriginalObject->Common.Type)
    441         {
    442         case ACPI_TYPE_INTEGER:
    443 
    444             /* We can only repair an Integer==0 */
    445 
    446             if (OriginalObject->Integer.Value)
    447             {
    448                 return (AE_AML_OPERAND_TYPE);
    449             }
    450             break;
    451 
    452         case ACPI_TYPE_BUFFER:
    453 
    454             if (OriginalObject->Buffer.Length)
    455             {
    456                 /* Additional checks can be added in the future */
    457 
    458                 *ReturnObject = NULL;
    459                 return (AE_OK);
    460             }
    461             break;
    462 
    463         case ACPI_TYPE_STRING:
    464         default:
    465 
    466             return (AE_AML_OPERAND_TYPE);
    467         }
    468     }
    469 
    470     /* Create the new buffer object for the resource descriptor */
    471 
    472     NewObject = AcpiUtCreateBufferObject (2);
    473     if (!NewObject)
    474     {
    475         return (AE_NO_MEMORY);
    476     }
    477 
    478     Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer);
    479 
    480     /* Initialize the Buffer with a single EndTag descriptor */
    481 
    482     Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
    483     Buffer[1] = 0x00;
    484 
    485     *ReturnObject = NewObject;
    486     return (AE_OK);
    487 }
    488 
    489 
    490 /*******************************************************************************
    491  *
    492  * FUNCTION:    AcpiNsConvertToReference
    493  *
    494  * PARAMETERS:  Scope               - Namespace node for the method/object
    495  *              OriginalObject      - Object to be converted
    496  *              ReturnObject        - Where the new converted object is returned
    497  *
    498  * RETURN:      Status. AE_OK if conversion was successful
    499  *
    500  * DESCRIPTION: Attempt to convert a Integer object to a ObjectReference.
    501  *              Buffer.
    502  *
    503  ******************************************************************************/
    504 
    505 ACPI_STATUS
    506 AcpiNsConvertToReference (
    507     ACPI_NAMESPACE_NODE     *Scope,
    508     ACPI_OPERAND_OBJECT     *OriginalObject,
    509     ACPI_OPERAND_OBJECT     **ReturnObject)
    510 {
    511     ACPI_OPERAND_OBJECT     *NewObject = NULL;
    512     ACPI_STATUS             Status;
    513     ACPI_NAMESPACE_NODE     *Node;
    514     ACPI_GENERIC_STATE      ScopeInfo;
    515     char                    *Name;
    516 
    517 
    518     ACPI_FUNCTION_NAME (NsConvertToReference);
    519 
    520 
    521     /* Convert path into internal presentation */
    522 
    523     Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name);
    524     if (ACPI_FAILURE (Status))
    525     {
    526         return_ACPI_STATUS (Status);
    527     }
    528 
    529     /* Find the namespace node */
    530 
    531     ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope);
    532     Status = AcpiNsLookup (&ScopeInfo, Name,
    533         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
    534         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node);
    535     if (ACPI_FAILURE (Status))
    536     {
    537         /* Check if we are resolving a named reference within a package */
    538 
    539         ACPI_ERROR_NAMESPACE (&ScopeInfo,
    540             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 (Status);
    566 }
    567