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