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