1 /****************************************************************************** 2 * 3 * Module Name: asloperands - AML operand processing 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #include <contrib/dev/acpica/compiler/aslcompiler.h> 45 #include "aslcompiler.y.h" 46 #include <contrib/dev/acpica/include/amlcode.h> 47 48 #define _COMPONENT ACPI_COMPILER 49 ACPI_MODULE_NAME ("asloperands") 50 51 /* Local prototypes */ 52 53 static void 54 OpnDoField ( 55 ACPI_PARSE_OBJECT *Op); 56 57 static void 58 OpnDoBankField ( 59 ACPI_PARSE_OBJECT *Op); 60 61 static void 62 OpnDoBuffer ( 63 ACPI_PARSE_OBJECT *Op); 64 65 static void 66 OpnDoDefinitionBlock ( 67 ACPI_PARSE_OBJECT *Op); 68 69 static void 70 OpnDoFieldCommon ( 71 ACPI_PARSE_OBJECT *FieldOp, 72 ACPI_PARSE_OBJECT *Op); 73 74 static void 75 OpnDoIndexField ( 76 ACPI_PARSE_OBJECT *Op); 77 78 static void 79 OpnDoLoadTable ( 80 ACPI_PARSE_OBJECT *Op); 81 82 static void 83 OpnDoMethod ( 84 ACPI_PARSE_OBJECT *Op); 85 86 static void 87 OpnDoMutex ( 88 ACPI_PARSE_OBJECT *Op); 89 90 static void 91 OpnDoRegion ( 92 ACPI_PARSE_OBJECT *Op); 93 94 static void 95 OpnAttachNameToNode ( 96 ACPI_PARSE_OBJECT *Op); 97 98 99 /******************************************************************************* 100 * 101 * FUNCTION: OpnDoMutex 102 * 103 * PARAMETERS: Op - The parent parse node 104 * 105 * RETURN: None 106 * 107 * DESCRIPTION: Construct the operands for the MUTEX ASL keyword. 108 * 109 ******************************************************************************/ 110 111 static void 112 OpnDoMutex ( 113 ACPI_PARSE_OBJECT *Op) 114 { 115 ACPI_PARSE_OBJECT *Next; 116 117 118 Next = Op->Asl.Child; 119 Next = Next->Asl.Next; 120 121 if (Next->Asl.Value.Integer > 15) 122 { 123 AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); 124 } 125 return; 126 } 127 128 129 /******************************************************************************* 130 * 131 * FUNCTION: OpnDoMethod 132 * 133 * PARAMETERS: Op - The parent parse node 134 * 135 * RETURN: None 136 * 137 * DESCRIPTION: Construct the operands for the METHOD ASL keyword. 138 * 139 ******************************************************************************/ 140 141 static void 142 OpnDoMethod ( 143 ACPI_PARSE_OBJECT *Op) 144 { 145 ACPI_PARSE_OBJECT *Next; 146 147 /* Optional arguments for this opcode with defaults */ 148 149 UINT8 NumArgs = 0; 150 UINT8 Serialized = 0; 151 UINT8 Concurrency = 0; 152 UINT8 MethodFlags; 153 154 155 /* Opcode and package length first */ 156 /* Method name */ 157 158 Next = Op->Asl.Child; 159 160 /* Num args */ 161 162 Next = Next->Asl.Next; 163 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 164 { 165 NumArgs = (UINT8) Next->Asl.Value.Integer; 166 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 167 } 168 169 /* Serialized Flag */ 170 171 Next = Next->Asl.Next; 172 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 173 { 174 Serialized = (UINT8) Next->Asl.Value.Integer; 175 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 176 } 177 178 /* Concurrency value (valid values are 0-15) */ 179 180 Next = Next->Asl.Next; 181 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 182 { 183 /* This is a ByteConstExpr, so eval the constant now */ 184 185 OpcAmlConstantWalk (Next, 0, NULL); 186 187 if (Next->Asl.Value.Integer > 15) 188 { 189 AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); 190 } 191 192 Concurrency = (UINT8) Next->Asl.Value.Integer; 193 } 194 195 /* Put the bits in their proper places */ 196 197 MethodFlags = (UINT8) 198 ((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 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 case PARSEOP_NAMESEG: 346 case PARSEOP_RESERVED_BYTES: 347 348 /* Named or reserved field entry */ 349 350 PkgLengthNode = Next->Asl.Child; 351 NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer; 352 CurrentBitOffset += NewBitOffset; 353 354 /* Save the current AccessAs value for error checking later */ 355 356 switch (AccessType) 357 { 358 case AML_FIELD_ACCESS_ANY: 359 case AML_FIELD_ACCESS_BYTE: 360 case AML_FIELD_ACCESS_BUFFER: 361 default: 362 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 384 /* All supported field opcodes must appear above */ 385 386 break; 387 } 388 389 /* Move on to next entry in the field list */ 390 391 Next = Next->Asl.Next; 392 } 393 } 394 395 396 /******************************************************************************* 397 * 398 * FUNCTION: OpnDoField 399 * 400 * PARAMETERS: Op - The parent parse node 401 * 402 * RETURN: None 403 * 404 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword 405 * 406 ******************************************************************************/ 407 408 static void 409 OpnDoField ( 410 ACPI_PARSE_OBJECT *Op) 411 { 412 ACPI_PARSE_OBJECT *Next; 413 414 415 /* Opcode is parent node */ 416 /* First child is field name */ 417 418 Next = Op->Asl.Child; 419 420 /* Second child is the AccessType */ 421 422 OpnDoFieldCommon (Op, Next->Asl.Next); 423 } 424 425 426 /******************************************************************************* 427 * 428 * FUNCTION: OpnDoIndexField 429 * 430 * PARAMETERS: Op - The parent parse node 431 * 432 * RETURN: None 433 * 434 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword 435 * 436 ******************************************************************************/ 437 438 static void 439 OpnDoIndexField ( 440 ACPI_PARSE_OBJECT *Op) 441 { 442 ACPI_PARSE_OBJECT *Next; 443 444 445 /* Opcode is parent node */ 446 /* First child is the index name */ 447 448 Next = Op->Asl.Child; 449 450 /* Second child is the data name */ 451 452 Next = Next->Asl.Next; 453 454 /* Third child is the AccessType */ 455 456 OpnDoFieldCommon (Op, Next->Asl.Next); 457 } 458 459 460 /******************************************************************************* 461 * 462 * FUNCTION: OpnDoBankField 463 * 464 * PARAMETERS: Op - The parent parse node 465 * 466 * RETURN: None 467 * 468 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword 469 * 470 ******************************************************************************/ 471 472 static void 473 OpnDoBankField ( 474 ACPI_PARSE_OBJECT *Op) 475 { 476 ACPI_PARSE_OBJECT *Next; 477 478 479 /* Opcode is parent node */ 480 /* First child is the region name */ 481 482 Next = Op->Asl.Child; 483 484 /* Second child is the bank name */ 485 486 Next = Next->Asl.Next; 487 488 /* Third child is the bank value */ 489 490 Next = Next->Asl.Next; 491 492 /* Fourth child is the AccessType */ 493 494 OpnDoFieldCommon (Op, Next->Asl.Next); 495 } 496 497 498 /******************************************************************************* 499 * 500 * FUNCTION: OpnDoRegion 501 * 502 * PARAMETERS: Op - The parent parse node 503 * 504 * RETURN: None 505 * 506 * DESCRIPTION: Tries to get the length of the region. Can only do this at 507 * compile time if the length is a constant. 508 * 509 ******************************************************************************/ 510 511 static void 512 OpnDoRegion ( 513 ACPI_PARSE_OBJECT *Op) 514 { 515 ACPI_PARSE_OBJECT *Next; 516 517 518 /* Opcode is parent node */ 519 /* First child is the region name */ 520 521 Next = Op->Asl.Child; 522 523 /* Second child is the space ID*/ 524 525 Next = Next->Asl.Next; 526 527 /* Third child is the region offset */ 528 529 Next = Next->Asl.Next; 530 531 /* Fourth child is the region length */ 532 533 Next = Next->Asl.Next; 534 if (Next->Asl.ParseOpcode == PARSEOP_INTEGER) 535 { 536 Op->Asl.Value.Integer = Next->Asl.Value.Integer; 537 } 538 else 539 { 540 Op->Asl.Value.Integer = ACPI_UINT64_MAX; 541 } 542 } 543 544 545 /******************************************************************************* 546 * 547 * FUNCTION: OpnDoBuffer 548 * 549 * PARAMETERS: Op - The parent parse node 550 * 551 * RETURN: None 552 * 553 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We 554 * build a single raw byte buffer from the initialization nodes, 555 * each parse node contains a buffer byte. 556 * 557 ******************************************************************************/ 558 559 static void 560 OpnDoBuffer ( 561 ACPI_PARSE_OBJECT *Op) 562 { 563 ACPI_PARSE_OBJECT *InitializerOp; 564 ACPI_PARSE_OBJECT *BufferLengthOp; 565 566 /* Optional arguments for this opcode with defaults */ 567 568 UINT32 BufferLength = 0; 569 570 571 /* Opcode and package length first */ 572 /* Buffer Length is next, followed by the initializer list */ 573 574 BufferLengthOp = Op->Asl.Child; 575 InitializerOp = BufferLengthOp->Asl.Next; 576 577 /* 578 * If the BufferLength is not an INTEGER or was not specified in the ASL 579 * (DEFAULT_ARG), it is a TermArg that is 580 * evaluated at run-time, and we are therefore finished. 581 */ 582 if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) && 583 (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 584 { 585 return; 586 } 587 588 /* 589 * We want to count the number of items in the initializer list, because if 590 * it is larger than the buffer length, we will define the buffer size 591 * to be the size of the initializer list (as per the ACPI Specification) 592 */ 593 switch (InitializerOp->Asl.ParseOpcode) 594 { 595 case PARSEOP_INTEGER: 596 case PARSEOP_BYTECONST: 597 case PARSEOP_WORDCONST: 598 case PARSEOP_DWORDCONST: 599 600 /* The peer list contains the byte list (if any...) */ 601 602 while (InitializerOp) 603 { 604 /* For buffers, this is a list of raw bytes */ 605 606 InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 607 InitializerOp->Asl.AmlLength = 1; 608 InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 609 610 BufferLength++; 611 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 612 } 613 break; 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 case PARSEOP_RAW_DATA: 629 630 /* Buffer nodes are already initialized (e.g. Unicode operator) */ 631 return; 632 633 case PARSEOP_DEFAULT_ARG: 634 break; 635 636 default: 637 638 AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp, 639 "Unknown buffer initializer opcode"); 640 printf ("Unknown buffer initializer opcode [%s]\n", 641 UtGetOpName (InitializerOp->Asl.ParseOpcode)); 642 return; 643 } 644 645 /* Check if initializer list is longer than the buffer length */ 646 647 if (BufferLengthOp->Asl.Value.Integer > BufferLength) 648 { 649 BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer; 650 } 651 652 if (!BufferLength) 653 { 654 /* No length AND no items -- issue notice */ 655 656 AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL); 657 658 /* But go ahead and put the buffer length of zero into the AML */ 659 } 660 661 /* 662 * Just set the buffer size node to be the buffer length, regardless 663 * of whether it was previously an integer or a default_arg placeholder 664 */ 665 BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; 666 BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP; 667 BufferLengthOp->Asl.Value.Integer = BufferLength; 668 669 (void) OpcSetOptimalIntegerSize (BufferLengthOp); 670 671 /* Remaining nodes are handled via the tree walk */ 672 } 673 674 675 /******************************************************************************* 676 * 677 * FUNCTION: OpnDoPackage 678 * 679 * PARAMETERS: Op - The parent parse node 680 * 681 * RETURN: None 682 * 683 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE: 684 * can only be called after constants have been folded, to ensure 685 * that the PackageLength operand has been fully reduced. 686 * 687 ******************************************************************************/ 688 689 void 690 OpnDoPackage ( 691 ACPI_PARSE_OBJECT *Op) 692 { 693 ACPI_PARSE_OBJECT *InitializerOp; 694 ACPI_PARSE_OBJECT *PackageLengthOp; 695 UINT32 PackageLength = 0; 696 697 698 /* Opcode and package length first, followed by the initializer list */ 699 700 PackageLengthOp = Op->Asl.Child; 701 InitializerOp = PackageLengthOp->Asl.Next; 702 703 /* Count the number of items in the initializer list */ 704 705 if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 706 { 707 /* The peer list contains the byte list (if any...) */ 708 709 while (InitializerOp) 710 { 711 PackageLength++; 712 InitializerOp = InitializerOp->Asl.Next; 713 } 714 } 715 716 /* If package length is a constant, compare to the initializer list */ 717 718 if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || 719 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)) 720 { 721 if (PackageLengthOp->Asl.Value.Integer > PackageLength) 722 { 723 /* 724 * Allow package length to be longer than the initializer 725 * list -- but if the length of initializer list is nonzero, 726 * issue a message since this is probably a coding error, 727 * even though technically legal. 728 */ 729 if (PackageLength > 0) 730 { 731 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT, 732 PackageLengthOp, NULL); 733 } 734 735 PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer; 736 } 737 else if (PackageLengthOp->Asl.Value.Integer < PackageLength) 738 { 739 /* 740 * The package length is smaller than the length of the 741 * initializer list. This is an error as per the ACPI spec. 742 */ 743 AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG, 744 PackageLengthOp, NULL); 745 } 746 } 747 748 if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 749 { 750 /* 751 * This is the case if the PackageLength was left empty - Package() 752 * The package length becomes the length of the initializer list 753 */ 754 Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER; 755 Op->Asl.Child->Asl.Value.Integer = PackageLength; 756 757 /* Set the AML opcode */ 758 759 (void) OpcSetOptimalIntegerSize (Op->Asl.Child); 760 } 761 762 /* If not a variable-length package, check for a zero package length */ 763 764 if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || 765 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST) || 766 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO) || 767 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)) 768 { 769 if (!PackageLength) 770 { 771 /* No length AND no initializer list -- issue a remark */ 772 773 AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH, 774 PackageLengthOp, NULL); 775 776 /* But go ahead and put the buffer length of zero into the AML */ 777 } 778 } 779 780 /* 781 * If the PackageLength is a constant <= 255, we can change the 782 * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode. 783 */ 784 if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 785 (Op->Asl.Child->Asl.Value.Integer <= 255)) || 786 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) || 787 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)|| 788 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO)) 789 { 790 Op->Asl.AmlOpcode = AML_PACKAGE_OP; 791 Op->Asl.ParseOpcode = PARSEOP_PACKAGE; 792 793 /* 794 * Just set the package size node to be the package length, regardless 795 * of whether it was previously an integer or a default_arg placeholder 796 */ 797 PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 798 PackageLengthOp->Asl.AmlLength = 1; 799 PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 800 PackageLengthOp->Asl.Value.Integer = PackageLength; 801 } 802 803 /* Remaining nodes are handled via the tree walk */ 804 } 805 806 807 /******************************************************************************* 808 * 809 * FUNCTION: OpnDoLoadTable 810 * 811 * PARAMETERS: Op - The parent parse node 812 * 813 * RETURN: None 814 * 815 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword. 816 * 817 ******************************************************************************/ 818 819 static void 820 OpnDoLoadTable ( 821 ACPI_PARSE_OBJECT *Op) 822 { 823 ACPI_PARSE_OBJECT *Next; 824 825 826 /* Opcode is parent node */ 827 /* First child is the table signature */ 828 829 Next = Op->Asl.Child; 830 831 /* Second child is the OEM ID*/ 832 833 Next = Next->Asl.Next; 834 835 /* Third child is the OEM table ID */ 836 837 Next = Next->Asl.Next; 838 839 /* Fourth child is the RootPath string */ 840 841 Next = Next->Asl.Next; 842 if (Next->Asl.ParseOpcode == PARSEOP_ZERO) 843 { 844 Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; 845 Next->Asl.Value.String = "\\"; 846 Next->Asl.AmlLength = 2; 847 OpcGenerateAmlOpcode (Next); 848 } 849 850 #ifdef ASL_FUTURE_IMPLEMENTATION 851 852 /* TBD: NOT IMPLEMENTED */ 853 /* Fifth child is the [optional] ParameterPathString */ 854 /* Sixth child is the [optional] ParameterData */ 855 856 Next = Next->Asl.Next; 857 if (Next->Asl.ParseOpcode == DEFAULT_ARG) 858 { 859 Next->Asl.AmlLength = 1; 860 Next->Asl.ParseOpcode = ZERO; 861 OpcGenerateAmlOpcode (Next); 862 } 863 864 865 Next = Next->Asl.Next; 866 if (Next->Asl.ParseOpcode == DEFAULT_ARG) 867 { 868 Next->Asl.AmlLength = 1; 869 Next->Asl.ParseOpcode = ZERO; 870 OpcGenerateAmlOpcode (Next); 871 } 872 #endif 873 } 874 875 876 /******************************************************************************* 877 * 878 * FUNCTION: OpnDoDefinitionBlock 879 * 880 * PARAMETERS: Op - The parent parse node 881 * 882 * RETURN: None 883 * 884 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword 885 * 886 ******************************************************************************/ 887 888 static void 889 OpnDoDefinitionBlock ( 890 ACPI_PARSE_OBJECT *Op) 891 { 892 ACPI_PARSE_OBJECT *Child; 893 ACPI_SIZE Length; 894 UINT32 i; 895 char *Filename; 896 897 898 /* 899 * These nodes get stuffed into the table header. They are special 900 * cased when the table is written to the output file. 901 * 902 * Mark all of these nodes as non-usable so they won't get output 903 * as AML opcodes! 904 */ 905 906 /* Get AML filename. Use it if non-null */ 907 908 Child = Op->Asl.Child; 909 if (Child->Asl.Value.Buffer && 910 *Child->Asl.Value.Buffer && 911 (Gbl_UseDefaultAmlFilename)) 912 { 913 /* 914 * We will use the AML filename that is embedded in the source file 915 * for the output filename. 916 */ 917 Filename = UtStringCacheCalloc (strlen (Gbl_DirectoryPath) + 918 strlen ((char *) Child->Asl.Value.Buffer) + 1); 919 920 /* Prepend the current directory path */ 921 922 strcpy (Filename, Gbl_DirectoryPath); 923 strcat (Filename, (char *) Child->Asl.Value.Buffer); 924 925 Gbl_OutputFilenamePrefix = Filename; 926 UtConvertBackslashes (Gbl_OutputFilenamePrefix); 927 } 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 (strlen (Gbl_TableSignature) != ACPI_NAME_SIZE) 939 { 940 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, 941 "Length is not exactly 4"); 942 } 943 944 for (i = 0; i < ACPI_NAME_SIZE; 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 = strlen (Child->Asl.Value.String); 974 Gbl_TableId = UtStringCacheCalloc (Length + 1); 975 strcpy (Gbl_TableId, Child->Asl.Value.String); 976 977 /* 978 * Convert anything non-alphanumeric to an underscore. This 979 * allows us to use the TableID to generate unique C symbols. 980 */ 981 for (i = 0; i < Length; i++) 982 { 983 if (!isalnum ((int) Gbl_TableId[i])) 984 { 985 Gbl_TableId[i] = '_'; 986 } 987 } 988 } 989 990 /* OEM Revision */ 991 992 Child = Child->Asl.Next; 993 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 994 } 995 996 997 /******************************************************************************* 998 * 999 * FUNCTION: UtGetArg 1000 * 1001 * PARAMETERS: Op - Get an argument for this op 1002 * Argn - Nth argument to get 1003 * 1004 * RETURN: The argument (as an Op object). NULL if argument does not exist 1005 * 1006 * DESCRIPTION: Get the specified op's argument (peer) 1007 * 1008 ******************************************************************************/ 1009 1010 ACPI_PARSE_OBJECT * 1011 UtGetArg ( 1012 ACPI_PARSE_OBJECT *Op, 1013 UINT32 Argn) 1014 { 1015 ACPI_PARSE_OBJECT *Arg = NULL; 1016 1017 1018 /* Get the requested argument object */ 1019 1020 Arg = Op->Asl.Child; 1021 while (Arg && Argn) 1022 { 1023 Argn--; 1024 Arg = Arg->Asl.Next; 1025 } 1026 1027 return (Arg); 1028 } 1029 1030 1031 /******************************************************************************* 1032 * 1033 * FUNCTION: OpnAttachNameToNode 1034 * 1035 * PARAMETERS: Op - The parent parse node 1036 * 1037 * RETURN: None 1038 * 1039 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the 1040 * argument list and attach it to the parent node so that we 1041 * can get to it quickly later. 1042 * 1043 ******************************************************************************/ 1044 1045 static void 1046 OpnAttachNameToNode ( 1047 ACPI_PARSE_OBJECT *Op) 1048 { 1049 ACPI_PARSE_OBJECT *Child = NULL; 1050 1051 1052 switch (Op->Asl.AmlOpcode) 1053 { 1054 case AML_DATA_REGION_OP: 1055 case AML_DEVICE_OP: 1056 case AML_EVENT_OP: 1057 case AML_EXTERNAL_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 1097 return; 1098 } 1099 1100 if (Child) 1101 { 1102 UtAttachNamepathToOwner (Op, Child); 1103 } 1104 } 1105 1106 1107 /******************************************************************************* 1108 * 1109 * FUNCTION: OpnGenerateAmlOperands 1110 * 1111 * PARAMETERS: Op - The parent parse node 1112 * 1113 * RETURN: None 1114 * 1115 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 1116 * complex AML opcodes require processing of the child nodes 1117 * (arguments/operands). 1118 * 1119 ******************************************************************************/ 1120 1121 void 1122 OpnGenerateAmlOperands ( 1123 ACPI_PARSE_OBJECT *Op) 1124 { 1125 1126 1127 if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 1128 { 1129 return; 1130 } 1131 1132 switch (Op->Asl.ParseOpcode) 1133 { 1134 case PARSEOP_DEFINITION_BLOCK: 1135 1136 OpnDoDefinitionBlock (Op); 1137 break; 1138 1139 case PARSEOP_METHOD: 1140 1141 OpnDoMethod (Op); 1142 break; 1143 1144 case PARSEOP_MUTEX: 1145 1146 OpnDoMutex (Op); 1147 break; 1148 1149 case PARSEOP_FIELD: 1150 1151 OpnDoField (Op); 1152 break; 1153 1154 case PARSEOP_INDEXFIELD: 1155 1156 OpnDoIndexField (Op); 1157 break; 1158 1159 case PARSEOP_BANKFIELD: 1160 1161 OpnDoBankField (Op); 1162 break; 1163 1164 case PARSEOP_BUFFER: 1165 1166 OpnDoBuffer (Op); 1167 break; 1168 1169 case PARSEOP_LOADTABLE: 1170 1171 OpnDoLoadTable (Op); 1172 break; 1173 1174 case PARSEOP_OPERATIONREGION: 1175 1176 OpnDoRegion (Op); 1177 break; 1178 1179 case PARSEOP_RESOURCETEMPLATE: 1180 1181 RsDoResourceTemplate (Op); 1182 break; 1183 1184 case PARSEOP_NAMESEG: 1185 case PARSEOP_NAMESTRING: 1186 case PARSEOP_METHODCALL: 1187 case PARSEOP_STRING_LITERAL: 1188 default: 1189 1190 break; 1191 } 1192 1193 /* TBD: move */ 1194 1195 OpnAttachNameToNode (Op); 1196 } 1197