Home | History | Annotate | Line # | Download | only in compiler
aslopcodes.c revision 1.8
      1 /******************************************************************************
      2  *
      3  * Module Name: aslopcode - AML opcode generation
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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 /* 64-bit integer */
    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 
    303                 Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
    304 
    305                 /* Now set the optimal integer size */
    306 
    307                 return (OpcSetOptimalIntegerSize (Op));
    308             }
    309         }
    310 
    311         Op->Asl.AmlOpcode = AML_QWORD_OP;
    312         return (8);
    313     }
    314 }
    315 
    316 
    317 /*******************************************************************************
    318  *
    319  * FUNCTION:    OpcDoAccessAs
    320  *
    321  * PARAMETERS:  Op        - Parse node
    322  *
    323  * RETURN:      None
    324  *
    325  * DESCRIPTION: Implement the ACCESS_AS ASL keyword.
    326  *
    327  ******************************************************************************/
    328 
    329 static void
    330 OpcDoAccessAs (
    331     ACPI_PARSE_OBJECT       *Op)
    332 {
    333     ACPI_PARSE_OBJECT       *TypeOp;
    334     ACPI_PARSE_OBJECT       *AttribOp;
    335     ACPI_PARSE_OBJECT       *LengthOp;
    336     UINT8                   Attribute;
    337 
    338 
    339     Op->Asl.AmlOpcodeLength = 1;
    340     TypeOp = Op->Asl.Child;
    341 
    342     /* First child is the access type */
    343 
    344     TypeOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    345     TypeOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    346 
    347     /* Second child is the optional access attribute */
    348 
    349     AttribOp = TypeOp->Asl.Next;
    350     if (AttribOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    351     {
    352         AttribOp->Asl.Value.Integer = 0;
    353     }
    354 
    355     AttribOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    356     AttribOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    357 
    358     /* Only a few AccessAttributes support AccessLength */
    359 
    360     Attribute = (UINT8) AttribOp->Asl.Value.Integer;
    361     if ((Attribute != AML_FIELD_ATTRIB_MULTIBYTE) &&
    362         (Attribute != AML_FIELD_ATTRIB_RAW_BYTES) &&
    363         (Attribute != AML_FIELD_ATTRIB_RAW_PROCESS))
    364     {
    365         return;
    366     }
    367 
    368     Op->Asl.AmlOpcode = AML_FIELD_EXT_ACCESS_OP;
    369 
    370     /*
    371      * Child of Attributes is the AccessLength (required for Multibyte,
    372      * RawBytes, RawProcess.)
    373      */
    374     LengthOp = AttribOp->Asl.Child;
    375     if (!LengthOp)
    376     {
    377         return;
    378     }
    379 
    380     /* TBD: probably can remove */
    381 
    382     if (LengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    383     {
    384         LengthOp->Asl.Value.Integer = 16;
    385     }
    386 
    387     LengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    388     LengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    389 }
    390 
    391 
    392 /*******************************************************************************
    393  *
    394  * FUNCTION:    OpcDoConnection
    395  *
    396  * PARAMETERS:  Op        - Parse node
    397  *
    398  * RETURN:      None
    399  *
    400  * DESCRIPTION: Implement the Connection ASL keyword.
    401  *
    402  ******************************************************************************/
    403 
    404 static void
    405 OpcDoConnection (
    406     ACPI_PARSE_OBJECT       *Op)
    407 {
    408     ASL_RESOURCE_NODE       *Rnode;
    409     ACPI_PARSE_OBJECT       *BufferOp;
    410     ACPI_PARSE_OBJECT       *BufferLengthOp;
    411     ACPI_PARSE_OBJECT       *BufferDataOp;
    412     ASL_RESOURCE_INFO       Info;
    413     UINT8                   State;
    414 
    415 
    416     Op->Asl.AmlOpcodeLength = 1;
    417 
    418     if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
    419     {
    420         return;
    421     }
    422 
    423     BufferOp = Op->Asl.Child;
    424     BufferLengthOp = BufferOp->Asl.Child;
    425     BufferDataOp = BufferLengthOp->Asl.Next;
    426 
    427     Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
    428     Info.CurrentByteOffset = 0;
    429     State = ACPI_RSTATE_NORMAL;
    430     Rnode = RsDoOneResourceDescriptor (&Info, &State);
    431     if (!Rnode)
    432     {
    433         return; /* error */
    434     }
    435 
    436     /*
    437      * Transform the nodes into the following
    438      *
    439      * Op           -> AML_BUFFER_OP
    440      * First Child  -> BufferLength
    441      * Second Child -> Descriptor Buffer (raw byte data)
    442      */
    443     BufferOp->Asl.ParseOpcode = PARSEOP_BUFFER;
    444     BufferOp->Asl.AmlOpcode = AML_BUFFER_OP;
    445     BufferOp->Asl.CompileFlags = OP_AML_PACKAGE | OP_IS_RESOURCE_DESC;
    446     UtSetParseOpName (BufferOp);
    447 
    448     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
    449     BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
    450     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
    451     UtSetParseOpName (BufferLengthOp);
    452 
    453     BufferDataOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    454     BufferDataOp->Asl.AmlOpcode = AML_RAW_DATA_CHAIN;
    455     BufferDataOp->Asl.AmlOpcodeLength = 0;
    456     BufferDataOp->Asl.AmlLength = Rnode->BufferLength;
    457     BufferDataOp->Asl.Value.Buffer = (UINT8 *) Rnode;
    458     UtSetParseOpName (BufferDataOp);
    459 }
    460 
    461 
    462 /*******************************************************************************
    463  *
    464  * FUNCTION:    OpcDoUnicode
    465  *
    466  * PARAMETERS:  Op        - Parse node
    467  *
    468  * RETURN:      None
    469  *
    470  * DESCRIPTION: Implement the UNICODE ASL "macro".  Convert the input string
    471  *              to a unicode buffer. There is no Unicode AML opcode.
    472  *
    473  * Note:  The Unicode string is 16 bits per character, no leading signature,
    474  *        with a 16-bit terminating NULL.
    475  *
    476  ******************************************************************************/
    477 
    478 static void
    479 OpcDoUnicode (
    480     ACPI_PARSE_OBJECT       *Op)
    481 {
    482     ACPI_PARSE_OBJECT       *InitializerOp;
    483     UINT32                  Length;
    484     UINT32                  Count;
    485     UINT32                  i;
    486     UINT8                   *AsciiString;
    487     UINT16                  *UnicodeString;
    488     ACPI_PARSE_OBJECT       *BufferLengthOp;
    489 
    490 
    491     /* Change op into a buffer object */
    492 
    493     Op->Asl.CompileFlags &= ~OP_COMPILE_TIME_CONST;
    494     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    495     UtSetParseOpName (Op);
    496 
    497     /* Buffer Length is first, followed by the string */
    498 
    499     BufferLengthOp = Op->Asl.Child;
    500     InitializerOp = BufferLengthOp->Asl.Next;
    501 
    502     AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;
    503 
    504     /* Create a new buffer for the Unicode string */
    505 
    506     Count = strlen (InitializerOp->Asl.Value.String) + 1;
    507     Length = Count * sizeof (UINT16);
    508     UnicodeString = UtLocalCalloc (Length);
    509 
    510     /* Convert to Unicode string (including null terminator) */
    511 
    512     for (i = 0; i < Count; i++)
    513     {
    514         UnicodeString[i] = (UINT16) AsciiString[i];
    515     }
    516 
    517     /*
    518      * Just set the buffer size node to be the buffer length, regardless
    519      * of whether it was previously an integer or a default_arg placeholder
    520      */
    521     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
    522     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
    523     BufferLengthOp->Asl.Value.Integer = Length;
    524     UtSetParseOpName (BufferLengthOp);
    525 
    526     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
    527 
    528     /* The Unicode string is a raw data buffer */
    529 
    530     InitializerOp->Asl.Value.Buffer = (UINT8 *) UnicodeString;
    531     InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    532     InitializerOp->Asl.AmlLength = Length;
    533     InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    534     InitializerOp->Asl.Child = NULL;
    535     UtSetParseOpName (InitializerOp);
    536 }
    537 
    538 
    539 /*******************************************************************************
    540  *
    541  * FUNCTION:    OpcDoEisaId
    542  *
    543  * PARAMETERS:  Op        - Parse node
    544  *
    545  * RETURN:      None
    546  *
    547  * DESCRIPTION: Convert a string EISA ID to numeric representation. See the
    548  *              Pnp BIOS Specification for details. Here is an excerpt:
    549  *
    550  *              A seven character ASCII representation of the product
    551  *              identifier compressed into a 32-bit identifier. The seven
    552  *              character ID consists of a three character manufacturer code,
    553  *              a three character hexadecimal product identifier, and a one
    554  *              character hexadecimal revision number. The manufacturer code
    555  *              is a 3 uppercase character code that is compressed into 3 5-bit
    556  *              values as follows:
    557  *                  1) Find hex ASCII value for each letter
    558  *                  2) Subtract 40h from each ASCII value
    559  *                  3) Retain 5 least significant bits for each letter by
    560  *                     discarding upper 3 bits because they are always 0.
    561  *                  4) Compressed code = concatenate 0 and the 3 5-bit values
    562  *
    563  *              The format of the compressed product identifier is as follows:
    564  *              Byte 0: Bit 7       - Reserved (0)
    565  *                      Bits 6-2:   - 1st character of compressed mfg code
    566  *                      Bits 1-0    - Upper 2 bits of 2nd character of mfg code
    567  *              Byte 1: Bits 7-5    - Lower 3 bits of 2nd character of mfg code
    568  *                      Bits 4-0    - 3rd character of mfg code
    569  *              Byte 2: Bits 7-4    - 1st hex digit of product number
    570  *                      Bits 3-0    - 2nd hex digit of product number
    571  *              Byte 3: Bits 7-4    - 3st hex digit of product number
    572  *                      Bits 3-0    - Hex digit of the revision number
    573  *
    574  ******************************************************************************/
    575 
    576 static void
    577 OpcDoEisaId (
    578     ACPI_PARSE_OBJECT       *Op)
    579 {
    580     UINT32                  EisaId = 0;
    581     UINT32                  BigEndianId;
    582     char                    *InString;
    583     ACPI_STATUS             Status = AE_OK;
    584     UINT32                  i;
    585 
    586 
    587     InString = (char *) Op->Asl.Value.String;
    588 
    589     /*
    590      * The EISAID string must be exactly 7 characters and of the form
    591      * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
    592      */
    593     if (strlen (InString) != 7)
    594     {
    595         Status = AE_BAD_PARAMETER;
    596     }
    597     else
    598     {
    599         /* Check all 7 characters for correct format */
    600 
    601         for (i = 0; i < 7; i++)
    602         {
    603             /* First 3 characters must be uppercase letters */
    604 
    605             if (i < 3)
    606             {
    607                 if (!isupper ((int) InString[i]))
    608                 {
    609                     Status = AE_BAD_PARAMETER;
    610                 }
    611             }
    612 
    613             /* Last 4 characters must be hex digits */
    614 
    615             else if (!isxdigit ((int) InString[i]))
    616             {
    617                 Status = AE_BAD_PARAMETER;
    618             }
    619         }
    620     }
    621 
    622     if (ACPI_FAILURE (Status))
    623     {
    624         AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
    625     }
    626     else
    627     {
    628         /* Create ID big-endian first (bits are contiguous) */
    629 
    630         BigEndianId =
    631             (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
    632             (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
    633             (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |
    634 
    635             (AcpiUtAsciiCharToHex (InString[3])) << 12 |
    636             (AcpiUtAsciiCharToHex (InString[4])) << 8  |
    637             (AcpiUtAsciiCharToHex (InString[5])) << 4  |
    638              AcpiUtAsciiCharToHex (InString[6]);
    639 
    640         /* Swap to little-endian to get final ID (see function header) */
    641 
    642         EisaId = AcpiUtDwordByteSwap (BigEndianId);
    643     }
    644 
    645     /*
    646      * Morph the Op into an integer, regardless of whether there
    647      * was an error in the EISAID string
    648      */
    649     Op->Asl.Value.Integer = EisaId;
    650 
    651     Op->Asl.CompileFlags &= ~OP_COMPILE_TIME_CONST;
    652     Op->Asl.ParseOpcode = PARSEOP_INTEGER;
    653     (void) OpcSetOptimalIntegerSize (Op);
    654 
    655     /* Op is now an integer */
    656 
    657     UtSetParseOpName (Op);
    658 }
    659 
    660 
    661 /*******************************************************************************
    662  *
    663  * FUNCTION:    OpcDoUuId
    664  *
    665  * PARAMETERS:  Op                  - Parse node
    666  *
    667  * RETURN:      None
    668  *
    669  * DESCRIPTION: Convert UUID string to 16-byte buffer
    670  *
    671  ******************************************************************************/
    672 
    673 static void
    674 OpcDoUuId (
    675     ACPI_PARSE_OBJECT       *Op)
    676 {
    677     char                    *InString;
    678     UINT8                   *Buffer;
    679     ACPI_STATUS             Status = AE_OK;
    680     ACPI_PARSE_OBJECT       *NewOp;
    681 
    682 
    683     InString = ACPI_CAST_PTR (char, Op->Asl.Value.String);
    684     Buffer = UtLocalCalloc (16);
    685 
    686     Status = AuValidateUuid (InString);
    687     if (ACPI_FAILURE (Status))
    688     {
    689         AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
    690     }
    691     else
    692     {
    693         AcpiUtConvertStringToUuid (InString, Buffer);
    694     }
    695 
    696     /* Change Op to a Buffer */
    697 
    698     Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    699     Op->Common.AmlOpcode = AML_BUFFER_OP;
    700 
    701     /* Disable further optimization */
    702 
    703     Op->Asl.CompileFlags &= ~OP_COMPILE_TIME_CONST;
    704     UtSetParseOpName (Op);
    705 
    706     /* Child node is the buffer length */
    707 
    708     NewOp = TrAllocateOp (PARSEOP_INTEGER);
    709 
    710     NewOp->Asl.AmlOpcode = AML_BYTE_OP;
    711     NewOp->Asl.Value.Integer = 16;
    712     NewOp->Asl.Parent = Op;
    713 
    714     Op->Asl.Child = NewOp;
    715     Op = NewOp;
    716 
    717     /* Peer to the child is the raw buffer data */
    718 
    719     NewOp = TrAllocateOp (PARSEOP_RAW_DATA);
    720     NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    721     NewOp->Asl.AmlLength = 16;
    722     NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer);
    723     NewOp->Asl.Parent = Op->Asl.Parent;
    724 
    725     Op->Asl.Next = NewOp;
    726 }
    727 
    728 
    729 /*******************************************************************************
    730  *
    731  * FUNCTION:    OpcGenerateAmlOpcode
    732  *
    733  * PARAMETERS:  Op                  - Parse node
    734  *
    735  * RETURN:      None
    736  *
    737  * DESCRIPTION: Generate the AML opcode associated with the node and its
    738  *              parse (lex/flex) keyword opcode. Essentially implements
    739  *              a mapping between the parse opcodes and the actual AML opcodes.
    740  *
    741  ******************************************************************************/
    742 
    743 void
    744 OpcGenerateAmlOpcode (
    745     ACPI_PARSE_OBJECT       *Op)
    746 {
    747     UINT16                  Index;
    748 
    749 
    750     Index = (UINT16) (Op->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
    751 
    752     Op->Asl.AmlOpcode     = AslKeywordMapping[Index].AmlOpcode;
    753     Op->Asl.AcpiBtype     = AslKeywordMapping[Index].AcpiBtype;
    754     Op->Asl.CompileFlags |= AslKeywordMapping[Index].Flags;
    755 
    756     if (!Op->Asl.Value.Integer)
    757     {
    758         Op->Asl.Value.Integer = AslKeywordMapping[Index].Value;
    759     }
    760 
    761     /* Special handling for some opcodes */
    762 
    763     switch (Op->Asl.ParseOpcode)
    764     {
    765     case PARSEOP_INTEGER:
    766         /*
    767          * Set the opcode based on the size of the integer
    768          */
    769         (void) OpcSetOptimalIntegerSize (Op);
    770         break;
    771 
    772     case PARSEOP_OFFSET:
    773 
    774         Op->Asl.AmlOpcodeLength = 1;
    775         break;
    776 
    777     case PARSEOP_ACCESSAS:
    778 
    779         OpcDoAccessAs (Op);
    780         break;
    781 
    782     case PARSEOP_CONNECTION:
    783 
    784         OpcDoConnection (Op);
    785         break;
    786 
    787     case PARSEOP_EISAID:
    788 
    789         OpcDoEisaId (Op);
    790         break;
    791 
    792     case PARSEOP_PRINTF:
    793 
    794         OpcDoPrintf (Op);
    795         break;
    796 
    797     case PARSEOP_FPRINTF:
    798 
    799         OpcDoFprintf (Op);
    800         break;
    801 
    802     case PARSEOP_TOPLD:
    803 
    804         OpcDoPld (Op);
    805         break;
    806 
    807     case PARSEOP_TOUUID:
    808 
    809         OpcDoUuId (Op);
    810         break;
    811 
    812     case PARSEOP_UNICODE:
    813 
    814         OpcDoUnicode (Op);
    815         break;
    816 
    817     case PARSEOP_INCLUDE:
    818 
    819         Gbl_HasIncludeFiles = TRUE;
    820         break;
    821 
    822     case PARSEOP_EXTERNAL:
    823 
    824         if (Gbl_DoExternals == FALSE)
    825         {
    826             Op->Asl.Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    827             Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    828         }
    829         break;
    830 
    831     case PARSEOP_TIMER:
    832 
    833         if (AcpiGbl_IntegerBitWidth == 32)
    834         {
    835             AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
    836         }
    837         break;
    838 
    839     default:
    840 
    841         /* Nothing to do for other opcodes */
    842 
    843         break;
    844     }
    845 
    846     return;
    847 }
    848