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