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