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