Home | History | Annotate | Line # | Download | only in compiler
asloperands.c revision 1.1.1.6
      1 /******************************************************************************
      2  *
      3  * Module Name: asloperands - AML operand processing
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2015, 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         Concurrency = (UINT8) Next->Asl.Value.Integer;
    192     }
    193 
    194     /* Put the bits in their proper places */
    195 
    196     MethodFlags = (UINT8) ((NumArgs & 0x7) |
    197                           ((Serialized & 0x1) << 3) |
    198                           ((Concurrency & 0xF) << 4));
    199 
    200     /* Use the last node for the combined flags byte */
    201 
    202     Next->Asl.Value.Integer = MethodFlags;
    203     Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    204     Next->Asl.AmlLength = 1;
    205     Next->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    206 
    207     /* Save the arg count in the first node */
    208 
    209     Op->Asl.Extra = NumArgs;
    210 }
    211 
    212 
    213 /*******************************************************************************
    214  *
    215  * FUNCTION:    OpnDoFieldCommon
    216  *
    217  * PARAMETERS:  FieldOp       - Node for an ASL field
    218  *              Op            - The parent parse node
    219  *
    220  * RETURN:      None
    221  *
    222  * DESCRIPTION: Construct the AML operands for the various field keywords,
    223  *              FIELD, BANKFIELD, INDEXFIELD
    224  *
    225  ******************************************************************************/
    226 
    227 static void
    228 OpnDoFieldCommon (
    229     ACPI_PARSE_OBJECT       *FieldOp,
    230     ACPI_PARSE_OBJECT       *Op)
    231 {
    232     ACPI_PARSE_OBJECT       *Next;
    233     ACPI_PARSE_OBJECT       *PkgLengthNode;
    234     UINT32                  CurrentBitOffset;
    235     UINT32                  NewBitOffset;
    236     UINT8                   AccessType;
    237     UINT8                   LockRule;
    238     UINT8                   UpdateRule;
    239     UINT8                   FieldFlags;
    240     UINT32                  MinimumLength;
    241 
    242 
    243     /* AccessType -- not optional, so no need to check for DEFAULT_ARG */
    244 
    245     AccessType = (UINT8) Op->Asl.Value.Integer;
    246     Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    247 
    248     /* Set the access type in the parent (field) node for use later */
    249 
    250     FieldOp->Asl.Value.Integer = AccessType;
    251 
    252     /* LockRule -- not optional, so no need to check for DEFAULT_ARG */
    253 
    254     Next = Op->Asl.Next;
    255     LockRule = (UINT8) Next->Asl.Value.Integer;
    256     Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    257 
    258     /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */
    259 
    260     Next = Next->Asl.Next;
    261     UpdateRule = (UINT8) Next->Asl.Value.Integer;
    262 
    263     /*
    264      * Generate the flags byte. The various fields are already
    265      * in the right bit position via translation from the
    266      * keywords by the parser.
    267      */
    268     FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule);
    269 
    270     /* Use the previous node to be the FieldFlags node */
    271 
    272     /* Set the node to RAW_DATA */
    273 
    274     Next->Asl.Value.Integer = FieldFlags;
    275     Next->Asl.AmlOpcode     = AML_RAW_DATA_BYTE;
    276     Next->Asl.AmlLength     = 1;
    277     Next->Asl.ParseOpcode   = PARSEOP_RAW_DATA;
    278 
    279     /* Process the FieldUnitList */
    280 
    281     Next = Next->Asl.Next;
    282     CurrentBitOffset = 0;
    283 
    284     while (Next)
    285     {
    286         /* Save the offset of this field unit */
    287 
    288         Next->Asl.ExtraValue = CurrentBitOffset;
    289 
    290         switch (Next->Asl.ParseOpcode)
    291         {
    292         case PARSEOP_ACCESSAS:
    293 
    294             PkgLengthNode = Next->Asl.Child;
    295             AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer;
    296 
    297             /* Nothing additional to do */
    298             break;
    299 
    300         case PARSEOP_OFFSET:
    301 
    302             /* New offset into the field */
    303 
    304             PkgLengthNode = Next->Asl.Child;
    305             NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8;
    306 
    307             /*
    308              * Examine the specified offset in relation to the
    309              * current offset counter.
    310              */
    311             if (NewBitOffset < CurrentBitOffset)
    312             {
    313                 /*
    314                  * Not allowed to specify a backwards offset!
    315                  * Issue error and ignore this node.
    316                  */
    317                 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode,
    318                     NULL);
    319                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    320                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    321             }
    322             else if (NewBitOffset == CurrentBitOffset)
    323             {
    324                 /*
    325                  * Offset is redundant; we don't need to output an
    326                  * offset opcode. Just set these nodes to default
    327                  */
    328                 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    329                 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    330             }
    331             else
    332             {
    333                 /*
    334                  * Valid new offset - set the value to be inserted into the AML
    335                  * and update the offset counter.
    336                  */
    337                 PkgLengthNode->Asl.Value.Integer =
    338                     NewBitOffset - CurrentBitOffset;
    339                 CurrentBitOffset = NewBitOffset;
    340             }
    341             break;
    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 
    361                     MinimumLength = 8;
    362                     break;
    363 
    364                 case AML_FIELD_ACCESS_WORD:
    365                     MinimumLength = 16;
    366                     break;
    367 
    368                 case AML_FIELD_ACCESS_DWORD:
    369                     MinimumLength = 32;
    370                     break;
    371 
    372                 case AML_FIELD_ACCESS_QWORD:
    373                     MinimumLength = 64;
    374                     break;
    375             }
    376 
    377             PkgLengthNode->Asl.ExtraValue = MinimumLength;
    378             break;
    379 
    380         default:
    381 
    382             /* All supported field opcodes must appear above */
    383 
    384             break;
    385         }
    386 
    387         /* Move on to next entry in the field list */
    388 
    389         Next = Next->Asl.Next;
    390     }
    391 }
    392 
    393 
    394 /*******************************************************************************
    395  *
    396  * FUNCTION:    OpnDoField
    397  *
    398  * PARAMETERS:  Op        - The parent parse node
    399  *
    400  * RETURN:      None
    401  *
    402  * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword
    403  *
    404  ******************************************************************************/
    405 
    406 static void
    407 OpnDoField (
    408     ACPI_PARSE_OBJECT       *Op)
    409 {
    410     ACPI_PARSE_OBJECT       *Next;
    411 
    412 
    413     /* Opcode is parent node */
    414     /* First child is field name */
    415 
    416     Next = Op->Asl.Child;
    417 
    418     /* Second child is the AccessType */
    419 
    420     OpnDoFieldCommon (Op, Next->Asl.Next);
    421 }
    422 
    423 
    424 /*******************************************************************************
    425  *
    426  * FUNCTION:    OpnDoIndexField
    427  *
    428  * PARAMETERS:  Op        - The parent parse node
    429  *
    430  * RETURN:      None
    431  *
    432  * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword
    433  *
    434  ******************************************************************************/
    435 
    436 static void
    437 OpnDoIndexField (
    438     ACPI_PARSE_OBJECT       *Op)
    439 {
    440     ACPI_PARSE_OBJECT       *Next;
    441 
    442 
    443     /* Opcode is parent node */
    444     /* First child is the index name */
    445 
    446     Next = Op->Asl.Child;
    447 
    448     /* Second child is the data name */
    449 
    450     Next = Next->Asl.Next;
    451 
    452     /* Third child is the AccessType */
    453 
    454     OpnDoFieldCommon (Op, Next->Asl.Next);
    455 }
    456 
    457 
    458 /*******************************************************************************
    459  *
    460  * FUNCTION:    OpnDoBankField
    461  *
    462  * PARAMETERS:  Op        - The parent parse node
    463  *
    464  * RETURN:      None
    465  *
    466  * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword
    467  *
    468  ******************************************************************************/
    469 
    470 static void
    471 OpnDoBankField (
    472     ACPI_PARSE_OBJECT       *Op)
    473 {
    474     ACPI_PARSE_OBJECT       *Next;
    475 
    476 
    477     /* Opcode is parent node */
    478     /* First child is the region name */
    479 
    480     Next = Op->Asl.Child;
    481 
    482     /* Second child is the bank name */
    483 
    484     Next = Next->Asl.Next;
    485 
    486     /* Third child is the bank value */
    487 
    488     Next = Next->Asl.Next;
    489 
    490     /* Fourth child is the AccessType */
    491 
    492     OpnDoFieldCommon (Op, Next->Asl.Next);
    493 }
    494 
    495 
    496 /*******************************************************************************
    497  *
    498  * FUNCTION:    OpnDoRegion
    499  *
    500  * PARAMETERS:  Op        - The parent parse node
    501  *
    502  * RETURN:      None
    503  *
    504  * DESCRIPTION: Tries to get the length of the region. Can only do this at
    505  *              compile time if the length is a constant.
    506  *
    507  ******************************************************************************/
    508 
    509 static void
    510 OpnDoRegion (
    511     ACPI_PARSE_OBJECT       *Op)
    512 {
    513     ACPI_PARSE_OBJECT       *Next;
    514 
    515 
    516     /* Opcode is parent node */
    517     /* First child is the region name */
    518 
    519     Next = Op->Asl.Child;
    520 
    521     /* Second child is the space ID*/
    522 
    523     Next = Next->Asl.Next;
    524 
    525     /* Third child is the region offset */
    526 
    527     Next = Next->Asl.Next;
    528 
    529     /* Fourth child is the region length */
    530 
    531     Next = Next->Asl.Next;
    532     if (Next->Asl.ParseOpcode == PARSEOP_INTEGER)
    533     {
    534         Op->Asl.Value.Integer = Next->Asl.Value.Integer;
    535     }
    536     else
    537     {
    538         Op->Asl.Value.Integer = ACPI_UINT64_MAX;
    539     }
    540 }
    541 
    542 
    543 /*******************************************************************************
    544  *
    545  * FUNCTION:    OpnDoBuffer
    546  *
    547  * PARAMETERS:  Op        - The parent parse node
    548  *
    549  * RETURN:      None
    550  *
    551  * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We
    552  *              build a single raw byte buffer from the initialization nodes,
    553  *              each parse node contains a buffer byte.
    554  *
    555  ******************************************************************************/
    556 
    557 static void
    558 OpnDoBuffer (
    559     ACPI_PARSE_OBJECT       *Op)
    560 {
    561     ACPI_PARSE_OBJECT       *InitializerOp;
    562     ACPI_PARSE_OBJECT       *BufferLengthOp;
    563 
    564     /* Optional arguments for this opcode with defaults */
    565 
    566     UINT32                  BufferLength = 0;
    567 
    568 
    569     /* Opcode and package length first */
    570     /* Buffer Length is next, followed by the initializer list */
    571 
    572     BufferLengthOp = Op->Asl.Child;
    573     InitializerOp = BufferLengthOp->Asl.Next;
    574 
    575     /*
    576      * If the BufferLength is not an INTEGER or was not specified in the ASL
    577      * (DEFAULT_ARG), it is a TermArg that is
    578      * evaluated at run-time, and we are therefore finished.
    579      */
    580     if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) &&
    581         (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
    582     {
    583         return;
    584     }
    585 
    586     /*
    587      * We want to count the number of items in the initializer list, because if
    588      * it is larger than the buffer length, we will define the buffer size
    589      * to be the size of the initializer list (as per the ACPI Specification)
    590      */
    591     switch (InitializerOp->Asl.ParseOpcode)
    592     {
    593     case PARSEOP_INTEGER:
    594     case PARSEOP_BYTECONST:
    595     case PARSEOP_WORDCONST:
    596     case PARSEOP_DWORDCONST:
    597 
    598         /* The peer list contains the byte list (if any...) */
    599 
    600         while (InitializerOp)
    601         {
    602             /* For buffers, this is a list of raw bytes */
    603 
    604             InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BYTE;
    605             InitializerOp->Asl.AmlLength      = 1;
    606             InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
    607 
    608             BufferLength++;
    609             InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
    610         }
    611         break;
    612 
    613     case PARSEOP_STRING_LITERAL:
    614 
    615         /*
    616          * Only one initializer, the string. Buffer must be big enough to hold
    617          * the string plus the null termination byte
    618          */
    619         BufferLength = strlen (InitializerOp->Asl.Value.String) + 1;
    620 
    621         InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
    622         InitializerOp->Asl.AmlLength      = BufferLength;
    623         InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
    624         break;
    625 
    626     case PARSEOP_RAW_DATA:
    627 
    628         /* Buffer nodes are already initialized (e.g. Unicode operator) */
    629         return;
    630 
    631     case PARSEOP_DEFAULT_ARG:
    632         break;
    633 
    634     default:
    635 
    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_ZERO)         ||
    765         (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG))
    766     {
    767         if (!PackageLength)
    768         {
    769             /* No length AND no initializer list -- issue a remark */
    770 
    771             AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH,
    772                 PackageLengthOp, NULL);
    773 
    774             /* But go ahead and put the buffer length of zero into the AML */
    775         }
    776     }
    777 
    778     /*
    779      * If the PackageLength is a constant <= 255, we can change the
    780      * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode.
    781      */
    782     if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    783             (Op->Asl.Child->Asl.Value.Integer <= 255))  ||
    784         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) ||
    785         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)||
    786         (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO))
    787     {
    788         Op->Asl.AmlOpcode = AML_PACKAGE_OP;
    789         Op->Asl.ParseOpcode = PARSEOP_PACKAGE;
    790 
    791         /*
    792          * Just set the package size node to be the package length, regardless
    793          * of whether it was previously an integer or a default_arg placeholder
    794          */
    795         PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    796         PackageLengthOp->Asl.AmlLength = 1;
    797         PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA;
    798         PackageLengthOp->Asl.Value.Integer = PackageLength;
    799     }
    800 
    801     /* Remaining nodes are handled via the tree walk */
    802 }
    803 
    804 
    805 /*******************************************************************************
    806  *
    807  * FUNCTION:    OpnDoLoadTable
    808  *
    809  * PARAMETERS:  Op        - The parent parse node
    810  *
    811  * RETURN:      None
    812  *
    813  * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword.
    814  *
    815  ******************************************************************************/
    816 
    817 static void
    818 OpnDoLoadTable (
    819     ACPI_PARSE_OBJECT       *Op)
    820 {
    821     ACPI_PARSE_OBJECT       *Next;
    822 
    823 
    824     /* Opcode is parent node */
    825     /* First child is the table signature */
    826 
    827     Next = Op->Asl.Child;
    828 
    829     /* Second child is the OEM ID*/
    830 
    831     Next = Next->Asl.Next;
    832 
    833     /* Third child is the OEM table ID */
    834 
    835     Next = Next->Asl.Next;
    836 
    837     /* Fourth child is the RootPath string */
    838 
    839     Next = Next->Asl.Next;
    840     if (Next->Asl.ParseOpcode == PARSEOP_ZERO)
    841     {
    842         Next->Asl.ParseOpcode    = PARSEOP_STRING_LITERAL;
    843         Next->Asl.Value.String   = "\\";
    844         Next->Asl.AmlLength      = 2;
    845         OpcGenerateAmlOpcode (Next);
    846     }
    847 
    848 #ifdef ASL_FUTURE_IMPLEMENTATION
    849 
    850     /* TBD: NOT IMPLEMENTED */
    851     /* Fifth child is the [optional] ParameterPathString */
    852     /* Sixth child is the [optional] ParameterData */
    853 
    854     Next = Next->Asl.Next;
    855     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
    856     {
    857         Next->Asl.AmlLength = 1;
    858         Next->Asl.ParseOpcode = ZERO;
    859         OpcGenerateAmlOpcode (Next);
    860     }
    861 
    862 
    863     Next = Next->Asl.Next;
    864     if (Next->Asl.ParseOpcode == DEFAULT_ARG)
    865     {
    866         Next->Asl.AmlLength = 1;
    867         Next->Asl.ParseOpcode = ZERO;
    868         OpcGenerateAmlOpcode (Next);
    869     }
    870 #endif
    871 }
    872 
    873 
    874 /*******************************************************************************
    875  *
    876  * FUNCTION:    OpnDoDefinitionBlock
    877  *
    878  * PARAMETERS:  Op        - The parent parse node
    879  *
    880  * RETURN:      None
    881  *
    882  * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword
    883  *
    884  ******************************************************************************/
    885 
    886 static void
    887 OpnDoDefinitionBlock (
    888     ACPI_PARSE_OBJECT       *Op)
    889 {
    890     ACPI_PARSE_OBJECT       *Child;
    891     ACPI_SIZE               Length;
    892     UINT32                  i;
    893     char                    *Filename;
    894 
    895 
    896     /*
    897      * These nodes get stuffed into the table header. They are special
    898      * cased when the table is written to the output file.
    899      *
    900      * Mark all of these nodes as non-usable so they won't get output
    901      * as AML opcodes!
    902      */
    903 
    904     /* Get AML filename. Use it if non-null */
    905 
    906     Child = Op->Asl.Child;
    907     if (Child->Asl.Value.Buffer  &&
    908         *Child->Asl.Value.Buffer &&
    909         (Gbl_UseDefaultAmlFilename))
    910     {
    911         /*
    912          * We will use the AML filename that is embedded in the source file
    913          * for the output filename.
    914          */
    915         Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) +
    916             strlen ((char *) Child->Asl.Value.Buffer) + 1);
    917 
    918         /* Prepend the current directory path */
    919 
    920         strcpy (Filename, Gbl_DirectoryPath);
    921         strcat (Filename, (char *) Child->Asl.Value.Buffer);
    922 
    923         Gbl_OutputFilenamePrefix = Filename;
    924         UtConvertBackslashes (Gbl_OutputFilenamePrefix);
    925     }
    926     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    927 
    928     /* Signature */
    929 
    930     Child = Child->Asl.Next;
    931     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    932     if (Child->Asl.Value.String)
    933     {
    934         Gbl_TableSignature = Child->Asl.Value.String;
    935         if (strlen (Gbl_TableSignature) != 4)
    936         {
    937             AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
    938                 "Length not exactly 4");
    939         }
    940 
    941         for (i = 0; i < 4; i++)
    942         {
    943             if (!isalnum ((int) Gbl_TableSignature[i]))
    944             {
    945                 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child,
    946                     "Contains non-alphanumeric characters");
    947             }
    948         }
    949     }
    950 
    951     /* Revision */
    952 
    953     Child = Child->Asl.Next;
    954     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    955     /*
    956      * We used the revision to set the integer width earlier
    957      */
    958 
    959     /* OEMID */
    960 
    961     Child = Child->Asl.Next;
    962     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    963 
    964     /* OEM TableID */
    965 
    966     Child = Child->Asl.Next;
    967     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    968     if (Child->Asl.Value.String)
    969     {
    970         Length = strlen (Child->Asl.Value.String);
    971         Gbl_TableId = UtStringCacheCalloc (Length + 1);
    972         strcpy (Gbl_TableId, Child->Asl.Value.String);
    973 
    974         /*
    975          * Convert anything non-alphanumeric to an underscore. This
    976          * allows us to use the TableID to generate unique C symbols.
    977          */
    978         for (i = 0; i < Length; i++)
    979         {
    980             if (!isalnum ((int) Gbl_TableId[i]))
    981             {
    982                 Gbl_TableId[i] = '_';
    983             }
    984         }
    985     }
    986 
    987     /* OEM Revision */
    988 
    989     Child = Child->Asl.Next;
    990     Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    991 }
    992 
    993 
    994 /*******************************************************************************
    995  *
    996  * FUNCTION:    UtGetArg
    997  *
    998  * PARAMETERS:  Op              - Get an argument for this op
    999  *              Argn            - Nth argument to get
   1000  *
   1001  * RETURN:      The argument (as an Op object). NULL if argument does not exist
   1002  *
   1003  * DESCRIPTION: Get the specified op's argument (peer)
   1004  *
   1005  ******************************************************************************/
   1006 
   1007 ACPI_PARSE_OBJECT *
   1008 UtGetArg (
   1009     ACPI_PARSE_OBJECT       *Op,
   1010     UINT32                  Argn)
   1011 {
   1012     ACPI_PARSE_OBJECT       *Arg = NULL;
   1013 
   1014 
   1015     /* Get the requested argument object */
   1016 
   1017     Arg = Op->Asl.Child;
   1018     while (Arg && Argn)
   1019     {
   1020         Argn--;
   1021         Arg = Arg->Asl.Next;
   1022     }
   1023 
   1024     return (Arg);
   1025 }
   1026 
   1027 
   1028 /*******************************************************************************
   1029  *
   1030  * FUNCTION:    OpnAttachNameToNode
   1031  *
   1032  * PARAMETERS:  Op        - The parent parse node
   1033  *
   1034  * RETURN:      None
   1035  *
   1036  * DESCRIPTION: For the named ASL/AML operators, get the actual name from the
   1037  *              argument list and attach it to the parent node so that we
   1038  *              can get to it quickly later.
   1039  *
   1040  ******************************************************************************/
   1041 
   1042 static void
   1043 OpnAttachNameToNode (
   1044     ACPI_PARSE_OBJECT       *Op)
   1045 {
   1046     ACPI_PARSE_OBJECT       *Child = NULL;
   1047 
   1048 
   1049     if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL)
   1050     {
   1051         Child = UtGetArg (Op, 0);
   1052     }
   1053     else switch (Op->Asl.AmlOpcode)
   1054     {
   1055     case AML_DATA_REGION_OP:
   1056     case AML_DEVICE_OP:
   1057     case AML_EVENT_OP:
   1058     case AML_METHOD_OP:
   1059     case AML_MUTEX_OP:
   1060     case AML_REGION_OP:
   1061     case AML_POWER_RES_OP:
   1062     case AML_PROCESSOR_OP:
   1063     case AML_THERMAL_ZONE_OP:
   1064     case AML_NAME_OP:
   1065     case AML_SCOPE_OP:
   1066 
   1067         Child = UtGetArg (Op, 0);
   1068         break;
   1069 
   1070     case AML_ALIAS_OP:
   1071 
   1072         Child = UtGetArg (Op, 1);
   1073         break;
   1074 
   1075     case AML_CREATE_BIT_FIELD_OP:
   1076     case AML_CREATE_BYTE_FIELD_OP:
   1077     case AML_CREATE_WORD_FIELD_OP:
   1078     case AML_CREATE_DWORD_FIELD_OP:
   1079     case AML_CREATE_QWORD_FIELD_OP:
   1080 
   1081         Child = UtGetArg (Op, 2);
   1082         break;
   1083 
   1084     case AML_CREATE_FIELD_OP:
   1085 
   1086         Child = UtGetArg (Op, 3);
   1087         break;
   1088 
   1089     case AML_BANK_FIELD_OP:
   1090     case AML_INDEX_FIELD_OP:
   1091     case AML_FIELD_OP:
   1092 
   1093         return;
   1094 
   1095     default:
   1096 
   1097         return;
   1098     }
   1099 
   1100     if (Child)
   1101     {
   1102         UtAttachNamepathToOwner (Op, Child);
   1103     }
   1104 }
   1105 
   1106 
   1107 /*******************************************************************************
   1108  *
   1109  * FUNCTION:    OpnGenerateAmlOperands
   1110  *
   1111  * PARAMETERS:  Op        - The parent parse node
   1112  *
   1113  * RETURN:      None
   1114  *
   1115  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
   1116  *              complex AML opcodes require processing of the child nodes
   1117  *              (arguments/operands).
   1118  *
   1119  ******************************************************************************/
   1120 
   1121 void
   1122 OpnGenerateAmlOperands (
   1123     ACPI_PARSE_OBJECT       *Op)
   1124 {
   1125 
   1126 
   1127     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
   1128     {
   1129         return;
   1130     }
   1131 
   1132     switch (Op->Asl.ParseOpcode)
   1133     {
   1134     case PARSEOP_DEFINITIONBLOCK:
   1135 
   1136         OpnDoDefinitionBlock (Op);
   1137         break;
   1138 
   1139     case PARSEOP_METHOD:
   1140 
   1141         OpnDoMethod (Op);
   1142         break;
   1143 
   1144     case PARSEOP_MUTEX:
   1145 
   1146         OpnDoMutex (Op);
   1147         break;
   1148 
   1149     case PARSEOP_FIELD:
   1150 
   1151         OpnDoField (Op);
   1152         break;
   1153 
   1154     case PARSEOP_INDEXFIELD:
   1155 
   1156         OpnDoIndexField (Op);
   1157         break;
   1158 
   1159     case PARSEOP_BANKFIELD:
   1160 
   1161         OpnDoBankField (Op);
   1162         break;
   1163 
   1164     case PARSEOP_BUFFER:
   1165 
   1166         OpnDoBuffer (Op);
   1167         break;
   1168 
   1169     case PARSEOP_LOADTABLE:
   1170 
   1171         OpnDoLoadTable (Op);
   1172         break;
   1173 
   1174     case PARSEOP_OPERATIONREGION:
   1175 
   1176         OpnDoRegion (Op);
   1177         break;
   1178 
   1179     case PARSEOP_RESOURCETEMPLATE:
   1180 
   1181         RsDoResourceTemplate (Op);
   1182         break;
   1183 
   1184     case PARSEOP_NAMESEG:
   1185     case PARSEOP_NAMESTRING:
   1186     case PARSEOP_METHODCALL:
   1187     case PARSEOP_STRING_LITERAL:
   1188 
   1189         break;
   1190 
   1191     default:
   1192 
   1193         break;
   1194     }
   1195 
   1196     /* TBD: move */
   1197 
   1198     OpnAttachNameToNode (Op);
   1199 }
   1200