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 <contrib/dev/acpica/compiler/aslcompiler.h> 119 #include "aslcompiler.y.h" 120 #include <contrib/dev/acpica/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