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