Home | History | Annotate | Line # | Download | only in compiler
asloperands.c revision 1.1.1.17
      1 /******************************************************************************
      2  *
      3  * Module Name: asloperands - AML operand processing
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2019, 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    ("asloperands")
     50 
     51 /* Local prototypes */
     52 
     53 static void
     54 OpnDoField (
     55     ACPI_PARSE_OBJECT       *Op);
     56 
     57 static void
     58 OpnDoBankField (
     59     ACPI_PARSE_OBJECT       *Op);
     60 
     61 static void
     62 OpnDoBuffer (
     63     ACPI_PARSE_OBJECT       *Op);
     64 
     65 static void
     66 OpnDoDefinitionBlock (
     67     ACPI_PARSE_OBJECT       *Op);
     68 
     69 static void
     70 OpnDoFieldCommon (
     71     ACPI_PARSE_OBJECT       *FieldOp,
     72     ACPI_PARSE_OBJECT       *Op);
     73 
     74 static void
     75 OpnDoIndexField (
     76     ACPI_PARSE_OBJECT       *Op);
     77 
     78 static void
     79 OpnDoLoadTable (
     80     ACPI_PARSE_OBJECT       *Op);
     81 
     82 static void
     83 OpnDoMethod (
     84     ACPI_PARSE_OBJECT       *Op);
     85 
     86 static void
     87 OpnDoMutex (
     88     ACPI_PARSE_OBJECT       *Op);
     89 
     90 static void
     91 OpnDoRegion (
     92     ACPI_PARSE_OBJECT       *Op);
     93 
     94 static void
     95 OpnAttachNameToNode (
     96     ACPI_PARSE_OBJECT       *Op);
     97 
     98 
     99 /*******************************************************************************
    100  *
    101  * FUNCTION:    OpnDoMutex
    102  *
    103  * PARAMETERS:  Op        - The parent parse node
    104  *
    105  * RETURN:      None
    106  *
    107  * DESCRIPTION: Construct the operands for the MUTEX ASL keyword.
    108  *
    109  ******************************************************************************/
    110 
    111 static void
    112 OpnDoMutex (
    113     ACPI_PARSE_OBJECT       *Op)
    114 {
    115     ACPI_PARSE_OBJECT       *Next;
    116 
    117 
    118     Next = Op->Asl.Child;
    119     Next = Next->Asl.Next;
    120 
    121     if (Next->Asl.Value.Integer > 15)
    122     {
    123         AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
    124     }
    125     return;
    126 }
    127 
    128 
    129 /*******************************************************************************
    130  *
    131  * FUNCTION:    OpnDoMethod
    132  *
    133  * PARAMETERS:  Op        - The parent parse node
    134  *
    135  * RETURN:      None
    136  *
    137  * DESCRIPTION: Construct the operands for the METHOD ASL keyword.
    138  *
    139  ******************************************************************************/
    140 
    141 static void
    142 OpnDoMethod (
    143     ACPI_PARSE_OBJECT       *Op)
    144 {
    145     ACPI_PARSE_OBJECT       *Next;
    146 
    147     /* Optional arguments for this opcode with defaults */
    148 
    149     UINT8                   NumArgs = 0;
    150     UINT8                   Serialized = 0;
    151     UINT8                   Concurrency = 0;
    152     UINT8                   MethodFlags;
    153 
    154 
    155     /* Opcode and package length first */
    156     /* Method name */
    157 
    158     Next = Op->Asl.Child;
    159 
    160     /* Num args */
    161 
    162     Next = Next->Asl.Next;
    163     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    164     {
    165         NumArgs = (UINT8) Next->Asl.Value.Integer;
    166         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    167     }
    168 
    169     /* Serialized Flag */
    170 
    171     Next = Next->Asl.Next;
    172     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    173     {
    174         Serialized = (UINT8) Next->Asl.Value.Integer;
    175         Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    176     }
    177 
    178     /* Concurrency value (valid values are 0-15) */
    179 
    180     Next = Next->Asl.Next;
    181     if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    182     {
    183         /* This is a ByteConstExpr, so eval the constant now */
    184 
    185         OpcAmlConstantWalk (Next, 0, NULL);
    186 
    187         if (Next->Asl.Value.Integer > 15)
    188         {
    189             AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL);
    190         }
    191 
    192         Concurrency = (UINT8) Next->Asl.Value.Integer;
    193     }
    194 
    195     /* Put the bits in their proper places */
    196 
    197     MethodFlags = (UINT8)
    198         ((NumArgs & 0x7) |
    199         ((Serialized & 0x1) << 3) |
    200         ((Concurrency & 0xF) << 4));
    201 
    202     /* Use the last node for the combined flags byte */
    203 
    204     Next->Asl.Value.Integer = MethodFlags;
    205     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    206     Next->Asl.AmlLength = 1;
    207     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    208 
    209     /* Save the arg count in the first node */
    210 
    211     Op->Asl.Extra = NumArgs;
    212 }
    213 
    214 
    215 /*******************************************************************************
    216  *
    217  * FUNCTION:    OpnDoFieldCommon
    218  *
    219  * PARAMETERS:  FieldOp       - Node for an ASL field
    220  *              Op            - The parent parse node
    221  *
    222  * RETURN:      None
    223  *
    224  * DESCRIPTION: Construct the AML operands for the various field keywords,
    225  *              FIELD, BANKFIELD, INDEXFIELD
    226  *
    227  ******************************************************************************/
    228 
    229 static void
    230 OpnDoFieldCommon (
    231     ACPI_PARSE_OBJECT       *FieldOp,
    232     ACPI_PARSE_OBJECT       *Op)
    233 {
    234     ACPI_PARSE_OBJECT       *Next;
    235     ACPI_PARSE_OBJECT       *PkgLengthNode;
    236     UINT32                  CurrentBitOffset;
    237     UINT32                  NewBitOffset;
    238     UINT8                   AccessType;
    239     UINT8                   LockRule;
    240     UINT8                   UpdateRule;
    241     UINT8                   FieldFlags;
    242     UINT32                  MinimumLength;
    243 
    244 
    245     /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
    246 
    247     AccessType = (UINT8) Op->Asl.Value.Integer;
    248     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    249 
    250     /* Set the access type in the parent (field) node for use later */
    251 
    252     FieldOp->Asl.Value.Integer = AccessType;
    253 
    254     /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
    255 
    256     Next = Op->Asl.Next;
    257     LockRule = (UINT8) Next->Asl.Value.Integer;
    258     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    259 
    260     /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
    261 
    262     Next = Next->Asl.Next;
    263     UpdateRule = (UINT8) Next->Asl.Value.Integer;
    264 
    265     /*
    266      * Generate the flags byte. The various fields are already
    267      * in the right bit position via translation from the
    268      * keywords by the parser.
    269      */
    270     FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
    271 
    272     /* Use the previous node to be the FieldFlags node */
    273 
    274     /* Set the node to RAW_DATA */
    275 
    276     Next->Asl.Value.Integer = FieldFlags;
    277     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    278     Next->Asl.AmlLength = 1;
    279     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    280 
    281     /* Process the FieldUnitList */
    282 
    283     Next = Next->Asl.Next;
    284     CurrentBitOffset = 0;
    285 
    286     while (Next)
    287     {
    288         /* Save the offset of this field unit */
    289 
    290         Next->Asl.ExtraValue = CurrentBitOffset;
    291 
    292         switch (Next->Asl.ParseOpcode)
    293         {
    294         case PARSEOP_ACCESSAS:
    295 
    296             PkgLengthNode = Next->Asl.Child;
    297             AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
    298 
    299             /* Nothing additional to do */
    300             break;
    301 
    302         case PARSEOP_OFFSET:
    303 
    304             /* New offset into the field */
    305 
    306             PkgLengthNode = Next->Asl.Child;
    307             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
    308 
    309             /*
    310              * Examine the specified offset in relation to the
    311              * current offset counter.
    312              */
    313             if (NewBitOffset < CurrentBitOffset)
    314             {
    315                 /*
    316                  * Not allowed to specify a backwards offset!
    317                  * Issue error and ignore this node.
    318                  */
    319                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
    320                     NULL);
    321                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    322                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    323             }
    324             else if (NewBitOffset == CurrentBitOffset)
    325             {
    326                 /*
    327                  * This Offset() operator is redundant and not needed,
    328                  * because the offset value is the same as the current
    329                  * offset.
    330                  */
    331                 AslError (ASL_REMARK, ASL_MSG_OFFSET, PkgLengthNode, NULL);
    332 
    333                 if (AslGbl_OptimizeTrivialParseNodes)
    334                 {
    335                     /*
    336                      * Optimize this Offset() operator by removing/ignoring
    337                      * it. Set the related nodes to default.
    338                      */
    339                     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    340                     PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    341 
    342                     AslError (ASL_OPTIMIZATION, ASL_MSG_OFFSET, PkgLengthNode,
    343                         "Optimizer has removed statement");
    344                 }
    345                 else
    346                 {
    347                     /* Optimization is disabled, treat as a valid Offset */
    348 
    349                     PkgLengthNode->Asl.Value.Integer =
    350                         NewBitOffset - CurrentBitOffset;
    351                     CurrentBitOffset = NewBitOffset;
    352                 }
    353             }
    354             else
    355             {
    356                 /*
    357                  * Valid new offset - set the value to be inserted into the AML
    358                  * and update the offset counter.
    359                  */
    360                 PkgLengthNode->Asl.Value.Integer =
    361                     NewBitOffset - CurrentBitOffset;
    362                 CurrentBitOffset = NewBitOffset;
    363             }
    364             break;
    365 
    366         case PARSEOP_NAMESEG:
    367         case PARSEOP_RESERVED_BYTES:
    368 
    369             /* Named or reserved field entry */
    370 
    371             PkgLengthNode = Next->Asl.Child;
    372             NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer;
    373             CurrentBitOffset += NewBitOffset;
    374 
    375             if ((NewBitOffset == 0) &&
    376                 (Next->Asl.ParseOpcode == PARSEOP_RESERVED_BYTES) &&
    377                 AslGbl_OptimizeTrivialParseNodes)
    378             {
    379                 /*
    380                  * Unnamed field with a bit length of zero. We can
    381                  * safely just ignore this. However, we will not ignore
    382                  * a named field of zero length, we don't want to just
    383                  * toss out a name.
    384                  */
    385                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    386                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    387                 break;
    388             }
    389 
    390             /* Save the current AccessAs value for error checking later */
    391 
    392             switch (AccessType)
    393             {
    394                 case AML_FIELD_ACCESS_ANY:
    395                 case AML_FIELD_ACCESS_BYTE:
    396                 case AML_FIELD_ACCESS_BUFFER:
    397                 default:
    398 
    399                     MinimumLength = 8;
    400                     break;
    401 
    402                 case AML_FIELD_ACCESS_WORD:
    403                     MinimumLength = 16;
    404                     break;
    405 
    406                 case AML_FIELD_ACCESS_DWORD:
    407                     MinimumLength = 32;
    408                     break;
    409 
    410                 case AML_FIELD_ACCESS_QWORD:
    411                     MinimumLength = 64;
    412                     break;
    413             }
    414 
    415             PkgLengthNode->Asl.ExtraValue = MinimumLength;
    416             break;
    417 
    418         default:
    419 
    420             /* All supported field opcodes must appear above */
    421 
    422             break;
    423         }
    424 
    425         /* Move on to next entry in the field list */
    426 
    427         Next = Next->Asl.Next;
    428     }
    429 }
    430 
    431 
    432 /*******************************************************************************
    433  *
    434  * FUNCTION:    OpnDoField
    435  *
    436  * PARAMETERS:  Op        - The parent parse node
    437  *
    438  * RETURN:      None
    439  *
    440  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
    441  *
    442  ******************************************************************************/
    443 
    444 static void
    445 OpnDoField (
    446     ACPI_PARSE_OBJECT       *Op)
    447 {
    448     ACPI_PARSE_OBJECT       *Next;
    449 
    450 
    451     /* Opcode is parent node */
    452     /* First child is field name */
    453 
    454     Next = Op->Asl.Child;
    455 
    456     /* Second child is the AccessType */
    457 
    458     OpnDoFieldCommon (Op, Next->Asl.Next);
    459 }
    460 
    461 
    462 /*******************************************************************************
    463  *
    464  * FUNCTION:    OpnDoIndexField
    465  *
    466  * PARAMETERS:  Op        - The parent parse node
    467  *
    468  * RETURN:      None
    469  *
    470  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
    471  *
    472  ******************************************************************************/
    473 
    474 static void
    475 OpnDoIndexField (
    476     ACPI_PARSE_OBJECT       *Op)
    477 {
    478     ACPI_PARSE_OBJECT       *Next;
    479 
    480 
    481     /* Opcode is parent node */
    482     /* First child is the index name */
    483 
    484     Next = Op->Asl.Child;
    485 
    486     /* Second child is the data name */
    487 
    488     Next = Next->Asl.Next;
    489 
    490     /* Third child is the AccessType */
    491 
    492     OpnDoFieldCommon (Op, Next->Asl.Next);
    493 }
    494 
    495 
    496 /*******************************************************************************
    497  *
    498  * FUNCTION:    OpnDoBankField
    499  *
    500  * PARAMETERS:  Op        - The parent parse node
    501  *
    502  * RETURN:      None
    503  *
    504  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
    505  *
    506  ******************************************************************************/
    507 
    508 static void
    509 OpnDoBankField (
    510     ACPI_PARSE_OBJECT       *Op)
    511 {
    512     ACPI_PARSE_OBJECT       *Next;
    513 
    514 
    515     /* Opcode is parent node */
    516     /* First child is the region name */
    517 
    518     Next = Op->Asl.Child;
    519 
    520     /* Second child is the bank name */
    521 
    522     Next = Next->Asl.Next;
    523 
    524     /* Third child is the bank value */
    525 
    526     Next = Next->Asl.Next;
    527 
    528     /* Fourth child is the AccessType */
    529 
    530     OpnDoFieldCommon (Op, Next->Asl.Next);
    531 }
    532 
    533 
    534 /*******************************************************************************
    535  *
    536  * FUNCTION:    OpnDoRegion
    537  *
    538  * PARAMETERS:  Op        - The parent parse node
    539  *
    540  * RETURN:      None
    541  *
    542  * DESCRIPTION: Tries to get the length of the region. Can only do this at
    543  *              compile time if the length is a constant.
    544  *
    545  ******************************************************************************/
    546 
    547 static void
    548 OpnDoRegion (
    549     ACPI_PARSE_OBJECT       *Op)
    550 {
    551     ACPI_PARSE_OBJECT       *Next;
    552     ACPI_ADR_SPACE_TYPE     SpaceId;
    553 
    554 
    555     /* Opcode is parent node */
    556     /* First child is the region name */
    557 
    558     Next = Op->Asl.Child;
    559 
    560     /* Second child is the space ID */
    561 
    562     Next = Next->Asl.Next;
    563     SpaceId = (ACPI_ADR_SPACE_TYPE) Next->Common.Value.Integer;
    564 
    565     /* Third child is the region offset */
    566 
    567     Next = Next->Asl.Next;
    568 
    569     /* Fourth child is the region length */
    570 
    571     Next = Next->Asl.Next;
    572     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
    573     {
    574         /* Check for zero length */
    575 
    576         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
    577         if (!Op->Asl.Value.Integer && (SpaceId < ACPI_NUM_PREDEFINED_REGIONS))
    578         {
    579             AslError (ASL_ERROR, ASL_MSG_REGION_LENGTH, Op, NULL);
    580         }
    581     }
    582     else
    583     {
    584         Op->Asl.Value.Integer = ACPI_UINT64_MAX;
    585     }
    586 }
    587 
    588 
    589 /*******************************************************************************
    590  *
    591  * FUNCTION:    OpnDoBuffer
    592  *
    593  * PARAMETERS:  Op        - The parent parse node
    594  *
    595  * RETURN:      None
    596  *
    597  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
    598  *              build a single raw byte buffer from the initialization nodes,
    599  *              each parse node contains a buffer byte.
    600  *
    601  ******************************************************************************/
    602 
    603 static void
    604 OpnDoBuffer (
    605     ACPI_PARSE_OBJECT       *Op)
    606 {
    607     ACPI_PARSE_OBJECT       *InitializerOp;
    608     ACPI_PARSE_OBJECT       *BufferLengthOp;
    609 
    610     /* Optional arguments for this opcode with defaults */
    611 
    612     UINT32                  BufferLength = 0;
    613 
    614 
    615     /* Opcode and package length first */
    616     /* Buffer Length is next, followed by the initializer list */
    617 
    618     BufferLengthOp = Op->Asl.Child;
    619     InitializerOp = BufferLengthOp->Asl.Next;
    620 
    621     /*
    622      * If the BufferLength is not an INTEGER or was not specified in the ASL
    623      * (DEFAULT_ARG), it is a TermArg that is
    624      * evaluated at run-time, and we are therefore finished.
    625      */
    626     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
    627         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
    628     {
    629         return;
    630     }
    631 
    632     /*
    633      * We want to count the number of items in the initializer list, because if
    634      * it is larger than the buffer length, we will define the buffer size
    635      * to be the size of the initializer list (as per the ACPI Specification)
    636      */
    637     switch (InitializerOp->Asl.ParseOpcode)
    638     {
    639     case PARSEOP_INTEGER:
    640     case PARSEOP_BYTECONST:
    641     case PARSEOP_WORDCONST:
    642     case PARSEOP_DWORDCONST:
    643 
    644         /* The peer list contains the byte list (if any...) */
    645 
    646         while (InitializerOp)
    647         {
    648             /* For buffers, this is a list of raw bytes */
    649 
    650             InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    651             InitializerOp->Asl.AmlLength = 1;
    652             InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    653 
    654             BufferLength++;
    655             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
    656         }
    657         break;
    658 
    659     case PARSEOP_STRING_LITERAL:
    660 
    661         /*
    662          * Only one initializer, the string. Buffer must be big enough to hold
    663          * the string plus the null termination byte
    664          */
    665         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
    666 
    667         InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    668         InitializerOp->Asl.AmlLength = BufferLength;
    669         InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    670         break;
    671 
    672     case PARSEOP_RAW_DATA:
    673 
    674         /* Buffer nodes are already initialized (e.g. Unicode operator) */
    675         return;
    676 
    677     case PARSEOP_DEFAULT_ARG:
    678         break;
    679 
    680     default:
    681 
    682         AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp,
    683             "Unknown buffer initializer opcode");
    684         printf ("Unknown buffer initializer opcode [%s]\n",
    685             UtGetOpName (InitializerOp->Asl.ParseOpcode));
    686         return;
    687     }
    688 
    689     /* Check if initializer list is longer than the buffer length */
    690 
    691     if (BufferLengthOp->Asl.Value.Integer > BufferLength)
    692     {
    693         BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer;
    694     }
    695 
    696     if (!BufferLength)
    697     {
    698         /* No length AND no items -- issue notice */
    699 
    700         AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL);
    701 
    702         /* But go ahead and put the buffer length of zero into the AML */
    703     }
    704 
    705     /*
    706      * Just set the buffer size node to be the buffer length, regardless
    707      * of whether it was previously an integer or a default_arg placeholder
    708      */
    709     BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER;
    710     BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP;
    711     BufferLengthOp->Asl.Value.Integer = BufferLength;
    712 
    713     (void) OpcSetOptimalIntegerSize (BufferLengthOp);
    714     UtSetParseOpName (BufferLengthOp);
    715 
    716     /* Remaining nodes are handled via the tree walk */
    717 }
    718 
    719 
    720 /*******************************************************************************
    721  *
    722  * FUNCTION:    OpnDoPackage
    723  *
    724  * PARAMETERS:  Op        - The parent parse node
    725  *
    726  * RETURN:      None
    727  *
    728  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
    729  *              can only be called after constants have been folded, to ensure
    730  *              that the PackageLength operand has been fully reduced.
    731  *
    732  ******************************************************************************/
    733 
    734 void
    735 OpnDoPackage (
    736     ACPI_PARSE_OBJECT       *Op)
    737 {
    738     ACPI_PARSE_OBJECT       *InitializerOp;
    739     ACPI_PARSE_OBJECT       *PackageLengthOp;
    740     UINT32                  PackageLength = 0;
    741 
    742 
    743     /* Opcode and package length first, followed by the initializer list */
    744 
    745     PackageLengthOp = Op->Asl.Child;
    746     InitializerOp = PackageLengthOp->Asl.Next;
    747 
    748     /* Count the number of items in the initializer list */
    749 
    750     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    751     {
    752         /* The peer list contains the byte list (if any...) */
    753 
    754         while (InitializerOp)
    755         {
    756             PackageLength++;
    757             InitializerOp = InitializerOp->Asl.Next;
    758         }
    759     }
    760 
    761     /* If package length is a constant, compare to the initializer list */
    762 
    763     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
    764         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
    765     {
    766         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
    767         {
    768             /*
    769              * Allow package length to be longer than the initializer
    770              * list -- but if the length of initializer list is nonzero,
    771              * issue a message since this is probably a coding error,
    772              * even though technically legal.
    773              */
    774             if (PackageLength > 0)
    775             {
    776                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
    777                     PackageLengthOp, NULL);
    778             }
    779 
    780             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
    781         }
    782         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
    783         {
    784             /*
    785              * The package length is smaller than the length of the
    786              * initializer list. This is an error as per the ACPI spec.
    787              */
    788             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
    789                 PackageLengthOp, NULL);
    790         }
    791     }
    792 
    793     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    794     {
    795         /*
    796          * This is the case if the PackageLength was left empty - Package()
    797          * The package length becomes the length of the initializer list
    798          */
    799         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
    800         Op->Asl.Child->Asl.Value.Integer = PackageLength;
    801         UtSetParseOpName (Op);
    802 
    803         /* Set the AML opcode */
    804 
    805         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
    806     }
    807 
    808     /* If not a variable-length package, check for a zero package length */
    809 
    810     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
    811         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
    812         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
    813         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
    814     {
    815         if (!PackageLength)
    816         {
    817             /* No length AND no initializer list -- issue a remark */
    818 
    819             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
    820                 PackageLengthOp, NULL);
    821 
    822             /* But go ahead and put the buffer length of zero into the AML */
    823         }
    824     }
    825 
    826     /*
    827      * If the PackageLength is a constant <= 255, we can change the
    828      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
    829      */
    830     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    831             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
    832         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
    833         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
    834         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
    835     {
    836         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
    837         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
    838 
    839         /*
    840          * Just set the package size node to be the package length, regardless
    841          * of whether it was previously an integer or a default_arg placeholder
    842          */
    843         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    844         PackageLengthOp->Asl.AmlLength = 1;
    845         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    846         PackageLengthOp->Asl.Value.Integer = PackageLength;
    847     }
    848 
    849     /* Remaining nodes are handled via the tree walk */
    850 }
    851 
    852 
    853 /*******************************************************************************
    854  *
    855  * FUNCTION:    OpnDoLoadTable
    856  *
    857  * PARAMETERS:  Op        - The parent parse node
    858  *
    859  * RETURN:      None
    860  *
    861  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
    862  *
    863  ******************************************************************************/
    864 
    865 static void
    866 OpnDoLoadTable (
    867     ACPI_PARSE_OBJECT       *Op)
    868 {
    869     ACPI_PARSE_OBJECT       *Next;
    870 
    871 
    872     /* Opcode is parent node */
    873     /* First child is the table signature */
    874 
    875     Next = Op->Asl.Child;
    876 
    877     /* Second child is the OEM ID*/
    878 
    879     Next = Next->Asl.Next;
    880 
    881     /* Third child is the OEM table ID */
    882 
    883     Next = Next->Asl.Next;
    884 
    885     /* Fourth child is the RootPath string */
    886 
    887     Next = Next->Asl.Next;
    888     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
    889     {
    890         Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
    891         Next->Asl.Value.String = "\\";
    892         Next->Asl.AmlLength = 2;
    893         OpcGenerateAmlOpcode (Next);
    894     }
    895 
    896 #ifdef ASL_FUTURE_IMPLEMENTATION
    897 
    898     /* TBD: NOT IMPLEMENTED */
    899     /* Fifth child is the [optional] ParameterPathString */
    900     /* Sixth child is the [optional] ParameterData */
    901 
    902     Next = Next->Asl.Next;
    903     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
    904     {
    905         Next->Asl.AmlLength = 1;
    906         Next->Asl.ParseOpcode = ZERO;
    907         OpcGenerateAmlOpcode (Next);
    908     }
    909 
    910 
    911     Next = Next->Asl.Next;
    912     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
    913     {
    914         Next->Asl.AmlLength = 1;
    915         Next->Asl.ParseOpcode = ZERO;
    916         OpcGenerateAmlOpcode (Next);
    917     }
    918 #endif
    919 }
    920 
    921 
    922 /*******************************************************************************
    923  *
    924  * FUNCTION:    OpnDoDefinitionBlock
    925  *
    926  * PARAMETERS:  Op        - The parent parse node
    927  *
    928  * RETURN:      None
    929  *
    930  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
    931  *
    932  ******************************************************************************/
    933 
    934 static void
    935 OpnDoDefinitionBlock (
    936     ACPI_PARSE_OBJECT       *Op)
    937 {
    938     ACPI_PARSE_OBJECT       *Child;
    939     ACPI_SIZE               Length;
    940     UINT32                  i;
    941     char                    *Filename;
    942     ACPI_STATUS             Status;
    943 
    944 
    945     /*
    946      * These nodes get stuffed into the table header. They are special
    947      * cased when the table is written to the output file.
    948      *
    949      * Mark all of these nodes as non-usable so they won't get output
    950      * as AML opcodes!
    951      */
    952 
    953     /* Get AML filename. Use it if non-null */
    954 
    955     Child = Op->Asl.Child;
    956     if (Child->Asl.Value.Buffer  &&
    957         *Child->Asl.Value.Buffer &&
    958         (AslGbl_UseDefaultAmlFilename))
    959     {
    960         /*
    961          * The walk may traverse multiple definition blocks. Switch files
    962          * to ensure that the correct files are manipulated.
    963          */
    964         FlSwitchFileSet (Op->Asl.Filename);
    965 
    966         /*
    967          * We will use the AML filename that is embedded in the source file
    968          * for the output filename.
    969          */
    970         Filename = UtLocalCacheCalloc (strlen (AslGbl_DirectoryPath) +
    971             strlen ((char *) Child->Asl.Value.Buffer) + 1);
    972 
    973         /* Prepend the current directory path */
    974 
    975         strcpy (Filename, AslGbl_DirectoryPath);
    976         strcat (Filename, (char *) Child->Asl.Value.Buffer);
    977 
    978         AslGbl_OutputFilenamePrefix = Filename;
    979         UtConvertBackslashes (AslGbl_OutputFilenamePrefix);
    980 
    981         /*
    982          * Use the definition block file parameter instead of the input
    983          * filename. Since all files were opened previously, remove the
    984          * existing file and open a new file with the name of this
    985          * definiton block parameter. Since AML code generation has yet
    986          * to happen, the previous file can be removed without any impacts.
    987          */
    988         FlCloseFile (ASL_FILE_AML_OUTPUT);
    989         FlDeleteFile (ASL_FILE_AML_OUTPUT);
    990         Status = FlOpenAmlOutputFile (AslGbl_OutputFilenamePrefix);
    991         if (ACPI_FAILURE (Status))
    992         {
    993             AslError (ASL_ERROR, ASL_MSG_OUTPUT_FILE_OPEN, NULL, NULL);
    994             return;
    995         }
    996     }
    997 
    998     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    999 
   1000     /* Signature */
   1001 
   1002     Child = Child->Asl.Next;
   1003     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1004     if (Child->Asl.Value.String)
   1005     {
   1006         AslGbl_FilesList->TableSignature = Child->Asl.Value.String;
   1007         AslGbl_TableSignature = Child->Asl.Value.String;
   1008         if (strlen (AslGbl_TableSignature) != ACPI_NAMESEG_SIZE)
   1009         {
   1010             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
   1011                 "Length must be exactly 4 characters");
   1012         }
   1013 
   1014         for (i = 0; i < ACPI_NAMESEG_SIZE; i++)
   1015         {
   1016             if (!isalnum ((int) AslGbl_TableSignature[i]))
   1017             {
   1018                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
   1019                     "Contains non-alphanumeric characters");
   1020             }
   1021         }
   1022     }
   1023 
   1024     /* Revision */
   1025 
   1026     Child = Child->Asl.Next;
   1027     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1028 
   1029     /*
   1030      * We used the revision to set the integer width earlier
   1031      */
   1032 
   1033     /* OEMID */
   1034 
   1035     Child = Child->Asl.Next;
   1036     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1037     if (Child->Asl.Value.String &&
   1038         strlen (Child->Asl.Value.String) > ACPI_OEM_ID_SIZE)
   1039     {
   1040         AslError (ASL_ERROR, ASL_MSG_OEM_ID, Child,
   1041             "Length cannot exceed 6 characters");
   1042     }
   1043 
   1044     /* OEM TableID */
   1045 
   1046     Child = Child->Asl.Next;
   1047     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1048     if (Child->Asl.Value.String)
   1049     {
   1050         Length = strlen (Child->Asl.Value.String);
   1051         if (Length > ACPI_OEM_TABLE_ID_SIZE)
   1052         {
   1053             AslError (ASL_ERROR, ASL_MSG_OEM_TABLE_ID, Child,
   1054                 "Length cannot exceed 8 characters");
   1055         }
   1056 
   1057         AslGbl_TableId = UtLocalCacheCalloc (Length + 1);
   1058         strcpy (AslGbl_TableId, Child->Asl.Value.String);
   1059         AslGbl_FilesList->TableId = AslGbl_TableId;
   1060 
   1061         /*
   1062          * Convert anything non-alphanumeric to an underscore. This
   1063          * allows us to use the TableID to generate unique C symbols.
   1064          */
   1065         for (i = 0; i < Length; i++)
   1066         {
   1067             if (!isalnum ((int) AslGbl_TableId[i]))
   1068             {
   1069                 AslGbl_TableId[i] = '_';
   1070             }
   1071         }
   1072     }
   1073 
   1074     /* OEM Revision */
   1075 
   1076     Child = Child->Asl.Next;
   1077     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1078 }
   1079 
   1080 
   1081 /*******************************************************************************
   1082  *
   1083  * FUNCTION:    UtGetArg
   1084  *
   1085  * PARAMETERS:  Op              - Get an argument for this op
   1086  *              Argn            - Nth argument to get
   1087  *
   1088  * RETURN:      The argument (as an Op object). NULL if argument does not exist
   1089  *
   1090  * DESCRIPTION: Get the specified op's argument (peer)
   1091  *
   1092  ******************************************************************************/
   1093 
   1094 ACPI_PARSE_OBJECT *
   1095 UtGetArg (
   1096     ACPI_PARSE_OBJECT       *Op,
   1097     UINT32                  Argn)
   1098 {
   1099     ACPI_PARSE_OBJECT       *Arg = NULL;
   1100 
   1101 
   1102     /* Get the requested argument object */
   1103 
   1104     Arg = Op->Asl.Child;
   1105     while (Arg && Argn)
   1106     {
   1107         Argn--;
   1108         Arg = Arg->Asl.Next;
   1109     }
   1110 
   1111     return (Arg);
   1112 }
   1113 
   1114 
   1115 /*******************************************************************************
   1116  *
   1117  * FUNCTION:    OpnAttachNameToNode
   1118  *
   1119  * PARAMETERS:  Op        - The parent parse node
   1120  *
   1121  * RETURN:      None
   1122  *
   1123  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
   1124  *              argument list and attach it to the parent node so that we
   1125  *              can get to it quickly later.
   1126  *
   1127  ******************************************************************************/
   1128 
   1129 static void
   1130 OpnAttachNameToNode (
   1131     ACPI_PARSE_OBJECT       *Op)
   1132 {
   1133     ACPI_PARSE_OBJECT       *Child = NULL;
   1134 
   1135 
   1136     switch (Op->Asl.AmlOpcode)
   1137     {
   1138     case AML_DATA_REGION_OP:
   1139     case AML_DEVICE_OP:
   1140     case AML_EVENT_OP:
   1141     case AML_EXTERNAL_OP:
   1142     case AML_METHOD_OP:
   1143     case AML_MUTEX_OP:
   1144     case AML_REGION_OP:
   1145     case AML_POWER_RESOURCE_OP:
   1146     case AML_PROCESSOR_OP:
   1147     case AML_THERMAL_ZONE_OP:
   1148     case AML_NAME_OP:
   1149     case AML_SCOPE_OP:
   1150 
   1151         Child = UtGetArg (Op, 0);
   1152         break;
   1153 
   1154     case AML_ALIAS_OP:
   1155 
   1156         Child = UtGetArg (Op, 1);
   1157         break;
   1158 
   1159     case AML_CREATE_BIT_FIELD_OP:
   1160     case AML_CREATE_BYTE_FIELD_OP:
   1161     case AML_CREATE_WORD_FIELD_OP:
   1162     case AML_CREATE_DWORD_FIELD_OP:
   1163     case AML_CREATE_QWORD_FIELD_OP:
   1164 
   1165         Child = UtGetArg (Op, 2);
   1166         break;
   1167 
   1168     case AML_CREATE_FIELD_OP:
   1169 
   1170         Child = UtGetArg (Op, 3);
   1171         break;
   1172 
   1173     case AML_BANK_FIELD_OP:
   1174     case AML_INDEX_FIELD_OP:
   1175     case AML_FIELD_OP:
   1176 
   1177         return;
   1178 
   1179     default:
   1180 
   1181         return;
   1182     }
   1183 
   1184     if (Child)
   1185     {
   1186         UtAttachNamepathToOwner (Op, Child);
   1187     }
   1188 }
   1189 
   1190 
   1191 /*******************************************************************************
   1192  *
   1193  * FUNCTION:    OpnGenerateAmlOperands
   1194  *
   1195  * PARAMETERS:  Op        - The parent parse node
   1196  *
   1197  * RETURN:      None
   1198  *
   1199  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
   1200  *              complex AML opcodes require processing of the child nodes
   1201  *              (arguments/operands).
   1202  *
   1203  ******************************************************************************/
   1204 
   1205 void
   1206 OpnGenerateAmlOperands (
   1207     ACPI_PARSE_OBJECT       *Op)
   1208 {
   1209 
   1210 
   1211     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
   1212     {
   1213         return;
   1214     }
   1215 
   1216     switch (Op->Asl.ParseOpcode)
   1217     {
   1218     case PARSEOP_DEFINITION_BLOCK:
   1219 
   1220         OpnDoDefinitionBlock (Op);
   1221         break;
   1222 
   1223     case PARSEOP_METHOD:
   1224 
   1225         OpnDoMethod (Op);
   1226         break;
   1227 
   1228     case PARSEOP_MUTEX:
   1229 
   1230         OpnDoMutex (Op);
   1231         break;
   1232 
   1233     case PARSEOP_FIELD:
   1234 
   1235         OpnDoField (Op);
   1236         break;
   1237 
   1238     case PARSEOP_INDEXFIELD:
   1239 
   1240         OpnDoIndexField (Op);
   1241         break;
   1242 
   1243     case PARSEOP_BANKFIELD:
   1244 
   1245         OpnDoBankField (Op);
   1246         break;
   1247 
   1248     case PARSEOP_BUFFER:
   1249 
   1250         OpnDoBuffer (Op);
   1251         break;
   1252 
   1253     case PARSEOP_LOADTABLE:
   1254 
   1255         OpnDoLoadTable (Op);
   1256         break;
   1257 
   1258     case PARSEOP_OPERATIONREGION:
   1259 
   1260         OpnDoRegion (Op);
   1261         break;
   1262 
   1263     case PARSEOP_RESOURCETEMPLATE:
   1264 
   1265         RsDoResourceTemplate (Op);
   1266         break;
   1267 
   1268     case PARSEOP_NAMESEG:
   1269     case PARSEOP_NAMESTRING:
   1270     case PARSEOP_METHODCALL:
   1271     case PARSEOP_STRING_LITERAL:
   1272     default:
   1273 
   1274         break;
   1275     }
   1276 
   1277     /* TBD: move */
   1278 
   1279     OpnAttachNameToNode (Op);
   1280 }
   1281