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