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