1 /****************************************************************************** 2 * 3 * Module Name: asloperands - AML operand processing 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include <contrib/dev/acpica/compiler/aslcompiler.h> 153 #include "aslcompiler.y.h" 154 #include <contrib/dev/acpica/include/amlcode.h> 155 156 #define _COMPONENT ACPI_COMPILER 157 ACPI_MODULE_NAME ("asloperands") 158 159 /* Local prototypes */ 160 161 static void 162 OpnDoField ( 163 ACPI_PARSE_OBJECT *Op); 164 165 static void 166 OpnDoBankField ( 167 ACPI_PARSE_OBJECT *Op); 168 169 static void 170 OpnDoBuffer ( 171 ACPI_PARSE_OBJECT *Op); 172 173 static void 174 OpnDoDefinitionBlock ( 175 ACPI_PARSE_OBJECT *Op); 176 177 static void 178 OpnDoFieldCommon ( 179 ACPI_PARSE_OBJECT *FieldOp, 180 ACPI_PARSE_OBJECT *Op); 181 182 static void 183 OpnDoIndexField ( 184 ACPI_PARSE_OBJECT *Op); 185 186 static void 187 OpnDoLoadTable ( 188 ACPI_PARSE_OBJECT *Op); 189 190 static void 191 OpnDoMethod ( 192 ACPI_PARSE_OBJECT *Op); 193 194 static void 195 OpnDoMutex ( 196 ACPI_PARSE_OBJECT *Op); 197 198 static void 199 OpnDoRegion ( 200 ACPI_PARSE_OBJECT *Op); 201 202 static void 203 OpnAttachNameToNode ( 204 ACPI_PARSE_OBJECT *Op); 205 206 207 /******************************************************************************* 208 * 209 * FUNCTION: OpnDoMutex 210 * 211 * PARAMETERS: Op - The parent parse node 212 * 213 * RETURN: None 214 * 215 * DESCRIPTION: Construct the operands for the MUTEX ASL keyword. 216 * 217 ******************************************************************************/ 218 219 static void 220 OpnDoMutex ( 221 ACPI_PARSE_OBJECT *Op) 222 { 223 ACPI_PARSE_OBJECT *Next; 224 225 226 Next = Op->Asl.Child; 227 Next = Next->Asl.Next; 228 229 if (Next->Asl.Value.Integer > 15) 230 { 231 AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); 232 } 233 return; 234 } 235 236 237 /******************************************************************************* 238 * 239 * FUNCTION: OpnDoMethod 240 * 241 * PARAMETERS: Op - The parent parse node 242 * 243 * RETURN: None 244 * 245 * DESCRIPTION: Construct the operands for the METHOD ASL keyword. 246 * 247 ******************************************************************************/ 248 249 static void 250 OpnDoMethod ( 251 ACPI_PARSE_OBJECT *Op) 252 { 253 ACPI_PARSE_OBJECT *Next; 254 255 /* Optional arguments for this opcode with defaults */ 256 257 UINT8 NumArgs = 0; 258 UINT8 Serialized = 0; 259 UINT8 Concurrency = 0; 260 UINT8 MethodFlags; 261 262 263 /* Opcode and package length first */ 264 /* Method name */ 265 266 Next = Op->Asl.Child; 267 268 /* Num args */ 269 270 Next = Next->Asl.Next; 271 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 272 { 273 NumArgs = (UINT8) Next->Asl.Value.Integer; 274 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 275 } 276 277 /* Serialized Flag */ 278 279 Next = Next->Asl.Next; 280 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 281 { 282 Serialized = (UINT8) Next->Asl.Value.Integer; 283 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 284 } 285 286 /* Concurrency value (valid values are 0-15) */ 287 288 Next = Next->Asl.Next; 289 if (Next->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 290 { 291 /* This is a ByteConstExpr, so eval the constant now */ 292 293 OpcAmlConstantWalk (Next, 0, NULL); 294 295 if (Next->Asl.Value.Integer > 15) 296 { 297 AslError (ASL_ERROR, ASL_MSG_SYNC_LEVEL, Next, NULL); 298 } 299 300 Concurrency = (UINT8) Next->Asl.Value.Integer; 301 } 302 303 /* Put the bits in their proper places */ 304 305 MethodFlags = (UINT8) 306 ((NumArgs & 0x7) | 307 ((Serialized & 0x1) << 3) | 308 ((Concurrency & 0xF) << 4)); 309 310 /* Use the last node for the combined flags byte */ 311 312 Next->Asl.Value.Integer = MethodFlags; 313 Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 314 Next->Asl.AmlLength = 1; 315 Next->Asl.ParseOpcode = PARSEOP_RAW_DATA; 316 317 /* Save the arg count in the first node */ 318 319 Op->Asl.Extra = NumArgs; 320 } 321 322 323 /******************************************************************************* 324 * 325 * FUNCTION: OpnDoFieldCommon 326 * 327 * PARAMETERS: FieldOp - Node for an ASL field 328 * Op - The parent parse node 329 * 330 * RETURN: None 331 * 332 * DESCRIPTION: Construct the AML operands for the various field keywords, 333 * FIELD, BANKFIELD, INDEXFIELD 334 * 335 ******************************************************************************/ 336 337 static void 338 OpnDoFieldCommon ( 339 ACPI_PARSE_OBJECT *FieldOp, 340 ACPI_PARSE_OBJECT *Op) 341 { 342 ACPI_PARSE_OBJECT *Next; 343 ACPI_PARSE_OBJECT *PkgLengthNode; 344 UINT32 CurrentBitOffset; 345 UINT32 NewBitOffset; 346 UINT8 AccessType; 347 UINT8 LockRule; 348 UINT8 UpdateRule; 349 UINT8 FieldFlags; 350 UINT32 MinimumLength; 351 352 353 /* AccessType -- not optional, so no need to check for DEFAULT_ARG */ 354 355 AccessType = (UINT8) Op->Asl.Value.Integer; 356 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 357 358 /* Set the access type in the parent (field) node for use later */ 359 360 FieldOp->Asl.Value.Integer = AccessType; 361 362 /* LockRule -- not optional, so no need to check for DEFAULT_ARG */ 363 364 Next = Op->Asl.Next; 365 LockRule = (UINT8) Next->Asl.Value.Integer; 366 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 367 368 /* UpdateRule -- not optional, so no need to check for DEFAULT_ARG */ 369 370 Next = Next->Asl.Next; 371 UpdateRule = (UINT8) Next->Asl.Value.Integer; 372 373 /* 374 * Generate the flags byte. The various fields are already 375 * in the right bit position via translation from the 376 * keywords by the parser. 377 */ 378 FieldFlags = (UINT8) (AccessType | LockRule | UpdateRule); 379 380 /* Use the previous node to be the FieldFlags node */ 381 382 /* Set the node to RAW_DATA */ 383 384 Next->Asl.Value.Integer = FieldFlags; 385 Next->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 386 Next->Asl.AmlLength = 1; 387 Next->Asl.ParseOpcode = PARSEOP_RAW_DATA; 388 389 /* Process the FieldUnitList */ 390 391 Next = Next->Asl.Next; 392 CurrentBitOffset = 0; 393 394 while (Next) 395 { 396 /* Save the offset of this field unit */ 397 398 Next->Asl.ExtraValue = CurrentBitOffset; 399 400 switch (Next->Asl.ParseOpcode) 401 { 402 case PARSEOP_ACCESSAS: 403 404 PkgLengthNode = Next->Asl.Child; 405 AccessType = (UINT8) PkgLengthNode->Asl.Value.Integer; 406 407 /* Nothing additional to do */ 408 break; 409 410 case PARSEOP_OFFSET: 411 412 /* New offset into the field */ 413 414 PkgLengthNode = Next->Asl.Child; 415 NewBitOffset = ((UINT32) PkgLengthNode->Asl.Value.Integer) * 8; 416 417 /* 418 * Examine the specified offset in relation to the 419 * current offset counter. 420 */ 421 if (NewBitOffset < CurrentBitOffset) 422 { 423 /* 424 * Not allowed to specify a backwards offset! 425 * Issue error and ignore this node. 426 */ 427 AslError (ASL_ERROR, ASL_MSG_BACKWARDS_OFFSET, PkgLengthNode, 428 NULL); 429 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 430 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 431 } 432 #ifdef _OBSOLETE_CODE 433 /* 434 * January 2022: removed this check due to complaints by users 435 * for too many (invalid) remarks. 436 */ 437 else if (NewBitOffset == CurrentBitOffset) 438 { 439 /* 440 * This Offset() operator is redundant and not needed, 441 * because the offset value is the same as the current 442 * offset. 443 */ 444 AslError (ASL_REMARK, ASL_MSG_OFFSET, PkgLengthNode, NULL); 445 446 if (AslGbl_OptimizeTrivialParseNodes) 447 { 448 /* 449 * Optimize this Offset() operator by removing/ignoring 450 * it. Set the related nodes to default. 451 */ 452 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 453 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 454 455 AslError (ASL_OPTIMIZATION, ASL_MSG_OFFSET, PkgLengthNode, 456 "Optimizer has removed statement"); 457 } 458 else 459 { 460 /* Optimization is disabled, treat as a valid Offset */ 461 462 PkgLengthNode->Asl.Value.Integer = 463 NewBitOffset - CurrentBitOffset; 464 CurrentBitOffset = NewBitOffset; 465 } 466 } 467 #endif 468 else 469 { 470 /* 471 * Valid new offset - set the value to be inserted into the AML 472 * and update the offset counter. 473 */ 474 PkgLengthNode->Asl.Value.Integer = 475 NewBitOffset - CurrentBitOffset; 476 CurrentBitOffset = NewBitOffset; 477 } 478 break; 479 480 case PARSEOP_NAMESEG: 481 case PARSEOP_RESERVED_BYTES: 482 483 /* Named or reserved field entry */ 484 485 PkgLengthNode = Next->Asl.Child; 486 NewBitOffset = (UINT32) PkgLengthNode->Asl.Value.Integer; 487 CurrentBitOffset += NewBitOffset; 488 489 if ((NewBitOffset == 0) && 490 (Next->Asl.ParseOpcode == PARSEOP_RESERVED_BYTES) && 491 AslGbl_OptimizeTrivialParseNodes) 492 { 493 /* 494 * Unnamed field with a bit length of zero. We can 495 * safely just ignore this. However, we will not ignore 496 * a named field of zero length, we don't want to just 497 * toss out a name. 498 */ 499 Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 500 PkgLengthNode->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 501 break; 502 } 503 504 /* Save the current AccessAs value for error checking later */ 505 506 switch (AccessType) 507 { 508 case AML_FIELD_ACCESS_ANY: 509 case AML_FIELD_ACCESS_BYTE: 510 case AML_FIELD_ACCESS_BUFFER: 511 default: 512 513 MinimumLength = 8; 514 break; 515 516 case AML_FIELD_ACCESS_WORD: 517 MinimumLength = 16; 518 break; 519 520 case AML_FIELD_ACCESS_DWORD: 521 MinimumLength = 32; 522 break; 523 524 case AML_FIELD_ACCESS_QWORD: 525 MinimumLength = 64; 526 break; 527 } 528 529 PkgLengthNode->Asl.ExtraValue = MinimumLength; 530 break; 531 532 default: 533 534 /* All supported field opcodes must appear above */ 535 536 break; 537 } 538 539 /* Move on to next entry in the field list */ 540 541 Next = Next->Asl.Next; 542 } 543 } 544 545 546 /******************************************************************************* 547 * 548 * FUNCTION: OpnDoField 549 * 550 * PARAMETERS: Op - The parent parse node 551 * 552 * RETURN: None 553 * 554 * DESCRIPTION: Construct the AML operands for the FIELD ASL keyword 555 * 556 ******************************************************************************/ 557 558 static void 559 OpnDoField ( 560 ACPI_PARSE_OBJECT *Op) 561 { 562 ACPI_PARSE_OBJECT *Next; 563 564 565 /* Opcode is parent node */ 566 /* First child is field name */ 567 568 Next = Op->Asl.Child; 569 570 /* Second child is the AccessType */ 571 572 OpnDoFieldCommon (Op, Next->Asl.Next); 573 } 574 575 576 /******************************************************************************* 577 * 578 * FUNCTION: OpnDoIndexField 579 * 580 * PARAMETERS: Op - The parent parse node 581 * 582 * RETURN: None 583 * 584 * DESCRIPTION: Construct the AML operands for the INDEXFIELD ASL keyword 585 * 586 ******************************************************************************/ 587 588 static void 589 OpnDoIndexField ( 590 ACPI_PARSE_OBJECT *Op) 591 { 592 ACPI_PARSE_OBJECT *Next; 593 594 595 /* Opcode is parent node */ 596 /* First child is the index name */ 597 598 Next = Op->Asl.Child; 599 600 /* Second child is the data name */ 601 602 Next = Next->Asl.Next; 603 604 /* Third child is the AccessType */ 605 606 OpnDoFieldCommon (Op, Next->Asl.Next); 607 } 608 609 610 /******************************************************************************* 611 * 612 * FUNCTION: OpnDoBankField 613 * 614 * PARAMETERS: Op - The parent parse node 615 * 616 * RETURN: None 617 * 618 * DESCRIPTION: Construct the AML operands for the BANKFIELD ASL keyword 619 * 620 ******************************************************************************/ 621 622 static void 623 OpnDoBankField ( 624 ACPI_PARSE_OBJECT *Op) 625 { 626 ACPI_PARSE_OBJECT *Next; 627 628 629 /* Opcode is parent node */ 630 /* First child is the region name */ 631 632 Next = Op->Asl.Child; 633 634 /* Second child is the bank name */ 635 636 Next = Next->Asl.Next; 637 638 /* Third child is the bank value */ 639 640 Next = Next->Asl.Next; 641 642 /* Fourth child is the AccessType */ 643 644 OpnDoFieldCommon (Op, Next->Asl.Next); 645 } 646 647 648 /******************************************************************************* 649 * 650 * FUNCTION: OpnDoRegion 651 * 652 * PARAMETERS: Op - The parent parse node 653 * 654 * RETURN: None 655 * 656 * DESCRIPTION: Tries to get the length of the region. Can only do this at 657 * compile time if the length is a constant. 658 * 659 ******************************************************************************/ 660 661 static void 662 OpnDoRegion ( 663 ACPI_PARSE_OBJECT *Op) 664 { 665 ACPI_PARSE_OBJECT *Next; 666 ACPI_ADR_SPACE_TYPE SpaceId; 667 668 669 /* Opcode is parent node */ 670 /* First child is the region name */ 671 672 Next = Op->Asl.Child; 673 674 /* Second child is the space ID */ 675 676 Next = Next->Asl.Next; 677 SpaceId = (ACPI_ADR_SPACE_TYPE) Next->Common.Value.Integer; 678 679 /* Third child is the region offset */ 680 681 Next = Next->Asl.Next; 682 683 /* Fourth child is the region length */ 684 685 Next = Next->Asl.Next; 686 if (Next->Asl.ParseOpcode == PARSEOP_INTEGER) 687 { 688 /* Check for zero length */ 689 690 Op->Asl.Value.Integer = Next->Asl.Value.Integer; 691 if (!Op->Asl.Value.Integer && (SpaceId < ACPI_NUM_PREDEFINED_REGIONS)) 692 { 693 AslError (ASL_ERROR, ASL_MSG_REGION_LENGTH, Op, NULL); 694 } 695 } 696 else 697 { 698 Op->Asl.Value.Integer = ACPI_UINT64_MAX; 699 } 700 } 701 702 703 /******************************************************************************* 704 * 705 * FUNCTION: OpnDoBuffer 706 * 707 * PARAMETERS: Op - The parent parse node 708 * 709 * RETURN: None 710 * 711 * DESCRIPTION: Construct the AML operands for the BUFFER ASL keyword. We 712 * build a single raw byte buffer from the initialization nodes, 713 * each parse node contains a buffer byte. 714 * 715 ******************************************************************************/ 716 717 static void 718 OpnDoBuffer ( 719 ACPI_PARSE_OBJECT *Op) 720 { 721 ACPI_PARSE_OBJECT *InitializerOp; 722 ACPI_PARSE_OBJECT *BufferLengthOp; 723 724 /* Optional arguments for this opcode with defaults */ 725 726 UINT32 BufferLength = 0; 727 728 729 /* Opcode and package length first */ 730 /* Buffer Length is next, followed by the initializer list */ 731 732 BufferLengthOp = Op->Asl.Child; 733 InitializerOp = BufferLengthOp->Asl.Next; 734 735 /* 736 * If the BufferLength is not an INTEGER or was not specified in the ASL 737 * (DEFAULT_ARG), it is a TermArg that is 738 * evaluated at run-time, and we are therefore finished. 739 */ 740 if ((BufferLengthOp->Asl.ParseOpcode != PARSEOP_INTEGER) && 741 (BufferLengthOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 742 { 743 return; 744 } 745 746 /* 747 * We want to count the number of items in the initializer list, because if 748 * it is larger than the buffer length, we will define the buffer size 749 * to be the size of the initializer list (as per the ACPI Specification) 750 */ 751 switch (InitializerOp->Asl.ParseOpcode) 752 { 753 case PARSEOP_INTEGER: 754 case PARSEOP_BYTECONST: 755 case PARSEOP_WORDCONST: 756 case PARSEOP_DWORDCONST: 757 758 /* The peer list contains the byte list (if any...) */ 759 760 while (InitializerOp) 761 { 762 /* For buffers, this is a list of raw bytes */ 763 764 InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 765 InitializerOp->Asl.AmlLength = 1; 766 InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 767 768 BufferLength++; 769 InitializerOp = ASL_GET_PEER_NODE (InitializerOp); 770 } 771 break; 772 773 case PARSEOP_STRING_LITERAL: 774 775 /* 776 * Only one initializer, the string. Buffer must be big enough to hold 777 * the string plus the null termination byte 778 */ 779 BufferLength = strlen (InitializerOp->Asl.Value.String) + 1; 780 781 InitializerOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; 782 InitializerOp->Asl.AmlLength = BufferLength; 783 InitializerOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 784 break; 785 786 case PARSEOP_RAW_DATA: 787 788 /* Buffer nodes are already initialized (e.g. Unicode operator) */ 789 return; 790 791 case PARSEOP_DEFAULT_ARG: 792 break; 793 794 default: 795 796 AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, InitializerOp, 797 "Unknown buffer initializer opcode"); 798 printf ("Unknown buffer initializer opcode [%s]\n", 799 UtGetOpName (InitializerOp->Asl.ParseOpcode)); 800 return; 801 } 802 803 /* Check if initializer list is longer than the buffer length */ 804 805 if (BufferLengthOp->Asl.Value.Integer > BufferLength) 806 { 807 BufferLength = (UINT32) BufferLengthOp->Asl.Value.Integer; 808 } 809 810 if (!BufferLength) 811 { 812 /* No length AND no items -- issue notice */ 813 814 AslError (ASL_REMARK, ASL_MSG_BUFFER_LENGTH, BufferLengthOp, NULL); 815 816 /* But go ahead and put the buffer length of zero into the AML */ 817 } 818 819 /* 820 * Just set the buffer size node to be the buffer length, regardless 821 * of whether it was previously an integer or a default_arg placeholder 822 */ 823 BufferLengthOp->Asl.ParseOpcode = PARSEOP_INTEGER; 824 BufferLengthOp->Asl.AmlOpcode = AML_DWORD_OP; 825 BufferLengthOp->Asl.Value.Integer = BufferLength; 826 827 (void) OpcSetOptimalIntegerSize (BufferLengthOp); 828 UtSetParseOpName (BufferLengthOp); 829 830 /* Remaining nodes are handled via the tree walk */ 831 } 832 833 834 /******************************************************************************* 835 * 836 * FUNCTION: OpnDoPackage 837 * 838 * PARAMETERS: Op - The parent parse node 839 * 840 * RETURN: None 841 * 842 * DESCRIPTION: Construct the AML operands for the PACKAGE ASL keyword. NOTE: 843 * can only be called after constants have been folded, to ensure 844 * that the PackageLength operand has been fully reduced. 845 * 846 ******************************************************************************/ 847 848 void 849 OpnDoPackage ( 850 ACPI_PARSE_OBJECT *Op) 851 { 852 ACPI_PARSE_OBJECT *InitializerOp; 853 ACPI_PARSE_OBJECT *PackageLengthOp; 854 UINT32 PackageLength = 0; 855 856 857 /* Opcode and package length first, followed by the initializer list */ 858 859 PackageLengthOp = Op->Asl.Child; 860 InitializerOp = PackageLengthOp->Asl.Next; 861 862 /* Count the number of items in the initializer list */ 863 864 if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 865 { 866 /* The peer list contains the byte list (if any...) */ 867 868 while (InitializerOp) 869 { 870 PackageLength++; 871 InitializerOp = InitializerOp->Asl.Next; 872 } 873 } 874 875 /* If package length is a constant, compare to the initializer list */ 876 877 if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || 878 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST)) 879 { 880 if (PackageLengthOp->Asl.Value.Integer > PackageLength) 881 { 882 /* 883 * Allow package length to be longer than the initializer 884 * list -- but if the length of initializer list is nonzero, 885 * issue a message since this is probably a coding error, 886 * even though technically legal. 887 */ 888 if (PackageLength > 0) 889 { 890 AslError (ASL_REMARK, ASL_MSG_LIST_LENGTH_SHORT, 891 PackageLengthOp, NULL); 892 } 893 894 PackageLength = (UINT32) PackageLengthOp->Asl.Value.Integer; 895 } 896 else if (PackageLengthOp->Asl.Value.Integer < PackageLength) 897 { 898 /* 899 * The package length is smaller than the length of the 900 * initializer list. This is an error as per the ACPI spec. 901 */ 902 AslError (ASL_ERROR, ASL_MSG_LIST_LENGTH_LONG, 903 PackageLengthOp, NULL); 904 } 905 } 906 907 if (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 908 { 909 /* 910 * This is the case if the PackageLength was left empty - Package() 911 * The package length becomes the length of the initializer list 912 */ 913 Op->Asl.Child->Asl.ParseOpcode = PARSEOP_INTEGER; 914 Op->Asl.Child->Asl.Value.Integer = PackageLength; 915 UtSetParseOpName (Op); 916 917 /* Set the AML opcode */ 918 919 (void) OpcSetOptimalIntegerSize (Op->Asl.Child); 920 } 921 922 /* If not a variable-length package, check for a zero package length */ 923 924 if ((PackageLengthOp->Asl.ParseOpcode == PARSEOP_INTEGER) || 925 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_QWORDCONST) || 926 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_ZERO) || 927 (PackageLengthOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)) 928 { 929 if (!PackageLength) 930 { 931 /* No length AND no initializer list -- issue a remark */ 932 933 AslError (ASL_REMARK, ASL_MSG_PACKAGE_LENGTH, 934 PackageLengthOp, NULL); 935 936 /* But go ahead and put the buffer length of zero into the AML */ 937 } 938 } 939 940 /* 941 * If the PackageLength is a constant <= 255, we can change the 942 * AML opcode from VarPackage to a simple (ACPI 1.0) Package opcode. 943 */ 944 if (((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 945 (Op->Asl.Child->Asl.Value.Integer <= 255)) || 946 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONE) || 947 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ONES)|| 948 (Op->Asl.Child->Asl.ParseOpcode == PARSEOP_ZERO)) 949 { 950 Op->Asl.AmlOpcode = AML_PACKAGE_OP; 951 Op->Asl.ParseOpcode = PARSEOP_PACKAGE; 952 953 /* 954 * Just set the package size node to be the package length, regardless 955 * of whether it was previously an integer or a default_arg placeholder 956 */ 957 PackageLengthOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 958 PackageLengthOp->Asl.AmlLength = 1; 959 PackageLengthOp->Asl.ParseOpcode = PARSEOP_RAW_DATA; 960 PackageLengthOp->Asl.Value.Integer = PackageLength; 961 } 962 963 /* Remaining nodes are handled via the tree walk */ 964 } 965 966 967 /******************************************************************************* 968 * 969 * FUNCTION: OpnDoLoadTable 970 * 971 * PARAMETERS: Op - The parent parse node 972 * 973 * RETURN: None 974 * 975 * DESCRIPTION: Construct the AML operands for the LOADTABLE ASL keyword. 976 * 977 ******************************************************************************/ 978 979 static void 980 OpnDoLoadTable ( 981 ACPI_PARSE_OBJECT *Op) 982 { 983 ACPI_PARSE_OBJECT *Next; 984 985 986 /* Opcode is parent node */ 987 /* First child is the table signature */ 988 989 Next = Op->Asl.Child; 990 991 /* Second child is the OEM ID*/ 992 993 Next = Next->Asl.Next; 994 995 /* Third child is the OEM table ID */ 996 997 Next = Next->Asl.Next; 998 999 /* Fourth child is the RootPath string */ 1000 1001 Next = Next->Asl.Next; 1002 if (Next->Asl.ParseOpcode == PARSEOP_ZERO) 1003 { 1004 Next->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; 1005 Next->Asl.Value.String = "\\"; 1006 Next->Asl.AmlLength = 2; 1007 OpcGenerateAmlOpcode (Next); 1008 } 1009 1010 #ifdef ASL_FUTURE_IMPLEMENTATION 1011 1012 /* TBD: NOT IMPLEMENTED */ 1013 /* Fifth child is the [optional] ParameterPathString */ 1014 /* Sixth child is the [optional] ParameterData */ 1015 1016 Next = Next->Asl.Next; 1017 if (Next->Asl.ParseOpcode == DEFAULT_ARG) 1018 { 1019 Next->Asl.AmlLength = 1; 1020 Next->Asl.ParseOpcode = ZERO; 1021 OpcGenerateAmlOpcode (Next); 1022 } 1023 1024 1025 Next = Next->Asl.Next; 1026 if (Next->Asl.ParseOpcode == DEFAULT_ARG) 1027 { 1028 Next->Asl.AmlLength = 1; 1029 Next->Asl.ParseOpcode = ZERO; 1030 OpcGenerateAmlOpcode (Next); 1031 } 1032 #endif 1033 } 1034 1035 1036 /******************************************************************************* 1037 * 1038 * FUNCTION: OpnDoDefinitionBlock 1039 * 1040 * PARAMETERS: Op - The parent parse node 1041 * 1042 * RETURN: None 1043 * 1044 * DESCRIPTION: Construct the AML operands for the DEFINITIONBLOCK ASL keyword 1045 * 1046 ******************************************************************************/ 1047 1048 static void 1049 OpnDoDefinitionBlock ( 1050 ACPI_PARSE_OBJECT *Op) 1051 { 1052 ACPI_PARSE_OBJECT *Child; 1053 ACPI_SIZE Length; 1054 UINT32 i; 1055 char *Filename; 1056 ACPI_STATUS Status; 1057 1058 1059 /* 1060 * These nodes get stuffed into the table header. They are special 1061 * cased when the table is written to the output file. 1062 * 1063 * Mark all of these nodes as non-usable so they won't get output 1064 * as AML opcodes! 1065 */ 1066 1067 /* Get AML filename. Use it if non-null */ 1068 1069 Child = Op->Asl.Child; 1070 if (Child->Asl.Value.Buffer && 1071 *Child->Asl.Value.Buffer && 1072 (AslGbl_UseDefaultAmlFilename)) 1073 { 1074 /* 1075 * The walk may traverse multiple definition blocks. Switch files 1076 * to ensure that the correct files are manipulated. 1077 */ 1078 FlSwitchFileSet (Op->Asl.Filename); 1079 1080 /* 1081 * We will use the AML filename that is embedded in the source file 1082 * for the output filename. 1083 */ 1084 Filename = UtLocalCacheCalloc (strlen (AslGbl_DirectoryPath) + 1085 strlen ((char *) Child->Asl.Value.Buffer) + 1); 1086 1087 /* Prepend the current directory path */ 1088 1089 strcpy (Filename, AslGbl_DirectoryPath); 1090 strcat (Filename, (char *) Child->Asl.Value.Buffer); 1091 1092 AslGbl_OutputFilenamePrefix = Filename; 1093 UtConvertBackslashes (AslGbl_OutputFilenamePrefix); 1094 1095 /* 1096 * Use the definition block file parameter instead of the input 1097 * filename. Since all files were opened previously, remove the 1098 * existing file and open a new file with the name of this 1099 * definition block parameter. Since AML code generation has yet 1100 * to happen, the previous file can be removed without any impacts. 1101 */ 1102 FlCloseFile (ASL_FILE_AML_OUTPUT); 1103 FlDeleteFile (ASL_FILE_AML_OUTPUT); 1104 Status = FlOpenAmlOutputFile (AslGbl_OutputFilenamePrefix); 1105 if (ACPI_FAILURE (Status)) 1106 { 1107 AslError (ASL_ERROR, ASL_MSG_OUTPUT_FILE_OPEN, NULL, NULL); 1108 return; 1109 } 1110 } 1111 1112 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1113 1114 /* Signature */ 1115 1116 Child = Child->Asl.Next; 1117 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1118 if (Child->Asl.Value.String) 1119 { 1120 AslGbl_FilesList->TableSignature = Child->Asl.Value.String; 1121 AslGbl_TableSignature = Child->Asl.Value.String; 1122 if (strlen (AslGbl_TableSignature) != ACPI_NAMESEG_SIZE) 1123 { 1124 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, 1125 "Length must be exactly 4 characters"); 1126 } 1127 1128 for (i = 0; i < ACPI_NAMESEG_SIZE; i++) 1129 { 1130 if (!isalnum ((int) AslGbl_TableSignature[i])) 1131 { 1132 AslError (ASL_ERROR, ASL_MSG_TABLE_SIGNATURE, Child, 1133 "Contains non-alphanumeric characters"); 1134 } 1135 } 1136 } 1137 1138 /* Revision */ 1139 1140 Child = Child->Asl.Next; 1141 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1142 1143 /* 1144 * We used the revision to set the integer width earlier 1145 */ 1146 1147 /* OEMID */ 1148 1149 Child = Child->Asl.Next; 1150 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1151 if (Child->Asl.Value.String && 1152 strlen (Child->Asl.Value.String) > ACPI_OEM_ID_SIZE) 1153 { 1154 AslError (ASL_ERROR, ASL_MSG_OEM_ID, Child, 1155 "Length cannot exceed 6 characters"); 1156 } 1157 1158 /* OEM TableID */ 1159 1160 Child = Child->Asl.Next; 1161 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1162 if (Child->Asl.Value.String) 1163 { 1164 Length = strlen (Child->Asl.Value.String); 1165 if (Length > ACPI_OEM_TABLE_ID_SIZE) 1166 { 1167 AslError (ASL_ERROR, ASL_MSG_OEM_TABLE_ID, Child, 1168 "Length cannot exceed 8 characters"); 1169 } 1170 1171 AslGbl_TableId = UtLocalCacheCalloc (Length + 1); 1172 strcpy (AslGbl_TableId, Child->Asl.Value.String); 1173 AslGbl_FilesList->TableId = AslGbl_TableId; 1174 1175 /* 1176 * Convert anything non-alphanumeric to an underscore. This 1177 * allows us to use the TableID to generate unique C symbols. 1178 */ 1179 for (i = 0; i < Length; i++) 1180 { 1181 if (!isalnum ((int) AslGbl_TableId[i])) 1182 { 1183 AslGbl_TableId[i] = '_'; 1184 } 1185 } 1186 } 1187 1188 /* OEM Revision */ 1189 1190 Child = Child->Asl.Next; 1191 Child->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1192 } 1193 1194 1195 /******************************************************************************* 1196 * 1197 * FUNCTION: UtGetArg 1198 * 1199 * PARAMETERS: Op - Get an argument for this op 1200 * Argn - Nth argument to get 1201 * 1202 * RETURN: The argument (as an Op object). NULL if argument does not exist 1203 * 1204 * DESCRIPTION: Get the specified op's argument (peer) 1205 * 1206 ******************************************************************************/ 1207 1208 ACPI_PARSE_OBJECT * 1209 UtGetArg ( 1210 ACPI_PARSE_OBJECT *Op, 1211 UINT32 Argn) 1212 { 1213 ACPI_PARSE_OBJECT *Arg = NULL; 1214 1215 1216 /* Get the requested argument object */ 1217 1218 Arg = Op->Asl.Child; 1219 while (Arg && Argn) 1220 { 1221 Argn--; 1222 Arg = Arg->Asl.Next; 1223 } 1224 1225 return (Arg); 1226 } 1227 1228 1229 /******************************************************************************* 1230 * 1231 * FUNCTION: OpnAttachNameToNode 1232 * 1233 * PARAMETERS: Op - The parent parse node 1234 * 1235 * RETURN: None 1236 * 1237 * DESCRIPTION: For the named ASL/AML operators, get the actual name from the 1238 * argument list and attach it to the parent node so that we 1239 * can get to it quickly later. 1240 * 1241 ******************************************************************************/ 1242 1243 static void 1244 OpnAttachNameToNode ( 1245 ACPI_PARSE_OBJECT *Op) 1246 { 1247 ACPI_PARSE_OBJECT *Child = NULL; 1248 1249 1250 switch (Op->Asl.AmlOpcode) 1251 { 1252 case AML_DATA_REGION_OP: 1253 case AML_DEVICE_OP: 1254 case AML_EVENT_OP: 1255 case AML_EXTERNAL_OP: 1256 case AML_METHOD_OP: 1257 case AML_MUTEX_OP: 1258 case AML_REGION_OP: 1259 case AML_POWER_RESOURCE_OP: 1260 case AML_PROCESSOR_OP: 1261 case AML_THERMAL_ZONE_OP: 1262 case AML_NAME_OP: 1263 case AML_SCOPE_OP: 1264 1265 Child = UtGetArg (Op, 0); 1266 break; 1267 1268 case AML_ALIAS_OP: 1269 1270 Child = UtGetArg (Op, 1); 1271 break; 1272 1273 case AML_CREATE_BIT_FIELD_OP: 1274 case AML_CREATE_BYTE_FIELD_OP: 1275 case AML_CREATE_WORD_FIELD_OP: 1276 case AML_CREATE_DWORD_FIELD_OP: 1277 case AML_CREATE_QWORD_FIELD_OP: 1278 1279 Child = UtGetArg (Op, 2); 1280 break; 1281 1282 case AML_CREATE_FIELD_OP: 1283 1284 Child = UtGetArg (Op, 3); 1285 break; 1286 1287 case AML_BANK_FIELD_OP: 1288 case AML_INDEX_FIELD_OP: 1289 case AML_FIELD_OP: 1290 1291 return; 1292 1293 default: 1294 1295 return; 1296 } 1297 1298 if (Child) 1299 { 1300 UtAttachNamepathToOwner (Op, Child); 1301 } 1302 } 1303 1304 1305 /******************************************************************************* 1306 * 1307 * FUNCTION: OpnGenerateAmlOperands 1308 * 1309 * PARAMETERS: Op - The parent parse node 1310 * 1311 * RETURN: None 1312 * 1313 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 1314 * complex AML opcodes require processing of the child nodes 1315 * (arguments/operands). 1316 * 1317 ******************************************************************************/ 1318 1319 void 1320 OpnGenerateAmlOperands ( 1321 ACPI_PARSE_OBJECT *Op) 1322 { 1323 1324 1325 if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 1326 { 1327 return; 1328 } 1329 1330 switch (Op->Asl.ParseOpcode) 1331 { 1332 case PARSEOP_DEFINITION_BLOCK: 1333 1334 OpnDoDefinitionBlock (Op); 1335 break; 1336 1337 case PARSEOP_METHOD: 1338 1339 OpnDoMethod (Op); 1340 break; 1341 1342 case PARSEOP_MUTEX: 1343 1344 OpnDoMutex (Op); 1345 break; 1346 1347 case PARSEOP_FIELD: 1348 1349 OpnDoField (Op); 1350 break; 1351 1352 case PARSEOP_INDEXFIELD: 1353 1354 OpnDoIndexField (Op); 1355 break; 1356 1357 case PARSEOP_BANKFIELD: 1358 1359 OpnDoBankField (Op); 1360 break; 1361 1362 case PARSEOP_BUFFER: 1363 1364 OpnDoBuffer (Op); 1365 break; 1366 1367 case PARSEOP_LOADTABLE: 1368 1369 OpnDoLoadTable (Op); 1370 break; 1371 1372 case PARSEOP_OPERATIONREGION: 1373 1374 OpnDoRegion (Op); 1375 break; 1376 1377 case PARSEOP_RESOURCETEMPLATE: 1378 1379 RsDoResourceTemplate (Op); 1380 break; 1381 1382 case PARSEOP_NAMESEG: 1383 case PARSEOP_NAMESTRING: 1384 case PARSEOP_METHODCALL: 1385 case PARSEOP_STRING_LITERAL: 1386 default: 1387 1388 break; 1389 } 1390 1391 /* TBD: move */ 1392 1393 OpnAttachNameToNode (Op); 1394 } 1395