1 2 /****************************************************************************** 3 * 4 * Module Name: asloperands - AML operand processing 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 46 #include <contrib/dev/acpica/compiler/aslcompiler.h> 47 #include "aslcompiler.y.h" 48 #include <contrib/dev/acpica/include/amlcode.h> 49 50 #define _COMPONENT ACPI_COMPILER 51 ACPI_MODULE_NAME ("asloperands") 52 53 /* Local prototypes */ 54 55 static void 56 OpnDoField ( 57 ACPI_PARSE_OBJECT *Op); 58 59 static void 60 OpnDoBankField ( 61 ACPI_PARSE_OBJECT *Op); 62 63 static void 64 OpnDoBuffer ( 65 ACPI_PARSE_OBJECT *Op); 66 67 static void 68 OpnDoDefinitionBlock ( 69 ACPI_PARSE_OBJECT *Op); 70 71 static void 72 OpnDoFieldCommon ( 73 ACPI_PARSE_OBJECT *FieldOp, 74 ACPI_PARSE_OBJECT *Op); 75 76 static void 77 OpnDoIndexField ( 78 ACPI_PARSE_OBJECT *Op); 79 80 static void 81 OpnDoLoadTable ( 82 ACPI_PARSE_OBJECT *Op); 83 84 static void 85 OpnDoMethod ( 86 ACPI_PARSE_OBJECT *Op); 87 88 static void 89 OpnDoMutex ( 90 ACPI_PARSE_OBJECT *Op); 91 92 static void 93 OpnDoRegion ( 94 ACPI_PARSE_OBJECT *Op); 95 96 static void 97 OpnAttachNameToNode ( 98 ACPI_PARSE_OBJECT *Op); 99 100 101 /******************************************************************************* 102 * 103 * FUNCTION: OpnDoMutex 104 * 105 * PARAMETERS: Op - The parent parse node 106 * 107 * RETURN: None 108 * 109 * DESCRIPTION: Construct the operands for the MUTEX ASL keyword. 110 * 111 ******************************************************************************/ 112 113 static void 114 OpnDoMutex ( 115 ACPI_PARSE_OBJECT *Op) 116 { 117 ACPI_PARSE_OBJECT *Next; 118 119 120 Next = Op->Asl.Child; 121 Next = Next->Asl.Next; 122 123 if (Next->Asl.Value.Integer > 15) 124 { 125 AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); 126 } 127 return; 128 } 129 130 131 /******************************************************************************* 132 * 133 * FUNCTION: OpnDoMethod 134 * 135 * PARAMETERS: Op - The parent parse node 136 * 137 * RETURN: None 138 * 139 * DESCRIPTION: Construct the operands for the METHOD ASL keyword. 140 * 141 ******************************************************************************/ 142 143 static void 144 OpnDoMethod ( 145 ACPI_PARSE_OBJECT *Op) 146 { 147 ACPI_PARSE_OBJECT *Next; 148 149 /* Optional arguments for this opcode with defaults */ 150 151 UINT8 NumArgs = 0; 152 UINT8 Serialized = 0; 153 UINT8 Concurrency = 0; 154 UINT8 MethodFlags; 155 156 157 /* Opcode and package length first */ 158 /* Method name */ 159 160 Next = Op->Asl.Child; 161 162 /* Num args */ 163 164 Next = Next->Asl.Next; 165 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 166 { 167 NumArgs = (UINT8) Next->Asl.Value.Integer; 168 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 169 } 170 171 /* Serialized Flag */ 172 173 Next = Next->Asl.Next; 174 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 175 { 176 Serialized = (UINT8) Next->Asl.Value.Integer; 177 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 178 } 179 180 /* Concurrency value (valid values are 0-15) */ 181 182 Next = Next->Asl.Next; 183 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 184 { 185 if (Next->Asl.Value.Integer > 15) 186 { 187 AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); 188 } 189 Concurrency = (UINT8) Next->Asl.Value.Integer; 190 } 191 192 /* Put the bits in their proper places */ 193 194 MethodFlags = (UINT8) ((NumArgs & 0x7) | 195 ((Serialized & 0x1) << 3) | 196 ((Concurrency & 0xF) << 4)); 197 198 /* Use the last node for the combined flags byte */ 199 200 Next->Asl.Value.Integer = MethodFlags; 201 Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 202 Next->Asl.AmlLength = 1; 203 Next->Asl.ParseOpcode = PARSEOP_RAW_DATA; 204 205 /* Save the arg count in the first node */ 206 207 Op->Asl.Extra = NumArgs; 208 } 209 210 211 /******************************************************************************* 212 * 213 * FUNCTION: OpnDoFieldCommon 214 * 215 * PARAMETERS: FieldOp - Node for an ASL field 216 * Op - The parent parse node 217 * 218 * RETURN: None 219 * 220 * DESCRIPTION: Construct the AML operands for the various field keywords, 221 * FIELD, BANKFIELD, INDEXFIELD 222 * 223 ******************************************************************************/ 224 225 static void 226 OpnDoFieldCommon ( 227 ACPI_PARSE_OBJECT *FieldOp, 228 ACPI_PARSE_OBJECT *Op) 229 { 230 ACPI_PARSE_OBJECT *Next; 231 ACPI_PARSE_OBJECT *PkgLengthNode; 232 UINT32 CurrentBitOffset; 233 UINT32 NewBitOffset; 234 UINT8 AccessType; 235 UINT8 LockRule; 236 UINT8 UpdateRule; 237 UINT8 FieldFlags; 238 UINT32 MinimumLength; 239 240 241 /* AccessType -- not optional, so no need to check for DEFAULT_ARG */ 242 243 AccessType = (UINT8) Op->Asl.Value.Integer; 244 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 245 246 /* Set the access type in the parent (field) node for use later */ 247 248 FieldOp->Asl.Value.Integer = AccessType; 249 250 /* LockRule -- not optional, so no need to check for DEFAULT_ARG */ 251 252 Next = Op->Asl.Next; 253 LockRule = (UINT8) Next->Asl.Value.Integer; 254 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 255 256 /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */ 257 258 Next = Next->Asl.Next; 259 UpdateRule = (UINT8) Next->Asl.Value.Integer; 260 261 /* 262 * Generate the flags byte. The various fields are already 263 * in the right bit position via translation from the 264 * keywords by the parser. 265 */ 266 FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule); 267 268 /* Use the previous node to be the FieldFlags node */ 269 270 /* Set the node to RAW_DATA */ 271 272 Next->Asl.Value.Integer = FieldFlags; 273 Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 274 Next->Asl.AmlLength = 1; 275 Next->Asl.ParseOpcode = PARSEOP_RAW_DATA; 276 277 /* Process the FieldUnitList */ 278 279 Next = Next->Asl.Next; 280 CurrentBitOffset = 0; 281 282 while (Next) 283 { 284 /* Save the offset of this field unit */ 285 286 Next->Asl.ExtraValue = CurrentBitOffset; 287 288 switch (Next->Asl.ParseOpcode) 289 { 290 case PARSEOP_ACCESSAS: 291 292 PkgLengthNode = Next->Asl.Child; 293 AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer; 294 295 /* Nothing additional to do */ 296 break; 297 298 299 case PARSEOP_OFFSET: 300 301 /* New offset into the field */ 302 303 PkgLengthNode = Next->Asl.Child; 304 NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8; 305 306 /* 307 * Examine the specified offset in relation to the 308 * current offset counter. 309 */ 310 if (NewBitOffset < CurrentBitOffset) 311 { 312 /* 313 * Not allowed to specify a backwards offset! 314 * Issue error and ignore this node. 315 */ 316 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode, 317 NULL); 318 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 319 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 320 } 321 else if (NewBitOffset == CurrentBitOffset) 322 { 323 /* 324 * Offset is redundant; we don't need to output an 325 * offset opcode. Just set these nodes to default 326 */ 327 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 328 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 329 } 330 else 331 { 332 /* 333 * Valid new offset - set the value to be inserted into the AML 334 * and update the offset counter. 335 */ 336 PkgLengthNode->Asl.Value.Integer = 337 NewBitOffset - CurrentBitOffset; 338 CurrentBitOffset = NewBitOffset; 339 } 340 break; 341 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 MinimumLength = 8; 361 break; 362 363 case AML_FIELD_ACCESS_WORD: 364 MinimumLength = 16; 365 break; 366 367 case AML_FIELD_ACCESS_DWORD: 368 MinimumLength = 32; 369 break; 370 371 case AML_FIELD_ACCESS_QWORD: 372 MinimumLength = 64; 373 break; 374 } 375 376 PkgLengthNode->Asl.ExtraValue = MinimumLength; 377 break; 378 379 default: 380 /* All supported field opcodes must appear above */ 381 break; 382 } 383 384 /* Move on to next entry in the field list */ 385 386 Next = Next->Asl.Next; 387 } 388 } 389 390 391 /******************************************************************************* 392 * 393 * FUNCTION: OpnDoField 394 * 395 * PARAMETERS: Op - The parent parse node 396 * 397 * RETURN: None 398 * 399 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword 400 * 401 ******************************************************************************/ 402 403 static void 404 OpnDoField ( 405 ACPI_PARSE_OBJECT *Op) 406 { 407 ACPI_PARSE_OBJECT *Next; 408 409 410 /* Opcode is parent node */ 411 /* First child is field name */ 412 413 Next = Op->Asl.Child; 414 415 /* Second child is the AccessType */ 416 417 OpnDoFieldCommon (Op, Next->Asl.Next); 418 } 419 420 421 /******************************************************************************* 422 * 423 * FUNCTION: OpnDoIndexField 424 * 425 * PARAMETERS: Op - The parent parse node 426 * 427 * RETURN: None 428 * 429 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword 430 * 431 ******************************************************************************/ 432 433 static void 434 OpnDoIndexField ( 435 ACPI_PARSE_OBJECT *Op) 436 { 437 ACPI_PARSE_OBJECT *Next; 438 439 440 /* Opcode is parent node */ 441 /* First child is the index name */ 442 443 Next = Op->Asl.Child; 444 445 /* Second child is the data name */ 446 447 Next = Next->Asl.Next; 448 449 /* Third child is the AccessType */ 450 451 OpnDoFieldCommon (Op, Next->Asl.Next); 452 } 453 454 455 /******************************************************************************* 456 * 457 * FUNCTION: OpnDoBankField 458 * 459 * PARAMETERS: Op - The parent parse node 460 * 461 * RETURN: None 462 * 463 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword 464 * 465 ******************************************************************************/ 466 467 static void 468 OpnDoBankField ( 469 ACPI_PARSE_OBJECT *Op) 470 { 471 ACPI_PARSE_OBJECT *Next; 472 473 474 /* Opcode is parent node */ 475 /* First child is the region name */ 476 477 Next = Op->Asl.Child; 478 479 /* Second child is the bank name */ 480 481 Next = Next->Asl.Next; 482 483 /* Third child is the bank value */ 484 485 Next = Next->Asl.Next; 486 487 /* Fourth child is the AccessType */ 488 489 OpnDoFieldCommon (Op, Next->Asl.Next); 490 } 491 492 493 /******************************************************************************* 494 * 495 * FUNCTION: OpnDoRegion 496 * 497 * PARAMETERS: Op - The parent parse node 498 * 499 * RETURN: None 500 * 501 * DESCRIPTION: Tries to get the length of the region. Can only do this at 502 * compile time if the length is a constant. 503 * 504 ******************************************************************************/ 505 506 static void 507 OpnDoRegion ( 508 ACPI_PARSE_OBJECT *Op) 509 { 510 ACPI_PARSE_OBJECT *Next; 511 512 513 /* Opcode is parent node */ 514 /* First child is the region name */ 515 516 Next = Op->Asl.Child; 517 518 /* Second child is the space ID*/ 519 520 Next = Next->Asl.Next; 521 522 /* Third child is the region offset */ 523 524 Next = Next->Asl.Next; 525 526 /* Fourth child is the region length */ 527 528 Next = Next->Asl.Next; 529 if (Next->Asl.ParseOpcode == PARSEOP_INTEGER) 530 { 531 Op->Asl.Value.Integer = Next->Asl.Value.Integer; 532 } 533 else 534 { 535 Op->Asl.Value.Integer = ACPI_UINT64_MAX; 536 } 537 } 538 539 540 /******************************************************************************* 541 * 542 * FUNCTION: OpnDoBuffer 543 * 544 * PARAMETERS: Op - The parent parse node 545 * 546 * RETURN: None 547 * 548 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We 549 * build a single raw byte buffer from the initialization nodes, 550 * each parse node contains a buffer byte. 551 * 552 ******************************************************************************/ 553 554 static void 555 OpnDoBuffer ( 556 ACPI_PARSE_OBJECT *Op) 557 { 558 ACPI_PARSE_OBJECT *InitializerOp; 559 ACPI_PARSE_OBJECT *BufferLengthOp; 560 561 /* Optional arguments for this opcode with defaults */ 562 563 UINT32 BufferLength = 0; 564 565 566 /* Opcode and package length first */ 567 /* Buffer Length is next, followed by the initializer list */ 568 569 BufferLengthOp = Op->Asl.Child; 570 InitializerOp = BufferLengthOp->Asl.Next; 571 572 /* 573 * If the BufferLength is not an INTEGER or was not specified in the ASL 574 * (DEFAULT_ARG), it is a TermArg that is 575 * evaluated at run-time, and we are therefore finished. 576 */ 577 if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) && 578 (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 579 { 580 return; 581 } 582 583 /* 584 * We want to count the number of items in the initializer list, because if 585 * it is larger than the buffer length, we will define the buffer size 586 * to be the size of the initializer list (as per the ACPI Specification) 587 */ 588 switch (InitializerOp->Asl.ParseOpcode) 589 { 590 case PARSEOP_INTEGER: 591 case PARSEOP_BYTECONST: 592 case PARSEOP_WORDCONST: 593 case PARSEOP_DWORDCONST: 594 595 /* The peer list contains the byte list (if any...) */ 596 597 while (InitializerOp) 598 { 599 /* For buffers, this is a list of raw bytes */ 600 601 InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 602 InitializerOp->Asl.AmlLength = 1; 603 InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 604 605 BufferLength++; 606 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 607 } 608 break; 609 610 611 case PARSEOP_STRING_LITERAL: 612 613 /* 614 * Only one initializer, the string. Buffer must be big enough to hold 615 * the string plus the null termination byte 616 */ 617 BufferLength = strlen (InitializerOp->Asl.Value.String) + 1; 618 619 InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; 620 InitializerOp->Asl.AmlLength = BufferLength; 621 InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 622 break; 623 624 625 case PARSEOP_RAW_DATA: 626 627 /* Buffer nodes are already initialized (e.g. Unicode operator) */ 628 return; 629 630 631 case PARSEOP_DEFAULT_ARG: 632 break; 633 634 635 default: 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 = ACPI_ALLOCATE (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 } 925 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 926 927 /* Signature */ 928 929 Child = Child->Asl.Next; 930 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 931 if (Child->Asl.Value.String) 932 { 933 Gbl_TableSignature = Child->Asl.Value.String; 934 if (ACPI_STRLEN (Gbl_TableSignature) != 4) 935 { 936 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, 937 "Length not exactly 4"); 938 } 939 940 for (i = 0; i < 4; i++) 941 { 942 if (!isalnum ((int) Gbl_TableSignature[i])) 943 { 944 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, 945 "Contains non-alphanumeric characters"); 946 } 947 } 948 } 949 950 /* Revision */ 951 952 Child = Child->Asl.Next; 953 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 954 /* 955 * We used the revision to set the integer width earlier 956 */ 957 958 /* OEMID */ 959 960 Child = Child->Asl.Next; 961 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 962 963 /* OEM TableID */ 964 965 Child = Child->Asl.Next; 966 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 967 if (Child->Asl.Value.String) 968 { 969 Length = ACPI_STRLEN (Child->Asl.Value.String); 970 Gbl_TableId = AcpiOsAllocate (Length + 1); 971 ACPI_STRCPY (Gbl_TableId, Child->Asl.Value.String); 972 973 for (i = 0; i < Length; i++) 974 { 975 if (Gbl_TableId[i] == ' ') 976 { 977 Gbl_TableId[i] = 0; 978 break; 979 } 980 } 981 } 982 983 /* OEM Revision */ 984 985 Child = Child->Asl.Next; 986 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 987 } 988 989 990 /******************************************************************************* 991 * 992 * FUNCTION: UtGetArg 993 * 994 * PARAMETERS: Op - Get an argument for this op 995 * Argn - Nth argument to get 996 * 997 * RETURN: The argument (as an Op object). NULL if argument does not exist 998 * 999 * DESCRIPTION: Get the specified op's argument (peer) 1000 * 1001 ******************************************************************************/ 1002 1003 ACPI_PARSE_OBJECT * 1004 UtGetArg ( 1005 ACPI_PARSE_OBJECT *Op, 1006 UINT32 Argn) 1007 { 1008 ACPI_PARSE_OBJECT *Arg = NULL; 1009 1010 1011 /* Get the requested argument object */ 1012 1013 Arg = Op->Asl.Child; 1014 while (Arg && Argn) 1015 { 1016 Argn--; 1017 Arg = Arg->Asl.Next; 1018 } 1019 1020 return (Arg); 1021 } 1022 1023 1024 /******************************************************************************* 1025 * 1026 * FUNCTION: OpnAttachNameToNode 1027 * 1028 * PARAMETERS: Op - The parent parse node 1029 * 1030 * RETURN: None 1031 * 1032 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the 1033 * argument list and attach it to the parent node so that we 1034 * can get to it quickly later. 1035 * 1036 ******************************************************************************/ 1037 1038 static void 1039 OpnAttachNameToNode ( 1040 ACPI_PARSE_OBJECT *Op) 1041 { 1042 ACPI_PARSE_OBJECT *Child = NULL; 1043 1044 1045 if (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL) 1046 { 1047 Child = UtGetArg (Op, 0); 1048 } 1049 else switch (Op->Asl.AmlOpcode) 1050 { 1051 case AML_DATA_REGION_OP: 1052 case AML_DEVICE_OP: 1053 case AML_EVENT_OP: 1054 case AML_METHOD_OP: 1055 case AML_MUTEX_OP: 1056 case AML_REGION_OP: 1057 case AML_POWER_RES_OP: 1058 case AML_PROCESSOR_OP: 1059 case AML_THERMAL_ZONE_OP: 1060 case AML_NAME_OP: 1061 case AML_SCOPE_OP: 1062 1063 Child = UtGetArg (Op, 0); 1064 break; 1065 1066 case AML_ALIAS_OP: 1067 1068 Child = UtGetArg (Op, 1); 1069 break; 1070 1071 case AML_CREATE_BIT_FIELD_OP: 1072 case AML_CREATE_BYTE_FIELD_OP: 1073 case AML_CREATE_WORD_FIELD_OP: 1074 case AML_CREATE_DWORD_FIELD_OP: 1075 case AML_CREATE_QWORD_FIELD_OP: 1076 1077 Child = UtGetArg (Op, 2); 1078 break; 1079 1080 case AML_CREATE_FIELD_OP: 1081 1082 Child = UtGetArg (Op, 3); 1083 break; 1084 1085 case AML_BANK_FIELD_OP: 1086 case AML_INDEX_FIELD_OP: 1087 case AML_FIELD_OP: 1088 1089 return; 1090 1091 default: 1092 return; 1093 } 1094 1095 if (Child) 1096 { 1097 UtAttachNamepathToOwner (Op, Child); 1098 } 1099 } 1100 1101 1102 /******************************************************************************* 1103 * 1104 * FUNCTION: OpnGenerateAmlOperands 1105 * 1106 * PARAMETERS: Op - The parent parse node 1107 * 1108 * RETURN: None 1109 * 1110 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 1111 * complex AML opcodes require processing of the child nodes 1112 * (arguments/operands). 1113 * 1114 ******************************************************************************/ 1115 1116 void 1117 OpnGenerateAmlOperands ( 1118 ACPI_PARSE_OBJECT *Op) 1119 { 1120 1121 1122 if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 1123 { 1124 return; 1125 } 1126 1127 switch (Op->Asl.ParseOpcode) 1128 { 1129 case PARSEOP_DEFINITIONBLOCK: 1130 OpnDoDefinitionBlock (Op); 1131 break; 1132 1133 case PARSEOP_METHOD: 1134 OpnDoMethod (Op); 1135 break; 1136 1137 case PARSEOP_MUTEX: 1138 OpnDoMutex (Op); 1139 break; 1140 1141 case PARSEOP_FIELD: 1142 OpnDoField (Op); 1143 break; 1144 1145 case PARSEOP_INDEXFIELD: 1146 OpnDoIndexField (Op); 1147 break; 1148 1149 case PARSEOP_BANKFIELD: 1150 OpnDoBankField (Op); 1151 break; 1152 1153 case PARSEOP_BUFFER: 1154 OpnDoBuffer (Op); 1155 break; 1156 1157 case PARSEOP_LOADTABLE: 1158 OpnDoLoadTable (Op); 1159 break; 1160 1161 case PARSEOP_OPERATIONREGION: 1162 OpnDoRegion (Op); 1163 break; 1164 1165 case PARSEOP_RESOURCETEMPLATE: 1166 RsDoResourceTemplate (Op); 1167 break; 1168 1169 case PARSEOP_NAMESEG: 1170 case PARSEOP_NAMESTRING: 1171 case PARSEOP_METHODCALL: 1172 case PARSEOP_STRING_LITERAL: 1173 break; 1174 1175 default: 1176 break; 1177 } 1178 1179 /* TBD: move */ 1180 1181 OpnAttachNameToNode (Op); 1182 } 1183 1184 1185