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