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