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