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