Home | History | Annotate | Line # | Download | only in compiler
asloperands.c revision 1.1.1.16
      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 
    715     /* Remaining nodes are handled via the tree walk */
    716 }
    717 
    718 
    719 /*******************************************************************************
    720  *
    721  * FUNCTION:    OpnDoPackage
    722  *
    723  * PARAMETERS:  Op        - The parent parse node
    724  *
    725  * RETURN:      None
    726  *
    727  * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE:
    728  *              can only be called after constants have been folded, to ensure
    729  *              that the PackageLength operand has been fully reduced.
    730  *
    731  ******************************************************************************/
    732 
    733 void
    734 OpnDoPackage (
    735     ACPI_PARSE_OBJECT       *Op)
    736 {
    737     ACPI_PARSE_OBJECT       *InitializerOp;
    738     ACPI_PARSE_OBJECT       *PackageLengthOp;
    739     UINT32                  PackageLength = 0;
    740 
    741 
    742     /* Opcode and package length first, followed by the initializer list */
    743 
    744     PackageLengthOp = Op->Asl.Child;
    745     InitializerOp = PackageLengthOp->Asl.Next;
    746 
    747     /* Count the number of items in the initializer list */
    748 
    749     if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    750     {
    751         /* The peer list contains the byte list (if any...) */
    752 
    753         while (InitializerOp)
    754         {
    755             PackageLength++;
    756             InitializerOp = InitializerOp->Asl.Next;
    757         }
    758     }
    759 
    760     /* If package length is a constant, compare to the initializer list */
    761 
    762     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
    763         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST))
    764     {
    765         if (PackageLengthOp->Asl.Value.Integer > PackageLength)
    766         {
    767             /*
    768              * Allow package length to be longer than the initializer
    769              * list -- but if the length of initializer list is nonzero,
    770              * issue a message since this is probably a coding error,
    771              * even though technically legal.
    772              */
    773             if (PackageLength > 0)
    774             {
    775                 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT,
    776                     PackageLengthOp, NULL);
    777             }
    778 
    779             PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer;
    780         }
    781         else if (PackageLengthOp->Asl.Value.Integer < PackageLength)
    782         {
    783             /*
    784              * The package length is smaller than the length of the
    785              * initializer list. This is an error as per the ACPI spec.
    786              */
    787             AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG,
    788                 PackageLengthOp, NULL);
    789         }
    790     }
    791 
    792     if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    793     {
    794         /*
    795          * This is the case if the PackageLength was left empty - Package()
    796          * The package length becomes the length of the initializer list
    797          */
    798         Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER;
    799         Op->Asl.Child->Asl.Value.Integer = PackageLength;
    800 
    801         /* Set the AML opcode */
    802 
    803         (void) OpcSetOptimalIntegerSize (Op->Asl.Child);
    804     }
    805 
    806     /* If not a variable-length package, check for a zero package length */
    807 
    808     if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)      ||
    809         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)   ||
    810         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO)         ||
    811         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
    812     {
    813         if (!PackageLength)
    814         {
    815             /* No length AND no initializer list -- issue a remark */
    816 
    817             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
    818                 PackageLengthOp, NULL);
    819 
    820             /* But go ahead and put the buffer length of zero into the AML */
    821         }
    822     }
    823 
    824     /*
    825      * If the PackageLength is a constant <= 255, we can change the
    826      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
    827      */
    828     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    829             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
    830         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
    831         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
    832         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
    833     {
    834         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
    835         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
    836 
    837         /*
    838          * Just set the package size node to be the package length, regardless
    839          * of whether it was previously an integer or a default_arg placeholder
    840          */
    841         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    842         PackageLengthOp->Asl.AmlLength = 1;
    843         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    844         PackageLengthOp->Asl.Value.Integer = PackageLength;
    845     }
    846 
    847     /* Remaining nodes are handled via the tree walk */
    848 }
    849 
    850 
    851 /*******************************************************************************
    852  *
    853  * FUNCTION:    OpnDoLoadTable
    854  *
    855  * PARAMETERS:  Op        - The parent parse node
    856  *
    857  * RETURN:      None
    858  *
    859  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
    860  *
    861  ******************************************************************************/
    862 
    863 static void
    864 OpnDoLoadTable (
    865     ACPI_PARSE_OBJECT       *Op)
    866 {
    867     ACPI_PARSE_OBJECT       *Next;
    868 
    869 
    870     /* Opcode is parent node */
    871     /* First child is the table signature */
    872 
    873     Next = Op->Asl.Child;
    874 
    875     /* Second child is the OEM ID*/
    876 
    877     Next = Next->Asl.Next;
    878 
    879     /* Third child is the OEM table ID */
    880 
    881     Next = Next->Asl.Next;
    882 
    883     /* Fourth child is the RootPath string */
    884 
    885     Next = Next->Asl.Next;
    886     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
    887     {
    888         Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
    889         Next->Asl.Value.String = "\\";
    890         Next->Asl.AmlLength = 2;
    891         OpcGenerateAmlOpcode (Next);
    892     }
    893 
    894 #ifdef ASL_FUTURE_IMPLEMENTATION
    895 
    896     /* TBD: NOT IMPLEMENTED */
    897     /* Fifth child is the [optional] ParameterPathString */
    898     /* Sixth child is the [optional] ParameterData */
    899 
    900     Next = Next->Asl.Next;
    901     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
    902     {
    903         Next->Asl.AmlLength = 1;
    904         Next->Asl.ParseOpcode = ZERO;
    905         OpcGenerateAmlOpcode (Next);
    906     }
    907 
    908 
    909     Next = Next->Asl.Next;
    910     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
    911     {
    912         Next->Asl.AmlLength = 1;
    913         Next->Asl.ParseOpcode = ZERO;
    914         OpcGenerateAmlOpcode (Next);
    915     }
    916 #endif
    917 }
    918 
    919 
    920 /*******************************************************************************
    921  *
    922  * FUNCTION:    OpnDoDefinitionBlock
    923  *
    924  * PARAMETERS:  Op        - The parent parse node
    925  *
    926  * RETURN:      None
    927  *
    928  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
    929  *
    930  ******************************************************************************/
    931 
    932 static void
    933 OpnDoDefinitionBlock (
    934     ACPI_PARSE_OBJECT       *Op)
    935 {
    936     ACPI_PARSE_OBJECT       *Child;
    937     ACPI_SIZE               Length;
    938     UINT32                  i;
    939     char                    *Filename;
    940     ACPI_STATUS             Status;
    941 
    942 
    943     /*
    944      * These nodes get stuffed into the table header. They are special
    945      * cased when the table is written to the output file.
    946      *
    947      * Mark all of these nodes as non-usable so they won't get output
    948      * as AML opcodes!
    949      */
    950 
    951     /* Get AML filename. Use it if non-null */
    952 
    953     Child = Op->Asl.Child;
    954     if (Child->Asl.Value.Buffer  &&
    955         *Child->Asl.Value.Buffer &&
    956         (AslGbl_UseDefaultAmlFilename))
    957     {
    958         /*
    959          * The walk may traverse multiple definition blocks. Switch files
    960          * to ensure that the correct files are manipulated.
    961          */
    962         FlSwitchFileSet (Op->Asl.Filename);
    963 
    964         /*
    965          * We will use the AML filename that is embedded in the source file
    966          * for the output filename.
    967          */
    968         Filename = UtLocalCacheCalloc (strlen (AslGbl_DirectoryPath) +
    969             strlen ((char *) Child->Asl.Value.Buffer) + 1);
    970 
    971         /* Prepend the current directory path */
    972 
    973         strcpy (Filename, AslGbl_DirectoryPath);
    974         strcat (Filename, (char *) Child->Asl.Value.Buffer);
    975 
    976         AslGbl_OutputFilenamePrefix = Filename;
    977         UtConvertBackslashes (AslGbl_OutputFilenamePrefix);
    978 
    979         /*
    980          * Use the definition block file parameter instead of the input
    981          * filename. Since all files were opened previously, remove the
    982          * existing file and open a new file with the name of this
    983          * definiton block parameter. Since AML code generation has yet
    984          * to happen, the previous file can be removed without any impacts.
    985          */
    986         FlCloseFile (ASL_FILE_AML_OUTPUT);
    987         FlDeleteFile (ASL_FILE_AML_OUTPUT);
    988         Status = FlOpenAmlOutputFile (AslGbl_OutputFilenamePrefix);
    989         if (ACPI_FAILURE (Status))
    990         {
    991             AslError (ASL_ERROR, ASL_MSG_OUTPUT_FILE_OPEN, NULL, NULL);
    992             return;
    993         }
    994     }
    995 
    996     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    997 
    998     /* Signature */
    999 
   1000     Child = Child->Asl.Next;
   1001     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1002     if (Child->Asl.Value.String)
   1003     {
   1004         AslGbl_FilesList->TableSignature = Child->Asl.Value.String;
   1005         AslGbl_TableSignature = Child->Asl.Value.String;
   1006         if (strlen (AslGbl_TableSignature) != ACPI_NAMESEG_SIZE)
   1007         {
   1008             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
   1009                 "Length must be exactly 4 characters");
   1010         }
   1011 
   1012         for (i = 0; i < ACPI_NAMESEG_SIZE; i++)
   1013         {
   1014             if (!isalnum ((int) AslGbl_TableSignature[i]))
   1015             {
   1016                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
   1017                     "Contains non-alphanumeric characters");
   1018             }
   1019         }
   1020     }
   1021 
   1022     /* Revision */
   1023 
   1024     Child = Child->Asl.Next;
   1025     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1026 
   1027     /*
   1028      * We used the revision to set the integer width earlier
   1029      */
   1030 
   1031     /* OEMID */
   1032 
   1033     Child = Child->Asl.Next;
   1034     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1035     if (Child->Asl.Value.String &&
   1036         strlen (Child->Asl.Value.String) > ACPI_OEM_ID_SIZE)
   1037     {
   1038         AslError (ASL_ERROR, ASL_MSG_OEM_ID, Child,
   1039             "Length cannot exceed 6 characters");
   1040     }
   1041 
   1042     /* OEM TableID */
   1043 
   1044     Child = Child->Asl.Next;
   1045     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1046     if (Child->Asl.Value.String)
   1047     {
   1048         Length = strlen (Child->Asl.Value.String);
   1049         if (Length > ACPI_OEM_TABLE_ID_SIZE)
   1050         {
   1051             AslError (ASL_ERROR, ASL_MSG_OEM_TABLE_ID, Child,
   1052                 "Length cannot exceed 8 characters");
   1053         }
   1054 
   1055         AslGbl_TableId = UtLocalCacheCalloc (Length + 1);
   1056         strcpy (AslGbl_TableId, Child->Asl.Value.String);
   1057         AslGbl_FilesList->TableId = AslGbl_TableId;
   1058 
   1059         /*
   1060          * Convert anything non-alphanumeric to an underscore. This
   1061          * allows us to use the TableID to generate unique C symbols.
   1062          */
   1063         for (i = 0; i < Length; i++)
   1064         {
   1065             if (!isalnum ((int) AslGbl_TableId[i]))
   1066             {
   1067                 AslGbl_TableId[i] = '_';
   1068             }
   1069         }
   1070     }
   1071 
   1072     /* OEM Revision */
   1073 
   1074     Child = Child->Asl.Next;
   1075     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
   1076 }
   1077 
   1078 
   1079 /*******************************************************************************
   1080  *
   1081  * FUNCTION:    UtGetArg
   1082  *
   1083  * PARAMETERS:  Op              - Get an argument for this op
   1084  *              Argn            - Nth argument to get
   1085  *
   1086  * RETURN:      The argument (as an Op object). NULL if argument does not exist
   1087  *
   1088  * DESCRIPTION: Get the specified op's argument (peer)
   1089  *
   1090  ******************************************************************************/
   1091 
   1092 ACPI_PARSE_OBJECT *
   1093 UtGetArg (
   1094     ACPI_PARSE_OBJECT       *Op,
   1095     UINT32                  Argn)
   1096 {
   1097     ACPI_PARSE_OBJECT       *Arg = NULL;
   1098 
   1099 
   1100     /* Get the requested argument object */
   1101 
   1102     Arg = Op->Asl.Child;
   1103     while (Arg && Argn)
   1104     {
   1105         Argn--;
   1106         Arg = Arg->Asl.Next;
   1107     }
   1108 
   1109     return (Arg);
   1110 }
   1111 
   1112 
   1113 /*******************************************************************************
   1114  *
   1115  * FUNCTION:    OpnAttachNameToNode
   1116  *
   1117  * PARAMETERS:  Op        - The parent parse node
   1118  *
   1119  * RETURN:      None
   1120  *
   1121  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
   1122  *              argument list and attach it to the parent node so that we
   1123  *              can get to it quickly later.
   1124  *
   1125  ******************************************************************************/
   1126 
   1127 static void
   1128 OpnAttachNameToNode (
   1129     ACPI_PARSE_OBJECT       *Op)
   1130 {
   1131     ACPI_PARSE_OBJECT       *Child = NULL;
   1132 
   1133 
   1134     switch (Op->Asl.AmlOpcode)
   1135     {
   1136     case AML_DATA_REGION_OP:
   1137     case AML_DEVICE_OP:
   1138     case AML_EVENT_OP:
   1139     case AML_EXTERNAL_OP:
   1140     case AML_METHOD_OP:
   1141     case AML_MUTEX_OP:
   1142     case AML_REGION_OP:
   1143     case AML_POWER_RESOURCE_OP:
   1144     case AML_PROCESSOR_OP:
   1145     case AML_THERMAL_ZONE_OP:
   1146     case AML_NAME_OP:
   1147     case AML_SCOPE_OP:
   1148 
   1149         Child = UtGetArg (Op, 0);
   1150         break;
   1151 
   1152     case AML_ALIAS_OP:
   1153 
   1154         Child = UtGetArg (Op, 1);
   1155         break;
   1156 
   1157     case AML_CREATE_BIT_FIELD_OP:
   1158     case AML_CREATE_BYTE_FIELD_OP:
   1159     case AML_CREATE_WORD_FIELD_OP:
   1160     case AML_CREATE_DWORD_FIELD_OP:
   1161     case AML_CREATE_QWORD_FIELD_OP:
   1162 
   1163         Child = UtGetArg (Op, 2);
   1164         break;
   1165 
   1166     case AML_CREATE_FIELD_OP:
   1167 
   1168         Child = UtGetArg (Op, 3);
   1169         break;
   1170 
   1171     case AML_BANK_FIELD_OP:
   1172     case AML_INDEX_FIELD_OP:
   1173     case AML_FIELD_OP:
   1174 
   1175         return;
   1176 
   1177     default:
   1178 
   1179         return;
   1180     }
   1181 
   1182     if (Child)
   1183     {
   1184         UtAttachNamepathToOwner (Op, Child);
   1185     }
   1186 }
   1187 
   1188 
   1189 /*******************************************************************************
   1190  *
   1191  * FUNCTION:    OpnGenerateAmlOperands
   1192  *
   1193  * PARAMETERS:  Op        - The parent parse node
   1194  *
   1195  * RETURN:      None
   1196  *
   1197  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
   1198  *              complex AML opcodes require processing of the child nodes
   1199  *              (arguments/operands).
   1200  *
   1201  ******************************************************************************/
   1202 
   1203 void
   1204 OpnGenerateAmlOperands (
   1205     ACPI_PARSE_OBJECT       *Op)
   1206 {
   1207 
   1208 
   1209     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
   1210     {
   1211         return;
   1212     }
   1213 
   1214     switch (Op->Asl.ParseOpcode)
   1215     {
   1216     case PARSEOP_DEFINITION_BLOCK:
   1217 
   1218         OpnDoDefinitionBlock (Op);
   1219         break;
   1220 
   1221     case PARSEOP_METHOD:
   1222 
   1223         OpnDoMethod (Op);
   1224         break;
   1225 
   1226     case PARSEOP_MUTEX:
   1227 
   1228         OpnDoMutex (Op);
   1229         break;
   1230 
   1231     case PARSEOP_FIELD:
   1232 
   1233         OpnDoField (Op);
   1234         break;
   1235 
   1236     case PARSEOP_INDEXFIELD:
   1237 
   1238         OpnDoIndexField (Op);
   1239         break;
   1240 
   1241     case PARSEOP_BANKFIELD:
   1242 
   1243         OpnDoBankField (Op);
   1244         break;
   1245 
   1246     case PARSEOP_BUFFER:
   1247 
   1248         OpnDoBuffer (Op);
   1249         break;
   1250 
   1251     case PARSEOP_LOADTABLE:
   1252 
   1253         OpnDoLoadTable (Op);
   1254         break;
   1255 
   1256     case PARSEOP_OPERATIONREGION:
   1257 
   1258         OpnDoRegion (Op);
   1259         break;
   1260 
   1261     case PARSEOP_RESOURCETEMPLATE:
   1262 
   1263         RsDoResourceTemplate (Op);
   1264         break;
   1265 
   1266     case PARSEOP_NAMESEG:
   1267     case PARSEOP_NAMESTRING:
   1268     case PARSEOP_METHODCALL:
   1269     case PARSEOP_STRING_LITERAL:
   1270     default:
   1271 
   1272         break;
   1273     }
   1274 
   1275     /* TBD: move */
   1276 
   1277     OpnAttachNameToNode (Op);
   1278 }
   1279