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