Home | History | Annotate | Line # | Download | only in compiler
aslopcodes.c revision 1.6
      1 /******************************************************************************
      2  *
      3  * Module Name: aslopcode - AML opcode generation
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "amlcode.h"
     47 
     48 #define _COMPONENT          ACPI_COMPILER
     49         ACPI_MODULE_NAME    ("aslopcodes")
     50 
     51 
     52 /* Local prototypes */
     53 
     54 static void
     55 OpcDoAccessAs (
     56     ACPI_PARSE_OBJECT       *Op);
     57 
     58 static void
     59 OpcDoConnection (
     60     ACPI_PARSE_OBJECT       *Op);
     61 
     62 static void
     63 OpcDoUnicode (
     64     ACPI_PARSE_OBJECT       *Op);
     65 
     66 static void
     67 OpcDoEisaId (
     68     ACPI_PARSE_OBJECT       *Op);
     69 
     70 static void
     71 OpcDoUuId (
     72     ACPI_PARSE_OBJECT       *Op);
     73 
     74 
     75 /*******************************************************************************
     76  *
     77  * FUNCTION:    OpcAmlOpcodeUpdateWalk
     78  *
     79  * PARAMETERS:  ASL_WALK_CALLBACK
     80  *
     81  * RETURN:      Status
     82  *
     83  * DESCRIPTION: Opcode update walk, ascending callback
     84  *
     85  ******************************************************************************/
     86 
     87 ACPI_STATUS
     88 OpcAmlOpcodeUpdateWalk (
     89     ACPI_PARSE_OBJECT       *Op,
     90     UINT32                  Level,
     91     void                    *Context)
     92 {
     93 
     94     /*
     95      * Handle the Package() case where the actual opcode cannot be determined
     96      * until the PackageLength operand has been folded and minimized.
     97      * (PackageOp versus VarPackageOp)
     98      *
     99      * This is (as of ACPI 3.0) the only case where the AML opcode can change
    100      * based upon the value of a parameter.
    101      *
    102      * The parser always inserts a VarPackage opcode, which can possibly be
    103      * optimized to a Package opcode.
    104      */
    105     if (Op->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)
    106     {
    107         OpnDoPackage (Op);
    108     }
    109 
    110     return (AE_OK);
    111 }
    112 
    113 
    114 /*******************************************************************************
    115  *
    116  * FUNCTION:    OpcAmlOpcodeWalk
    117  *
    118  * PARAMETERS:  ASL_WALK_CALLBACK
    119  *
    120  * RETURN:      Status
    121  *
    122  * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
    123  *              operands.
    124  *
    125  ******************************************************************************/
    126 
    127 ACPI_STATUS
    128 OpcAmlOpcodeWalk (
    129     ACPI_PARSE_OBJECT       *Op,
    130     UINT32                  Level,
    131     void                    *Context)
    132 {
    133 
    134     TotalParseNodes++;
    135 
    136     OpcGenerateAmlOpcode (Op);
    137     OpnGenerateAmlOperands (Op);
    138     return (AE_OK);
    139 }
    140 
    141 
    142 /*******************************************************************************
    143  *
    144  * FUNCTION:    OpcGetIntegerWidth
    145  *
    146  * PARAMETERS:  Op          - DEFINITION BLOCK op
    147  *
    148  * RETURN:      none
    149  *
    150  * DESCRIPTION: Extract integer width from the table revision
    151  *
    152  ******************************************************************************/
    153 
    154 void
    155 OpcGetIntegerWidth (
    156     ACPI_PARSE_OBJECT       *Op)
    157 {
    158     ACPI_PARSE_OBJECT       *Child;
    159 
    160 
    161     if (!Op)
    162     {
    163         return;
    164     }
    165 
    166     if (Gbl_RevisionOverride)
    167     {
    168         AcpiUtSetIntegerWidth (Gbl_RevisionOverride);
    169     }
    170     else
    171     {
    172         Child = Op->Asl.Child;
    173         Child = Child->Asl.Next;
    174         Child = Child->Asl.Next;
    175 
    176         /* Use the revision to set the integer width */
    177 
    178         AcpiUtSetIntegerWidth ((UINT8) Child->Asl.Value.Integer);
    179     }
    180 }
    181 
    182 
    183 /*******************************************************************************
    184  *
    185  * FUNCTION:    OpcSetOptimalIntegerSize
    186  *
    187  * PARAMETERS:  Op        - A parse tree node
    188  *
    189  * RETURN:      Integer width, in bytes. Also sets the node AML opcode to the
    190  *              optimal integer AML prefix opcode.
    191  *
    192  * DESCRIPTION: Determine the optimal AML encoding of an integer. All leading
    193  *              zeros can be truncated to squeeze the integer into the
    194  *              minimal number of AML bytes.
    195  *
    196  ******************************************************************************/
    197 
    198 UINT32
    199 OpcSetOptimalIntegerSize (
    200     ACPI_PARSE_OBJECT       *Op)
    201 {
    202 
    203 #if 0
    204     /*
    205      * TBD: - we don't want to optimize integers in the block header, but the
    206      * code below does not work correctly.
    207      */
    208     if (Op->Asl.Parent &&
    209         Op->Asl.Parent->Asl.Parent &&
    210        (Op->Asl.Parent->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK))
    211     {
    212         return (0);
    213     }
    214 #endif
    215 
    216     /*
    217      * Check for the special AML integers first - Zero, One, Ones.
    218      * These are single-byte opcodes that are the smallest possible
    219      * representation of an integer.
    220      *
    221      * This optimization is optional.
    222      */
    223     if (Gbl_IntegerOptimizationFlag)
    224     {
    225         switch (Op->Asl.Value.Integer)
    226         {
    227         case 0:
    228 
    229             Op->Asl.AmlOpcode = AML_ZERO_OP;
    230             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
    231                 Op, "Zero");
    232             return (1);
    233 
    234         case 1:
    235 
    236             Op->Asl.AmlOpcode = AML_ONE_OP;
    237             AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
    238                 Op, "One");
    239             return (1);
    240 
    241         case ACPI_UINT32_MAX:
    242 
    243             /* Check for table integer width (32 or 64) */
    244 
    245             if (AcpiGbl_IntegerByteWidth == 4)
    246             {
    247                 Op->Asl.AmlOpcode = AML_ONES_OP;
    248                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
    249                     Op, "Ones");
    250                 return (1);
    251             }
    252             break;
    253 
    254         case ACPI_UINT64_MAX:
    255 
    256             /* Check for table integer width (32 or 64) */
    257 
    258             if (AcpiGbl_IntegerByteWidth == 8)
    259             {
    260                 Op->Asl.AmlOpcode = AML_ONES_OP;
    261                 AslError (ASL_OPTIMIZATION, ASL_MSG_INTEGER_OPTIMIZATION,
    262                     Op, "Ones");
    263                 return (1);
    264             }
    265             break;
    266 
    267         default:
    268 
    269             break;
    270         }
    271     }
    272 
    273     /* Find the best fit using the various AML integer prefixes */
    274 
    275     if (Op->Asl.Value.Integer <= ACPI_UINT8_MAX)
    276     {
    277         Op->Asl.AmlOpcode = AML_BYTE_OP;
    278         return (1);
    279     }
    280 
    281     if (Op->Asl.Value.Integer <= ACPI_UINT16_MAX)
    282     {
    283         Op->Asl.AmlOpcode = AML_WORD_OP;
    284         return (2);
    285     }
    286 
    287     if (Op->Asl.Value.Integer <= ACPI_UINT32_MAX)
    288     {
    289         Op->Asl.AmlOpcode = AML_DWORD_OP;
    290         return (4);
    291     }
    292     else
    293     {
    294         if (AcpiGbl_IntegerByteWidth == 4)
    295         {
    296             AslError (ASL_WARNING, ASL_MSG_INTEGER_LENGTH,
    297                 Op, NULL);
    298 
    299             if (!Gbl_IgnoreErrors)
    300             {
    301                 /* Truncate the integer to 32-bit */
    302                 Op->Asl.AmlOpcode = AML_DWORD_OP;
    303                 return (4);
    304             }
    305         }
    306 
    307         Op->Asl.AmlOpcode = AML_QWORD_OP;
    308         return (8);
    309     }
    310 }
    311 
    312 
    313 /*******************************************************************************
    314  *
    315  * FUNCTION:    OpcDoAccessAs
    316  *
    317  * PARAMETERS:  Op        - Parse node
    318  *
    319  * RETURN:      None
    320  *
    321  * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
    322  *
    323  ******************************************************************************/
    324 
    325 static void
    326 OpcDoAccessAs (
    327     ACPI_PARSE_OBJECT       *Op)
    328 {
    329     ACPI_PARSE_OBJECT       *TypeOp;
    330     ACPI_PARSE_OBJECT       *AttribOp;
    331     ACPI_PARSE_OBJECT       *LengthOp;
    332     UINT8                   Attribute;
    333 
    334 
    335     Op->Asl.AmlOpcodeLength = 1;
    336     TypeOp = Op->Asl.Child;
    337 
    338     /* First child is the access type */
    339 
    340     TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    341     TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    342 
    343     /* Second child is the optional access attribute */
    344 
    345     AttribOp = TypeOp->Asl.Next;
    346     if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    347     {
    348         AttribOp->Asl.Value.Integer = 0;
    349     }
    350 
    351     AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    352     AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    353 
    354     /* Only a few AccessAttributes support AccessLength */
    355 
    356     Attribute = (UINT8) AttribOp->Asl.Value.Integer;
    357     if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
    358         (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
    359         (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
    360     {
    361         return;
    362     }
    363 
    364     Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
    365 
    366     /*
    367      * Child of Attributes is the AccessLength (required for Multibyte,
    368      * RawBytes, RawProcess.)
    369      */
    370     LengthOp = AttribOp->Asl.Child;
    371     if (!LengthOp)
    372     {
    373         return;
    374     }
    375 
    376     /* TBD: probably can remove */
    377 
    378     if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    379     {
    380         LengthOp->Asl.Value.Integer = 16;
    381     }
    382 
    383     LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    384     LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    385 }
    386 
    387 
    388 /*******************************************************************************
    389  *
    390  * FUNCTION:    OpcDoConnection
    391  *
    392  * PARAMETERS:  Op        - Parse node
    393  *
    394  * RETURN:      None
    395  *
    396  * DESCRIPTION: Implement the Connection ASL keyword.
    397  *
    398  ******************************************************************************/
    399 
    400 static void
    401 OpcDoConnection (
    402     ACPI_PARSE_OBJECT       *Op)
    403 {
    404     ASL_RESOURCE_NODE       *Rnode;
    405     ACPI_PARSE_OBJECT       *BufferOp;
    406     ACPI_PARSE_OBJECT       *BufferLengthOp;
    407     ACPI_PARSE_OBJECT       *BufferDataOp;
    408     ASL_RESOURCE_INFO       Info;
    409     UINT8                   State;
    410 
    411 
    412     Op->Asl.AmlOpcodeLength = 1;
    413 
    414     if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
    415     {
    416         return;
    417     }
    418 
    419     BufferOp = Op->Asl.Child;
    420     BufferLengthOp = BufferOp->Asl.Child;
    421     BufferDataOp = BufferLengthOp->Asl.Next;
    422 
    423     Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
    424     Info.CurrentByteOffset = 0;
    425     State = ACPI_RSTATE_NORMAL;
    426     Rnode = RsDoOneResourceDescriptor (&Info, &State);
    427     if (!Rnode)
    428     {
    429         return; /* error */
    430     }
    431 
    432     /*
    433      * Transform the nodes into the following
    434      *
    435      * Op           -> AML_BUFFER_OP
    436      * First Child  -> BufferLength
    437      * Second Child -> Descriptor Buffer (raw byte data)
    438      */
    439     BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
    440     BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
    441     BufferOp->Asl.CompileFlags = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
    442     UtSetParseOpName (BufferOp);
    443 
    444     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
    445     BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
    446     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
    447     UtSetParseOpName (BufferLengthOp);
    448 
    449     BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    450     BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
    451     BufferDataOp->Asl.AmlOpcodeLength = 0;
    452     BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
    453     BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
    454     UtSetParseOpName (BufferDataOp);
    455 }
    456 
    457 
    458 /*******************************************************************************
    459  *
    460  * FUNCTION:    OpcDoUnicode
    461  *
    462  * PARAMETERS:  Op        - Parse node
    463  *
    464  * RETURN:      None
    465  *
    466  * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
    467  *              to a unicode buffer. There is no Unicode AML opcode.
    468  *
    469  * Note:  The Unicode string is 16 bits per character, no leading signature,
    470  *        with a 16-bit terminating NULL.
    471  *
    472  ******************************************************************************/
    473 
    474 static void
    475 OpcDoUnicode (
    476     ACPI_PARSE_OBJECT       *Op)
    477 {
    478     ACPI_PARSE_OBJECT       *InitializerOp;
    479     UINT32                  Length;
    480     UINT32                  Count;
    481     UINT32                  i;
    482     UINT8                   *AsciiString;
    483     UINT16                  *UnicodeString;
    484     ACPI_PARSE_OBJECT       *BufferLengthOp;
    485 
    486 
    487     /* Change op into a buffer object */
    488 
    489     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    490     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    491     UtSetParseOpName (Op);
    492 
    493     /* Buffer Length is first, followed by the string */
    494 
    495     BufferLengthOp = Op->Asl.Child;
    496     InitializerOp = BufferLengthOp->Asl.Next;
    497 
    498     AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
    499 
    500     /* Create a new buffer for the Unicode string */
    501 
    502     Count = strlen (InitializerOp->Asl.Value.String) + 1;
    503     Length = Count * sizeof (UINT16);
    504     UnicodeString = UtLocalCalloc (Length);
    505 
    506     /* Convert to Unicode string (including null terminator) */
    507 
    508     for (i = 0; i < Count; i++)
    509     {
    510         UnicodeString[i] = (UINT16) AsciiString[i];
    511     }
    512 
    513     /*
    514      * Just set the buffer size node to be the buffer length, regardless
    515      * of whether it was previously an integer or a default_arg placeholder
    516      */
    517     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
    518     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
    519     BufferLengthOp->Asl.Value.Integer = Length;
    520     UtSetParseOpName (BufferLengthOp);
    521 
    522     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
    523 
    524     /* The Unicode string is a raw data buffer */
    525 
    526     InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
    527     InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    528     InitializerOp->Asl.AmlLength = Length;
    529     InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    530     InitializerOp->Asl.Child = NULL;
    531     UtSetParseOpName (InitializerOp);
    532 }
    533 
    534 
    535 /*******************************************************************************
    536  *
    537  * FUNCTION:    OpcDoEisaId
    538  *
    539  * PARAMETERS:  Op        - Parse node
    540  *
    541  * RETURN:      None
    542  *
    543  * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
    544  *              Pnp BIOS Specification for details. Here is an excerpt:
    545  *
    546  *              A seven character ASCII representation of the product
    547  *              identifier compressed into a 32-bit identifier. The seven
    548  *              character ID consists of a three character manufacturer code,
    549  *              a three character hexadecimal product identifier, and a one
    550  *              character hexadecimal revision number. The manufacturer code
    551  *              is a 3 uppercase character code that is compressed into 3 5-bit
    552  *              values as follows:
    553  *                  1) Find hex ASCII value for each letter
    554  *                  2) Subtract 40h from each ASCII value
    555  *                  3) Retain 5 least significant bits for each letter by
    556  *                     discarding upper 3 bits because they are always 0.
    557  *                  4) Compressed code = concatenate 0 and the 3 5-bit values
    558  *
    559  *              The format of the compressed product identifier is as follows:
    560  *              Byte 0: Bit 7       - Reserved (0)
    561  *                      Bits 6-2:   - 1st character of compressed mfg code
    562  *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
    563  *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
    564  *                      Bits 4-0    - 3rd character of mfg code
    565  *              Byte 2: Bits 7-4    - 1st hex digit of product number
    566  *                      Bits 3-0    - 2nd hex digit of product number
    567  *              Byte 3: Bits 7-4    - 3st hex digit of product number
    568  *                      Bits 3-0    - Hex digit of the revision number
    569  *
    570  ******************************************************************************/
    571 
    572 static void
    573 OpcDoEisaId (
    574     ACPI_PARSE_OBJECT       *Op)
    575 {
    576     UINT32                  EisaId = 0;
    577     UINT32                  BigEndianId;
    578     char                    *InString;
    579     ACPI_STATUS             Status = AE_OK;
    580     UINT32                  i;
    581 
    582 
    583     InString = (char *) Op->Asl.Value.String;
    584 
    585     /*
    586      * The EISAID string must be exactly 7 characters and of the form
    587      * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
    588      */
    589     if (strlen (InString) != 7)
    590     {
    591         Status = AE_BAD_PARAMETER;
    592     }
    593     else
    594     {
    595         /* Check all 7 characters for correct format */
    596 
    597         for (i = 0; i < 7; i++)
    598         {
    599             /* First 3 characters must be uppercase letters */
    600 
    601             if (i < 3)
    602             {
    603                 if (!isupper ((int) InString[i]))
    604                 {
    605                     Status = AE_BAD_PARAMETER;
    606                 }
    607             }
    608 
    609             /* Last 4 characters must be hex digits */
    610 
    611             else if (!isxdigit ((int) InString[i]))
    612             {
    613                 Status = AE_BAD_PARAMETER;
    614             }
    615         }
    616     }
    617 
    618     if (ACPI_FAILURE (Status))
    619     {
    620         AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
    621     }
    622     else
    623     {
    624         /* Create ID big-endian first (bits are contiguous) */
    625 
    626         BigEndianId =
    627             (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
    628             (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
    629             (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
    630 
    631             (AcpiUtAsciiCharToHex (InString[3])) << 12 |
    632             (AcpiUtAsciiCharToHex (InString[4])) << 8  |
    633             (AcpiUtAsciiCharToHex (InString[5])) << 4  |
    634              AcpiUtAsciiCharToHex (InString[6]);
    635 
    636         /* Swap to little-endian to get final ID (see function header) */
    637 
    638         EisaId = AcpiUtDwordByteSwap (BigEndianId);
    639     }
    640 
    641     /*
    642      * Morph the Op into an integer, regardless of whether there
    643      * was an error in the EISAID string
    644      */
    645     Op->Asl.Value.Integer = EisaId;
    646 
    647     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    648     Op->Asl.ParseOpcode = PARSEOP_INTEGER;
    649     (void) OpcSetOptimalIntegerSize (Op);
    650 
    651     /* Op is now an integer */
    652 
    653     UtSetParseOpName (Op);
    654 }
    655 
    656 
    657 /*******************************************************************************
    658  *
    659  * FUNCTION:    OpcDoUuId
    660  *
    661  * PARAMETERS:  Op                  - Parse node
    662  *
    663  * RETURN:      None
    664  *
    665  * DESCRIPTION: Convert UUID string to 16-byte buffer
    666  *
    667  ******************************************************************************/
    668 
    669 static void
    670 OpcDoUuId (
    671     ACPI_PARSE_OBJECT       *Op)
    672 {
    673     char                    *InString;
    674     UINT8                   *Buffer;
    675     ACPI_STATUS             Status = AE_OK;
    676     ACPI_PARSE_OBJECT       *NewOp;
    677 
    678 
    679     InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
    680     Buffer = UtLocalCalloc (16);
    681 
    682     Status = AuValidateUuid (InString);
    683     if (ACPI_FAILURE (Status))
    684     {
    685         AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
    686     }
    687     else
    688     {
    689         AcpiUtConvertStringToUuid (InString, Buffer);
    690     }
    691 
    692     /* Change Op to a Buffer */
    693 
    694     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    695     Op->Common.AmlOpcode = AML_BUFFER_OP;
    696 
    697     /* Disable further optimization */
    698 
    699     Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    700     UtSetParseOpName (Op);
    701 
    702     /* Child node is the buffer length */
    703 
    704     NewOp = TrAllocateNode (PARSEOP_INTEGER);
    705 
    706     NewOp->Asl.AmlOpcode = AML_BYTE_OP;
    707     NewOp->Asl.Value.Integer = 16;
    708     NewOp->Asl.Parent = Op;
    709 
    710     Op->Asl.Child = NewOp;
    711     Op = NewOp;
    712 
    713     /* Peer to the child is the raw buffer data */
    714 
    715     NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
    716     NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    717     NewOp->Asl.AmlLength = 16;
    718     NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
    719     NewOp->Asl.Parent = Op->Asl.Parent;
    720 
    721     Op->Asl.Next = NewOp;
    722 }
    723 
    724 
    725 /*******************************************************************************
    726  *
    727  * FUNCTION:    OpcGenerateAmlOpcode
    728  *
    729  * PARAMETERS:  Op                  - Parse node
    730  *
    731  * RETURN:      None
    732  *
    733  * DESCRIPTION: Generate the AML opcode associated with the node and its
    734  *              parse (lex/flex) keyword opcode. Essentially implements
    735  *              a mapping between the parse opcodes and the actual AML opcodes.
    736  *
    737  ******************************************************************************/
    738 
    739 void
    740 OpcGenerateAmlOpcode (
    741     ACPI_PARSE_OBJECT       *Op)
    742 {
    743     UINT16                  Index;
    744 
    745 
    746     Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
    747 
    748     Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
    749     Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
    750     Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
    751 
    752     if (!Op->Asl.Value.Integer)
    753     {
    754         Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
    755     }
    756 
    757     /* Special handling for some opcodes */
    758 
    759     switch (Op->Asl.ParseOpcode)
    760     {
    761     case PARSEOP_INTEGER:
    762         /*
    763          * Set the opcode based on the size of the integer
    764          */
    765         (void) OpcSetOptimalIntegerSize (Op);
    766         break;
    767 
    768     case PARSEOP_OFFSET:
    769 
    770         Op->Asl.AmlOpcodeLength = 1;
    771         break;
    772 
    773     case PARSEOP_ACCESSAS:
    774 
    775         OpcDoAccessAs (Op);
    776         break;
    777 
    778     case PARSEOP_CONNECTION:
    779 
    780         OpcDoConnection (Op);
    781         break;
    782 
    783     case PARSEOP_EISAID:
    784 
    785         OpcDoEisaId (Op);
    786         break;
    787 
    788     case PARSEOP_PRINTF:
    789 
    790         OpcDoPrintf (Op);
    791         break;
    792 
    793     case PARSEOP_FPRINTF:
    794 
    795         OpcDoFprintf (Op);
    796         break;
    797 
    798     case PARSEOP_TOPLD:
    799 
    800         OpcDoPld (Op);
    801         break;
    802 
    803     case PARSEOP_TOUUID:
    804 
    805         OpcDoUuId (Op);
    806         break;
    807 
    808     case PARSEOP_UNICODE:
    809 
    810         OpcDoUnicode (Op);
    811         break;
    812 
    813     case PARSEOP_INCLUDE:
    814 
    815         Gbl_HasIncludeFiles = TRUE;
    816         break;
    817 
    818     case PARSEOP_EXTERNAL:
    819 
    820         if (Gbl_DoExternals == FALSE)
    821         {
    822             Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    823             Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    824         }
    825         break;
    826 
    827     case PARSEOP_TIMER:
    828 
    829         if (AcpiGbl_IntegerBitWidth == 32)
    830         {
    831             AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
    832         }
    833         break;
    834 
    835     default:
    836 
    837         /* Nothing to do for other opcodes */
    838 
    839         break;
    840     }
    841 
    842     return;
    843 }
    844