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