1 /****************************************************************************** 2 * 3 * Module Name: asloperands - AML operand processing 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/compiler/aslcompiler.h> 46 #include "aslcompiler.y.h" 47 #include <contrib/dev/acpica/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 302 case PARSEOP_OFFSET: 303 304 /* New offset into the field */ 305 306 PkgLengthNode = Next->Asl.Child; 307 NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8; 308 309 /* 310 * Examine the specified offset in relation to the 311 * current offset counter. 312 */ 313 if (NewBitOffset < CurrentBitOffset) 314 { 315 /* 316 * Not allowed to specify a backwards offset! 317 * Issue error and ignore this node. 318 */ 319 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode, 320 NULL); 321 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 322 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 323 } 324 else if (NewBitOffset == CurrentBitOffset) 325 { 326 /* 327 * Offset is redundant; we don't need to output an 328 * offset opcode. Just set these nodes to default 329 */ 330 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 331 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 332 } 333 else 334 { 335 /* 336 * Valid new offset - set the value to be inserted into the AML 337 * and update the offset counter. 338 */ 339 PkgLengthNode->Asl.Value.Integer = 340 NewBitOffset - CurrentBitOffset; 341 CurrentBitOffset = NewBitOffset; 342 } 343 break; 344 345 346 case PARSEOP_NAMESEG: 347 case PARSEOP_RESERVED_BYTES: 348 349 /* Named or reserved field entry */ 350 351 PkgLengthNode = Next->Asl.Child; 352 NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer; 353 CurrentBitOffset += NewBitOffset; 354 355 /* Save the current AccessAs value for error checking later */ 356 357 switch (AccessType) 358 { 359 case AML_FIELD_ACCESS_ANY: 360 case AML_FIELD_ACCESS_BYTE: 361 case AML_FIELD_ACCESS_BUFFER: 362 default: 363 MinimumLength = 8; 364 break; 365 366 case AML_FIELD_ACCESS_WORD: 367 MinimumLength = 16; 368 break; 369 370 case AML_FIELD_ACCESS_DWORD: 371 MinimumLength = 32; 372 break; 373 374 case AML_FIELD_ACCESS_QWORD: 375 MinimumLength = 64; 376 break; 377 } 378 379 PkgLengthNode->Asl.ExtraValue = MinimumLength; 380 break; 381 382 default: 383 /* All supported field opcodes must appear above */ 384 break; 385 } 386 387 /* Move on to next entry in the field list */ 388 389 Next = Next->Asl.Next; 390 } 391 } 392 393 394 /******************************************************************************* 395 * 396 * FUNCTION: OpnDoField 397 * 398 * PARAMETERS: Op - The parent parse node 399 * 400 * RETURN: None 401 * 402 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword 403 * 404 ******************************************************************************/ 405 406 static void 407 OpnDoField ( 408 ACPI_PARSE_OBJECT *Op) 409 { 410 ACPI_PARSE_OBJECT *Next; 411 412 413 /* Opcode is parent node */ 414 /* First child is field name */ 415 416 Next = Op->Asl.Child; 417 418 /* Second child is the AccessType */ 419 420 OpnDoFieldCommon (Op, Next->Asl.Next); 421 } 422 423 424 /******************************************************************************* 425 * 426 * FUNCTION: OpnDoIndexField 427 * 428 * PARAMETERS: Op - The parent parse node 429 * 430 * RETURN: None 431 * 432 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword 433 * 434 ******************************************************************************/ 435 436 static void 437 OpnDoIndexField ( 438 ACPI_PARSE_OBJECT *Op) 439 { 440 ACPI_PARSE_OBJECT *Next; 441 442 443 /* Opcode is parent node */ 444 /* First child is the index name */ 445 446 Next = Op->Asl.Child; 447 448 /* Second child is the data name */ 449 450 Next = Next->Asl.Next; 451 452 /* Third child is the AccessType */ 453 454 OpnDoFieldCommon (Op, Next->Asl.Next); 455 } 456 457 458 /******************************************************************************* 459 * 460 * FUNCTION: OpnDoBankField 461 * 462 * PARAMETERS: Op - The parent parse node 463 * 464 * RETURN: None 465 * 466 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword 467 * 468 ******************************************************************************/ 469 470 static void 471 OpnDoBankField ( 472 ACPI_PARSE_OBJECT *Op) 473 { 474 ACPI_PARSE_OBJECT *Next; 475 476 477 /* Opcode is parent node */ 478 /* First child is the region name */ 479 480 Next = Op->Asl.Child; 481 482 /* Second child is the bank name */ 483 484 Next = Next->Asl.Next; 485 486 /* Third child is the bank value */ 487 488 Next = Next->Asl.Next; 489 490 /* Fourth child is the AccessType */ 491 492 OpnDoFieldCommon (Op, Next->Asl.Next); 493 } 494 495 496 /******************************************************************************* 497 * 498 * FUNCTION: OpnDoRegion 499 * 500 * PARAMETERS: Op - The parent parse node 501 * 502 * RETURN: None 503 * 504 * DESCRIPTION: Tries to get the length of the region. Can only do this at 505 * compile time if the length is a constant. 506 * 507 ******************************************************************************/ 508 509 static void 510 OpnDoRegion ( 511 ACPI_PARSE_OBJECT *Op) 512 { 513 ACPI_PARSE_OBJECT *Next; 514 515 516 /* Opcode is parent node */ 517 /* First child is the region name */ 518 519 Next = Op->Asl.Child; 520 521 /* Second child is the space ID*/ 522 523 Next = Next->Asl.Next; 524 525 /* Third child is the region offset */ 526 527 Next = Next->Asl.Next; 528 529 /* Fourth child is the region length */ 530 531 Next = Next->Asl.Next; 532 if (Next->Asl.ParseOpcode == PARSEOP_INTEGER) 533 { 534 Op->Asl.Value.Integer = Next->Asl.Value.Integer; 535 } 536 else 537 { 538 Op->Asl.Value.Integer = ACPI_UINT64_MAX; 539 } 540 } 541 542 543 /******************************************************************************* 544 * 545 * FUNCTION: OpnDoBuffer 546 * 547 * PARAMETERS: Op - The parent parse node 548 * 549 * RETURN: None 550 * 551 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We 552 * build a single raw byte buffer from the initialization nodes, 553 * each parse node contains a buffer byte. 554 * 555 ******************************************************************************/ 556 557 static void 558 OpnDoBuffer ( 559 ACPI_PARSE_OBJECT *Op) 560 { 561 ACPI_PARSE_OBJECT *InitializerOp; 562 ACPI_PARSE_OBJECT *BufferLengthOp; 563 564 /* Optional arguments for this opcode with defaults */ 565 566 UINT32 BufferLength = 0; 567 568 569 /* Opcode and package length first */ 570 /* Buffer Length is next, followed by the initializer list */ 571 572 BufferLengthOp = Op->Asl.Child; 573 InitializerOp = BufferLengthOp->Asl.Next; 574 575 /* 576 * If the BufferLength is not an INTEGER or was not specified in the ASL 577 * (DEFAULT_ARG), it is a TermArg that is 578 * evaluated at run-time, and we are therefore finished. 579 */ 580 if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) && 581 (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 582 { 583 return; 584 } 585 586 /* 587 * We want to count the number of items in the initializer list, because if 588 * it is larger than the buffer length, we will define the buffer size 589 * to be the size of the initializer list (as per the ACPI Specification) 590 */ 591 switch (InitializerOp->Asl.ParseOpcode) 592 { 593 case PARSEOP_INTEGER: 594 case PARSEOP_BYTECONST: 595 case PARSEOP_WORDCONST: 596 case PARSEOP_DWORDCONST: 597 598 /* The peer list contains the byte list (if any...) */ 599 600 while (InitializerOp) 601 { 602 /* For buffers, this is a list of raw bytes */ 603 604 InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 605 InitializerOp->Asl.AmlLength = 1; 606 InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 607 608 BufferLength++; 609 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 610 } 611 break; 612 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 628 case PARSEOP_RAW_DATA: 629 630 /* Buffer nodes are already initialized (e.g. Unicode operator) */ 631 return; 632 633 634 case PARSEOP_DEFAULT_ARG: 635 break; 636 637 638 default: 639 AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp, 640 "Unknown buffer initializer opcode"); 641 printf ("Unknown buffer initializer opcode [%s]\n", 642 UtGetOpName (InitializerOp->Asl.ParseOpcode)); 643 return; 644 } 645 646 /* Check if initializer list is longer than the buffer length */ 647 648 if (BufferLengthOp->Asl.Value.Integer > BufferLength) 649 { 650 BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer; 651 } 652 653 if (!BufferLength) 654 { 655 /* No length AND no items -- issue notice */ 656 657 AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL); 658 659 /* But go ahead and put the buffer length of zero into the AML */ 660 } 661 662 /* 663 * Just set the buffer size node to be the buffer length, regardless 664 * of whether it was previously an integer or a default_arg placeholder 665 */ 666 BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; 667 BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP; 668 BufferLengthOp->Asl.Value.Integer = BufferLength; 669 670 (void) OpcSetOptimalIntegerSize (BufferLengthOp); 671 672 /* Remaining nodes are handled via the tree walk */ 673 } 674 675 676 /******************************************************************************* 677 * 678 * FUNCTION: OpnDoPackage 679 * 680 * PARAMETERS: Op - The parent parse node 681 * 682 * RETURN: None 683 * 684 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE: 685 * can only be called after constants have been folded, to ensure 686 * that the PackageLength operand has been fully reduced. 687 * 688 ******************************************************************************/ 689 690 void 691 OpnDoPackage ( 692 ACPI_PARSE_OBJECT *Op) 693 { 694 ACPI_PARSE_OBJECT *InitializerOp; 695 ACPI_PARSE_OBJECT *PackageLengthOp; 696 UINT32 PackageLength = 0; 697 698 699 /* Opcode and package length first, followed by the initializer list */ 700 701 PackageLengthOp = Op->Asl.Child; 702 InitializerOp = PackageLengthOp->Asl.Next; 703 704 /* Count the number of items in the initializer list */ 705 706 if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 707 { 708 /* The peer list contains the byte list (if any...) */ 709 710 while (InitializerOp) 711 { 712 PackageLength++; 713 InitializerOp = InitializerOp->Asl.Next; 714 } 715 } 716 717 /* If package length is a constant, compare to the initializer list */ 718 719 if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || 720 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)) 721 { 722 if (PackageLengthOp->Asl.Value.Integer > PackageLength) 723 { 724 /* 725 * Allow package length to be longer than the initializer 726 * list -- but if the length of initializer list is nonzero, 727 * issue a message since this is probably a coding error, 728 * even though technically legal. 729 */ 730 if (PackageLength > 0) 731 { 732 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT, 733 PackageLengthOp, NULL); 734 } 735 736 PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer; 737 } 738 else if (PackageLengthOp->Asl.Value.Integer < PackageLength) 739 { 740 /* 741 * The package length is smaller than the length of the 742 * initializer list. This is an error as per the ACPI spec. 743 */ 744 AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG, 745 PackageLengthOp, NULL); 746 } 747 } 748 749 if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 750 { 751 /* 752 * This is the case if the PackageLength was left empty - Package() 753 * The package length becomes the length of the initializer list 754 */ 755 Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER; 756 Op->Asl.Child->Asl.Value.Integer = PackageLength; 757 758 /* Set the AML opcode */ 759 760 (void) OpcSetOptimalIntegerSize (Op->Asl.Child); 761 } 762 763 /* If not a variable-length package, check for a zero package length */ 764 765 if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || 766 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST) || 767 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO) || 768 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)) 769 { 770 if (!PackageLength) 771 { 772 /* No length AND no initializer list -- issue a remark */ 773 774 AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH, 775 PackageLengthOp, NULL); 776 777 /* But go ahead and put the buffer length of zero into the AML */ 778 } 779 } 780 781 /* 782 * If the PackageLength is a constant <= 255, we can change the 783 * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode. 784 */ 785 if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 786 (Op->Asl.Child->Asl.Value.Integer <= 255)) || 787 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) || 788 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)|| 789 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO)) 790 { 791 Op->Asl.AmlOpcode = AML_PACKAGE_OP; 792 Op->Asl.ParseOpcode = PARSEOP_PACKAGE; 793 794 /* 795 * Just set the package size node to be the package length, regardless 796 * of whether it was previously an integer or a default_arg placeholder 797 */ 798 PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 799 PackageLengthOp->Asl.AmlLength = 1; 800 PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 801 PackageLengthOp->Asl.Value.Integer = PackageLength; 802 } 803 804 /* Remaining nodes are handled via the tree walk */ 805 } 806 807 808 /******************************************************************************* 809 * 810 * FUNCTION: OpnDoLoadTable 811 * 812 * PARAMETERS: Op - The parent parse node 813 * 814 * RETURN: None 815 * 816 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword. 817 * 818 ******************************************************************************/ 819 820 static void 821 OpnDoLoadTable ( 822 ACPI_PARSE_OBJECT *Op) 823 { 824 ACPI_PARSE_OBJECT *Next; 825 826 827 /* Opcode is parent node */ 828 /* First child is the table signature */ 829 830 Next = Op->Asl.Child; 831 832 /* Second child is the OEM ID*/ 833 834 Next = Next->Asl.Next; 835 836 /* Third child is the OEM table ID */ 837 838 Next = Next->Asl.Next; 839 840 /* Fourth child is the RootPath string */ 841 842 Next = Next->Asl.Next; 843 if (Next->Asl.ParseOpcode == PARSEOP_ZERO) 844 { 845 Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; 846 Next->Asl.Value.String = "\\"; 847 Next->Asl.AmlLength = 2; 848 OpcGenerateAmlOpcode (Next); 849 } 850 851 #ifdef ASL_FUTURE_IMPLEMENTATION 852 853 /* TBD: NOT IMPLEMENTED */ 854 /* Fifth child is the [optional] ParameterPathString */ 855 /* Sixth child is the [optional] ParameterData */ 856 857 Next = Next->Asl.Next; 858 if (Next->Asl.ParseOpcode == DEFAULT_ARG) 859 { 860 Next->Asl.AmlLength = 1; 861 Next->Asl.ParseOpcode = ZERO; 862 OpcGenerateAmlOpcode (Next); 863 } 864 865 866 Next = Next->Asl.Next; 867 if (Next->Asl.ParseOpcode == DEFAULT_ARG) 868 { 869 Next->Asl.AmlLength = 1; 870 Next->Asl.ParseOpcode = ZERO; 871 OpcGenerateAmlOpcode (Next); 872 } 873 #endif 874 } 875 876 877 /******************************************************************************* 878 * 879 * FUNCTION: OpnDoDefinitionBlock 880 * 881 * PARAMETERS: Op - The parent parse node 882 * 883 * RETURN: None 884 * 885 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword 886 * 887 ******************************************************************************/ 888 889 static void 890 OpnDoDefinitionBlock ( 891 ACPI_PARSE_OBJECT *Op) 892 { 893 ACPI_PARSE_OBJECT *Child; 894 ACPI_SIZE Length; 895 UINT32 i; 896 char *Filename; 897 898 899 /* 900 * These nodes get stuffed into the table header. They are special 901 * cased when the table is written to the output file. 902 * 903 * Mark all of these nodes as non-usable so they won't get output 904 * as AML opcodes! 905 */ 906 907 /* Get AML filename. Use it if non-null */ 908 909 Child = Op->Asl.Child; 910 if (Child->Asl.Value.Buffer && 911 *Child->Asl.Value.Buffer && 912 (Gbl_UseDefaultAmlFilename)) 913 { 914 /* 915 * We will use the AML filename that is embedded in the source file 916 * for the output filename. 917 */ 918 Filename = ACPI_ALLOCATE (strlen (Gbl_DirectoryPath) + 919 strlen ((char *) Child->Asl.Value.Buffer) + 1); 920 921 /* Prepend the current directory path */ 922 923 strcpy (Filename, Gbl_DirectoryPath); 924 strcat (Filename, (char *) Child->Asl.Value.Buffer); 925 926 Gbl_OutputFilenamePrefix = Filename; 927 } 928 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 929 930 /* Signature */ 931 932 Child = Child->Asl.Next; 933 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 934 if (Child->Asl.Value.String) 935 { 936 Gbl_TableSignature = Child->Asl.Value.String; 937 if (ACPI_STRLEN (Gbl_TableSignature) != 4) 938 { 939 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, 940 "Length not exactly 4"); 941 } 942 943 for (i = 0; i < 4; i++) 944 { 945 if (!isalnum ((int) Gbl_TableSignature[i])) 946 { 947 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, 948 "Contains non-alphanumeric characters"); 949 } 950 } 951 } 952 953 /* Revision */ 954 955 Child = Child->Asl.Next; 956 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 957 /* 958 * We used the revision to set the integer width earlier 959 */ 960 961 /* OEMID */ 962 963 Child = Child->Asl.Next; 964 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 965 966 /* OEM TableID */ 967 968 Child = Child->Asl.Next; 969 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 970 if (Child->Asl.Value.String) 971 { 972 Length = ACPI_STRLEN (Child->Asl.Value.String); 973 Gbl_TableId = AcpiOsAllocate (Length + 1); 974 ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String); 975 976 for (i = 0; i < Length; i++) 977 { 978 if (Gbl_TableId[i] == ' ') 979 { 980 Gbl_TableId[i] = 0; 981 break; 982 } 983 } 984 } 985 986 /* OEM Revision */ 987 988 Child = Child->Asl.Next; 989 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 990 } 991 992 993 /******************************************************************************* 994 * 995 * FUNCTION: UtGetArg 996 * 997 * PARAMETERS: Op - Get an argument for this op 998 * Argn - Nth argument to get 999 * 1000 * RETURN: The argument (as an Op object). NULL if argument does not exist 1001 * 1002 * DESCRIPTION: Get the specified op's argument (peer) 1003 * 1004 ******************************************************************************/ 1005 1006 ACPI_PARSE_OBJECT * 1007 UtGetArg ( 1008 ACPI_PARSE_OBJECT *Op, 1009 UINT32 Argn) 1010 { 1011 ACPI_PARSE_OBJECT *Arg = NULL; 1012 1013 1014 /* Get the requested argument object */ 1015 1016 Arg = Op->Asl.Child; 1017 while (Arg && Argn) 1018 { 1019 Argn--; 1020 Arg = Arg->Asl.Next; 1021 } 1022 1023 return (Arg); 1024 } 1025 1026 1027 /******************************************************************************* 1028 * 1029 * FUNCTION: OpnAttachNameToNode 1030 * 1031 * PARAMETERS: Op - The parent parse node 1032 * 1033 * RETURN: None 1034 * 1035 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the 1036 * argument list and attach it to the parent node so that we 1037 * can get to it quickly later. 1038 * 1039 ******************************************************************************/ 1040 1041 static void 1042 OpnAttachNameToNode ( 1043 ACPI_PARSE_OBJECT *Op) 1044 { 1045 ACPI_PARSE_OBJECT *Child = NULL; 1046 1047 1048 if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) 1049 { 1050 Child = UtGetArg (Op, 0); 1051 } 1052 else switch (Op->Asl.AmlOpcode) 1053 { 1054 case AML_DATA_REGION_OP: 1055 case AML_DEVICE_OP: 1056 case AML_EVENT_OP: 1057 case AML_METHOD_OP: 1058 case AML_MUTEX_OP: 1059 case AML_REGION_OP: 1060 case AML_POWER_RES_OP: 1061 case AML_PROCESSOR_OP: 1062 case AML_THERMAL_ZONE_OP: 1063 case AML_NAME_OP: 1064 case AML_SCOPE_OP: 1065 1066 Child = UtGetArg (Op, 0); 1067 break; 1068 1069 case AML_ALIAS_OP: 1070 1071 Child = UtGetArg (Op, 1); 1072 break; 1073 1074 case AML_CREATE_BIT_FIELD_OP: 1075 case AML_CREATE_BYTE_FIELD_OP: 1076 case AML_CREATE_WORD_FIELD_OP: 1077 case AML_CREATE_DWORD_FIELD_OP: 1078 case AML_CREATE_QWORD_FIELD_OP: 1079 1080 Child = UtGetArg (Op, 2); 1081 break; 1082 1083 case AML_CREATE_FIELD_OP: 1084 1085 Child = UtGetArg (Op, 3); 1086 break; 1087 1088 case AML_BANK_FIELD_OP: 1089 case AML_INDEX_FIELD_OP: 1090 case AML_FIELD_OP: 1091 1092 return; 1093 1094 default: 1095 return; 1096 } 1097 1098 if (Child) 1099 { 1100 UtAttachNamepathToOwner (Op, Child); 1101 } 1102 } 1103 1104 1105 /******************************************************************************* 1106 * 1107 * FUNCTION: OpnGenerateAmlOperands 1108 * 1109 * PARAMETERS: Op - The parent parse node 1110 * 1111 * RETURN: None 1112 * 1113 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 1114 * complex AML opcodes require processing of the child nodes 1115 * (arguments/operands). 1116 * 1117 ******************************************************************************/ 1118 1119 void 1120 OpnGenerateAmlOperands ( 1121 ACPI_PARSE_OBJECT *Op) 1122 { 1123 1124 1125 if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 1126 { 1127 return; 1128 } 1129 1130 switch (Op->Asl.ParseOpcode) 1131 { 1132 case PARSEOP_DEFINITIONBLOCK: 1133 OpnDoDefinitionBlock (Op); 1134 break; 1135 1136 case PARSEOP_METHOD: 1137 OpnDoMethod (Op); 1138 break; 1139 1140 case PARSEOP_MUTEX: 1141 OpnDoMutex (Op); 1142 break; 1143 1144 case PARSEOP_FIELD: 1145 OpnDoField (Op); 1146 break; 1147 1148 case PARSEOP_INDEXFIELD: 1149 OpnDoIndexField (Op); 1150 break; 1151 1152 case PARSEOP_BANKFIELD: 1153 OpnDoBankField (Op); 1154 break; 1155 1156 case PARSEOP_BUFFER: 1157 OpnDoBuffer (Op); 1158 break; 1159 1160 case PARSEOP_LOADTABLE: 1161 OpnDoLoadTable (Op); 1162 break; 1163 1164 case PARSEOP_OPERATIONREGION: 1165 OpnDoRegion (Op); 1166 break; 1167 1168 case PARSEOP_RESOURCETEMPLATE: 1169 RsDoResourceTemplate (Op); 1170 break; 1171 1172 case PARSEOP_NAMESEG: 1173 case PARSEOP_NAMESTRING: 1174 case PARSEOP_METHODCALL: 1175 case PARSEOP_STRING_LITERAL: 1176 break; 1177 1178 default: 1179 break; 1180 } 1181 1182 /* TBD: move */ 1183 1184 OpnAttachNameToNode (Op); 1185 } 1186