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