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