1 /****************************************************************************** 2 * 3 * Module Name: psloop - Main AML parse loop 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2009, 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 117 /* 118 * Parse the AML and build an operation tree as most interpreters, (such as 119 * Perl) do. Parsing is done by hand rather than with a YACC generated parser 120 * to tightly constrain stack and dynamic memory usage. Parsing is kept 121 * flexible and the code fairly compact by parsing based on a list of AML 122 * opcode templates in AmlOpInfo[]. 123 */ 124 125 #include "acpi.h" 126 #include "accommon.h" 127 #include "acparser.h" 128 #include "acdispat.h" 129 #include "amlcode.h" 130 131 #define _COMPONENT ACPI_PARSER 132 ACPI_MODULE_NAME ("psloop") 133 134 static UINT32 AcpiGbl_Depth = 0; 135 136 137 /* Local prototypes */ 138 139 static ACPI_STATUS 140 AcpiPsGetAmlOpcode ( 141 ACPI_WALK_STATE *WalkState); 142 143 static ACPI_STATUS 144 AcpiPsBuildNamedOp ( 145 ACPI_WALK_STATE *WalkState, 146 UINT8 *AmlOpStart, 147 ACPI_PARSE_OBJECT *UnnamedOp, 148 ACPI_PARSE_OBJECT **Op); 149 150 static ACPI_STATUS 151 AcpiPsCreateOp ( 152 ACPI_WALK_STATE *WalkState, 153 UINT8 *AmlOpStart, 154 ACPI_PARSE_OBJECT **NewOp); 155 156 static ACPI_STATUS 157 AcpiPsGetArguments ( 158 ACPI_WALK_STATE *WalkState, 159 UINT8 *AmlOpStart, 160 ACPI_PARSE_OBJECT *Op); 161 162 static ACPI_STATUS 163 AcpiPsCompleteOp ( 164 ACPI_WALK_STATE *WalkState, 165 ACPI_PARSE_OBJECT **Op, 166 ACPI_STATUS Status); 167 168 static ACPI_STATUS 169 AcpiPsCompleteFinalOp ( 170 ACPI_WALK_STATE *WalkState, 171 ACPI_PARSE_OBJECT *Op, 172 ACPI_STATUS Status); 173 174 static void 175 AcpiPsLinkModuleCode ( 176 ACPI_PARSE_OBJECT *ParentOp, 177 UINT8 *AmlStart, 178 UINT32 AmlLength, 179 ACPI_OWNER_ID OwnerId); 180 181 182 /******************************************************************************* 183 * 184 * FUNCTION: AcpiPsGetAmlOpcode 185 * 186 * PARAMETERS: WalkState - Current state 187 * 188 * RETURN: Status 189 * 190 * DESCRIPTION: Extract the next AML opcode from the input stream. 191 * 192 ******************************************************************************/ 193 194 static ACPI_STATUS 195 AcpiPsGetAmlOpcode ( 196 ACPI_WALK_STATE *WalkState) 197 { 198 199 ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); 200 201 202 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, 203 WalkState->ParserState.AmlStart); 204 WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState)); 205 206 /* 207 * First cut to determine what we have found: 208 * 1) A valid AML opcode 209 * 2) A name string 210 * 3) An unknown/invalid opcode 211 */ 212 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 213 214 switch (WalkState->OpInfo->Class) 215 { 216 case AML_CLASS_ASCII: 217 case AML_CLASS_PREFIX: 218 /* 219 * Starts with a valid prefix or ASCII char, this is a name 220 * string. Convert the bare name string to a namepath. 221 */ 222 WalkState->Opcode = AML_INT_NAMEPATH_OP; 223 WalkState->ArgTypes = ARGP_NAMESTRING; 224 break; 225 226 case AML_CLASS_UNKNOWN: 227 228 /* The opcode is unrecognized. Just skip unknown opcodes */ 229 230 ACPI_ERROR ((AE_INFO, 231 "Found unknown opcode %X at AML address %p offset %X, ignoring", 232 WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset)); 233 234 ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128); 235 236 /* Assume one-byte bad opcode */ 237 238 WalkState->ParserState.Aml++; 239 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 240 241 default: 242 243 /* Found opcode info, this is a normal opcode */ 244 245 WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); 246 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; 247 break; 248 } 249 250 return_ACPI_STATUS (AE_OK); 251 } 252 253 254 /******************************************************************************* 255 * 256 * FUNCTION: AcpiPsBuildNamedOp 257 * 258 * PARAMETERS: WalkState - Current state 259 * AmlOpStart - Begin of named Op in AML 260 * UnnamedOp - Early Op (not a named Op) 261 * Op - Returned Op 262 * 263 * RETURN: Status 264 * 265 * DESCRIPTION: Parse a named Op 266 * 267 ******************************************************************************/ 268 269 static ACPI_STATUS 270 AcpiPsBuildNamedOp ( 271 ACPI_WALK_STATE *WalkState, 272 UINT8 *AmlOpStart, 273 ACPI_PARSE_OBJECT *UnnamedOp, 274 ACPI_PARSE_OBJECT **Op) 275 { 276 ACPI_STATUS Status = AE_OK; 277 ACPI_PARSE_OBJECT *Arg = NULL; 278 279 280 ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState); 281 282 283 UnnamedOp->Common.Value.Arg = NULL; 284 UnnamedOp->Common.ArgListLength = 0; 285 UnnamedOp->Common.AmlOpcode = WalkState->Opcode; 286 287 /* 288 * Get and append arguments until we find the node that contains 289 * the name (the type ARGP_NAME). 290 */ 291 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && 292 (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME)) 293 { 294 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), 295 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); 296 if (ACPI_FAILURE (Status)) 297 { 298 return_ACPI_STATUS (Status); 299 } 300 301 AcpiPsAppendArg (UnnamedOp, Arg); 302 INCREMENT_ARG_LIST (WalkState->ArgTypes); 303 } 304 305 /* 306 * Make sure that we found a NAME and didn't run out of arguments 307 */ 308 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes)) 309 { 310 return_ACPI_STATUS (AE_AML_NO_OPERAND); 311 } 312 313 /* We know that this arg is a name, move to next arg */ 314 315 INCREMENT_ARG_LIST (WalkState->ArgTypes); 316 317 /* 318 * Find the object. This will either insert the object into 319 * the namespace or simply look it up 320 */ 321 WalkState->Op = NULL; 322 323 Status = WalkState->DescendingCallback (WalkState, Op); 324 if (ACPI_FAILURE (Status)) 325 { 326 ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog")); 327 return_ACPI_STATUS (Status); 328 } 329 330 if (!*Op) 331 { 332 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 333 } 334 335 Status = AcpiPsNextParseState (WalkState, *Op, Status); 336 if (ACPI_FAILURE (Status)) 337 { 338 if (Status == AE_CTRL_PENDING) 339 { 340 return_ACPI_STATUS (AE_CTRL_PARSE_PENDING); 341 } 342 return_ACPI_STATUS (Status); 343 } 344 345 AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); 346 AcpiGbl_Depth++; 347 348 if ((*Op)->Common.AmlOpcode == AML_REGION_OP || 349 (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP) 350 { 351 /* 352 * Defer final parsing of an OperationRegion body, because we don't 353 * have enough info in the first pass to parse it correctly (i.e., 354 * there may be method calls within the TermArg elements of the body.) 355 * 356 * However, we must continue parsing because the opregion is not a 357 * standalone package -- we don't know where the end is at this point. 358 * 359 * (Length is unknown until parse of the body complete) 360 */ 361 (*Op)->Named.Data = AmlOpStart; 362 (*Op)->Named.Length = 0; 363 } 364 365 return_ACPI_STATUS (AE_OK); 366 } 367 368 369 /******************************************************************************* 370 * 371 * FUNCTION: AcpiPsCreateOp 372 * 373 * PARAMETERS: WalkState - Current state 374 * AmlOpStart - Op start in AML 375 * NewOp - Returned Op 376 * 377 * RETURN: Status 378 * 379 * DESCRIPTION: Get Op from AML 380 * 381 ******************************************************************************/ 382 383 static ACPI_STATUS 384 AcpiPsCreateOp ( 385 ACPI_WALK_STATE *WalkState, 386 UINT8 *AmlOpStart, 387 ACPI_PARSE_OBJECT **NewOp) 388 { 389 ACPI_STATUS Status = AE_OK; 390 ACPI_PARSE_OBJECT *Op; 391 ACPI_PARSE_OBJECT *NamedOp = NULL; 392 ACPI_PARSE_OBJECT *ParentScope; 393 UINT8 ArgumentCount; 394 const ACPI_OPCODE_INFO *OpInfo; 395 396 397 ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState); 398 399 400 Status = AcpiPsGetAmlOpcode (WalkState); 401 if (Status == AE_CTRL_PARSE_CONTINUE) 402 { 403 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 404 } 405 406 /* Create Op structure and append to parent's argument list */ 407 408 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 409 Op = AcpiPsAllocOp (WalkState->Opcode); 410 if (!Op) 411 { 412 return_ACPI_STATUS (AE_NO_MEMORY); 413 } 414 415 if (WalkState->OpInfo->Flags & AML_NAMED) 416 { 417 Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp); 418 AcpiPsFreeOp (Op); 419 if (ACPI_FAILURE (Status)) 420 { 421 return_ACPI_STATUS (Status); 422 } 423 424 *NewOp = NamedOp; 425 return_ACPI_STATUS (AE_OK); 426 } 427 428 /* Not a named opcode, just allocate Op and append to parent */ 429 430 if (WalkState->OpInfo->Flags & AML_CREATE) 431 { 432 /* 433 * Backup to beginning of CreateXXXfield declaration 434 * BodyLength is unknown until we parse the body 435 */ 436 Op->Named.Data = AmlOpStart; 437 Op->Named.Length = 0; 438 } 439 440 if (WalkState->Opcode == AML_BANK_FIELD_OP) 441 { 442 /* 443 * Backup to beginning of BankField declaration 444 * BodyLength is unknown until we parse the body 445 */ 446 Op->Named.Data = AmlOpStart; 447 Op->Named.Length = 0; 448 } 449 450 ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState)); 451 AcpiPsAppendArg (ParentScope, Op); 452 453 if (ParentScope) 454 { 455 OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode); 456 if (OpInfo->Flags & AML_HAS_TARGET) 457 { 458 ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type); 459 if (ParentScope->Common.ArgListLength > ArgumentCount) 460 { 461 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 462 } 463 } 464 else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) 465 { 466 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 467 } 468 } 469 470 if (WalkState->DescendingCallback != NULL) 471 { 472 /* 473 * Find the object. This will either insert the object into 474 * the namespace or simply look it up 475 */ 476 WalkState->Op = *NewOp = Op; 477 478 Status = WalkState->DescendingCallback (WalkState, &Op); 479 Status = AcpiPsNextParseState (WalkState, Op, Status); 480 if (Status == AE_CTRL_PENDING) 481 { 482 Status = AE_CTRL_PARSE_PENDING; 483 } 484 } 485 486 return_ACPI_STATUS (Status); 487 } 488 489 490 /******************************************************************************* 491 * 492 * FUNCTION: AcpiPsGetArguments 493 * 494 * PARAMETERS: WalkState - Current state 495 * AmlOpStart - Op start in AML 496 * Op - Current Op 497 * 498 * RETURN: Status 499 * 500 * DESCRIPTION: Get arguments for passed Op. 501 * 502 ******************************************************************************/ 503 504 static ACPI_STATUS 505 AcpiPsGetArguments ( 506 ACPI_WALK_STATE *WalkState, 507 UINT8 *AmlOpStart, 508 ACPI_PARSE_OBJECT *Op) 509 { 510 ACPI_STATUS Status = AE_OK; 511 ACPI_PARSE_OBJECT *Arg = NULL; 512 const ACPI_OPCODE_INFO *OpInfo; 513 514 515 ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); 516 517 518 switch (Op->Common.AmlOpcode) 519 { 520 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ 521 case AML_WORD_OP: /* AML_WORDDATA_ARG */ 522 case AML_DWORD_OP: /* AML_DWORDATA_ARG */ 523 case AML_QWORD_OP: /* AML_QWORDATA_ARG */ 524 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ 525 526 /* Fill in constant or string argument directly */ 527 528 AcpiPsGetNextSimpleArg (&(WalkState->ParserState), 529 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); 530 break; 531 532 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ 533 534 Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1); 535 if (ACPI_FAILURE (Status)) 536 { 537 return_ACPI_STATUS (Status); 538 } 539 540 WalkState->ArgTypes = 0; 541 break; 542 543 default: 544 /* 545 * Op is not a constant or string, append each argument to the Op 546 */ 547 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount) 548 { 549 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml, 550 WalkState->ParserState.AmlStart); 551 552 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), 553 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); 554 if (ACPI_FAILURE (Status)) 555 { 556 return_ACPI_STATUS (Status); 557 } 558 559 if (Arg) 560 { 561 Arg->Common.AmlOffset = WalkState->AmlOffset; 562 AcpiPsAppendArg (Op, Arg); 563 } 564 565 INCREMENT_ARG_LIST (WalkState->ArgTypes); 566 } 567 568 569 /* 570 * Handle executable code at "module-level". This refers to 571 * executable opcodes that appear outside of any control method. 572 */ 573 if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) && 574 ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0)) 575 { 576 /* 577 * We want to skip If/Else/While constructs during Pass1 because we 578 * want to actually conditionally execute the code during Pass2. 579 * 580 * Except for disassembly, where we always want to walk the 581 * If/Else/While packages 582 */ 583 switch (Op->Common.AmlOpcode) 584 { 585 case AML_IF_OP: 586 case AML_ELSE_OP: 587 case AML_WHILE_OP: 588 589 /* 590 * Currently supported module-level opcodes are: 591 * IF/ELSE/WHILE. These appear to be the most common, 592 * and easiest to support since they open an AML 593 * package. 594 */ 595 if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) 596 { 597 AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart, 598 (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart), 599 WalkState->OwnerId); 600 } 601 602 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 603 "Pass1: Skipping an If/Else/While body\n")); 604 605 /* Skip body of if/else/while in pass 1 */ 606 607 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; 608 WalkState->ArgCount = 0; 609 break; 610 611 default: 612 /* 613 * Check for an unsupported executable opcode at module 614 * level. We must be in PASS1, the parent must be a SCOPE, 615 * The opcode class must be EXECUTE, and the opcode must 616 * not be an argument to another opcode. 617 */ 618 if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) && 619 (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) 620 { 621 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 622 if ((OpInfo->Class == AML_CLASS_EXECUTE) && 623 (!Arg)) 624 { 625 ACPI_WARNING ((AE_INFO, 626 "Detected an unsupported executable opcode " 627 "at module-level: [0x%.4X] at table offset 0x%.4X", 628 Op->Common.AmlOpcode, 629 (UINT32) (ACPI_PTR_DIFF (AmlOpStart, 630 WalkState->ParserState.AmlStart) + 631 sizeof (ACPI_TABLE_HEADER)))); 632 } 633 } 634 break; 635 } 636 } 637 638 /* Special processing for certain opcodes */ 639 640 switch (Op->Common.AmlOpcode) 641 { 642 case AML_METHOD_OP: 643 /* 644 * Skip parsing of control method because we don't have enough 645 * info in the first pass to parse it correctly. 646 * 647 * Save the length and address of the body 648 */ 649 Op->Named.Data = WalkState->ParserState.Aml; 650 Op->Named.Length = (UINT32) 651 (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml); 652 653 /* Skip body of method */ 654 655 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; 656 WalkState->ArgCount = 0; 657 break; 658 659 case AML_BUFFER_OP: 660 case AML_PACKAGE_OP: 661 case AML_VAR_PACKAGE_OP: 662 663 if ((Op->Common.Parent) && 664 (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && 665 (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) 666 { 667 /* 668 * Skip parsing of Buffers and Packages because we don't have 669 * enough info in the first pass to parse them correctly. 670 */ 671 Op->Named.Data = AmlOpStart; 672 Op->Named.Length = (UINT32) 673 (WalkState->ParserState.PkgEnd - AmlOpStart); 674 675 /* Skip body */ 676 677 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd; 678 WalkState->ArgCount = 0; 679 } 680 break; 681 682 case AML_WHILE_OP: 683 684 if (WalkState->ControlState) 685 { 686 WalkState->ControlState->Control.PackageEnd = 687 WalkState->ParserState.PkgEnd; 688 } 689 break; 690 691 default: 692 693 /* No action for all other opcodes */ 694 break; 695 } 696 697 break; 698 } 699 700 return_ACPI_STATUS (AE_OK); 701 } 702 703 704 /******************************************************************************* 705 * 706 * FUNCTION: AcpiPsLinkModuleCode 707 * 708 * PARAMETERS: ParentOp - Parent parser op 709 * AmlStart - Pointer to the AML 710 * AmlLength - Length of executable AML 711 * OwnerId - OwnerId of module level code 712 * 713 * RETURN: None. 714 * 715 * DESCRIPTION: Wrap the module-level code with a method object and link the 716 * object to the global list. Note, the mutex field of the method 717 * object is used to link multiple module-level code objects. 718 * 719 ******************************************************************************/ 720 721 static void 722 AcpiPsLinkModuleCode ( 723 ACPI_PARSE_OBJECT *ParentOp, 724 UINT8 *AmlStart, 725 UINT32 AmlLength, 726 ACPI_OWNER_ID OwnerId) 727 { 728 ACPI_OPERAND_OBJECT *Prev; 729 ACPI_OPERAND_OBJECT *Next; 730 ACPI_OPERAND_OBJECT *MethodObj; 731 ACPI_NAMESPACE_NODE *ParentNode; 732 733 734 /* Get the tail of the list */ 735 736 Prev = Next = AcpiGbl_ModuleCodeList; 737 while (Next) 738 { 739 Prev = Next; 740 Next = Next->Method.Mutex; 741 } 742 743 /* 744 * Insert the module level code into the list. Merge it if it is 745 * adjacent to the previous element. 746 */ 747 if (!Prev || 748 ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart)) 749 { 750 /* Create, initialize, and link a new temporary method object */ 751 752 MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 753 if (!MethodObj) 754 { 755 return; 756 } 757 758 if (ParentOp->Common.Node) 759 { 760 ParentNode = ParentOp->Common.Node; 761 } 762 else 763 { 764 ParentNode = AcpiGbl_RootNode; 765 } 766 767 MethodObj->Method.AmlStart = AmlStart; 768 MethodObj->Method.AmlLength = AmlLength; 769 MethodObj->Method.OwnerId = OwnerId; 770 MethodObj->Method.Flags |= AOPOBJ_MODULE_LEVEL; 771 772 /* 773 * Save the parent node in NextObject. This is cheating, but we 774 * don't want to expand the method object. 775 */ 776 MethodObj->Method.NextObject = 777 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode); 778 779 if (!Prev) 780 { 781 AcpiGbl_ModuleCodeList = MethodObj; 782 } 783 else 784 { 785 Prev->Method.Mutex = MethodObj; 786 } 787 } 788 else 789 { 790 Prev->Method.AmlLength += AmlLength; 791 } 792 } 793 794 795 /******************************************************************************* 796 * 797 * FUNCTION: AcpiPsCompleteOp 798 * 799 * PARAMETERS: WalkState - Current state 800 * Op - Returned Op 801 * Status - Parse status before complete Op 802 * 803 * RETURN: Status 804 * 805 * DESCRIPTION: Complete Op 806 * 807 ******************************************************************************/ 808 809 static ACPI_STATUS 810 AcpiPsCompleteOp ( 811 ACPI_WALK_STATE *WalkState, 812 ACPI_PARSE_OBJECT **Op, 813 ACPI_STATUS Status) 814 { 815 ACPI_STATUS Status2; 816 817 818 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); 819 820 821 /* 822 * Finished one argument of the containing scope 823 */ 824 WalkState->ParserState.Scope->ParseScope.ArgCount--; 825 826 /* Close this Op (will result in parse subtree deletion) */ 827 828 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 829 if (ACPI_FAILURE (Status2)) 830 { 831 return_ACPI_STATUS (Status2); 832 } 833 834 *Op = NULL; 835 836 switch (Status) 837 { 838 case AE_OK: 839 break; 840 841 842 case AE_CTRL_TRANSFER: 843 844 /* We are about to transfer to a called method */ 845 846 WalkState->PrevOp = NULL; 847 WalkState->PrevArgTypes = WalkState->ArgTypes; 848 return_ACPI_STATUS (Status); 849 850 851 case AE_CTRL_END: 852 853 AcpiPsPopScope (&(WalkState->ParserState), Op, 854 &WalkState->ArgTypes, &WalkState->ArgCount); 855 856 if (*Op) 857 { 858 WalkState->Op = *Op; 859 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 860 WalkState->Opcode = (*Op)->Common.AmlOpcode; 861 862 Status = WalkState->AscendingCallback (WalkState); 863 Status = AcpiPsNextParseState (WalkState, *Op, Status); 864 865 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 866 if (ACPI_FAILURE (Status2)) 867 { 868 return_ACPI_STATUS (Status2); 869 } 870 } 871 872 Status = AE_OK; 873 break; 874 875 876 case AE_CTRL_BREAK: 877 case AE_CTRL_CONTINUE: 878 879 /* Pop off scopes until we find the While */ 880 881 while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) 882 { 883 AcpiPsPopScope (&(WalkState->ParserState), Op, 884 &WalkState->ArgTypes, &WalkState->ArgCount); 885 } 886 887 /* Close this iteration of the While loop */ 888 889 WalkState->Op = *Op; 890 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 891 WalkState->Opcode = (*Op)->Common.AmlOpcode; 892 893 Status = WalkState->AscendingCallback (WalkState); 894 Status = AcpiPsNextParseState (WalkState, *Op, Status); 895 896 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 897 if (ACPI_FAILURE (Status2)) 898 { 899 return_ACPI_STATUS (Status2); 900 } 901 902 Status = AE_OK; 903 break; 904 905 906 case AE_CTRL_TERMINATE: 907 908 /* Clean up */ 909 do 910 { 911 if (*Op) 912 { 913 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 914 if (ACPI_FAILURE (Status2)) 915 { 916 return_ACPI_STATUS (Status2); 917 } 918 919 AcpiUtDeleteGenericState ( 920 AcpiUtPopGenericState (&WalkState->ControlState)); 921 } 922 923 AcpiPsPopScope (&(WalkState->ParserState), Op, 924 &WalkState->ArgTypes, &WalkState->ArgCount); 925 926 } while (*Op); 927 928 return_ACPI_STATUS (AE_OK); 929 930 931 default: /* All other non-AE_OK status */ 932 933 do 934 { 935 if (*Op) 936 { 937 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 938 if (ACPI_FAILURE (Status2)) 939 { 940 return_ACPI_STATUS (Status2); 941 } 942 } 943 944 AcpiPsPopScope (&(WalkState->ParserState), Op, 945 &WalkState->ArgTypes, &WalkState->ArgCount); 946 947 } while (*Op); 948 949 950 #if 0 951 /* 952 * TBD: Cleanup parse ops on error 953 */ 954 if (*Op == NULL) 955 { 956 AcpiPsPopScope (ParserState, Op, 957 &WalkState->ArgTypes, &WalkState->ArgCount); 958 } 959 #endif 960 WalkState->PrevOp = NULL; 961 WalkState->PrevArgTypes = WalkState->ArgTypes; 962 return_ACPI_STATUS (Status); 963 } 964 965 /* This scope complete? */ 966 967 if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) 968 { 969 AcpiPsPopScope (&(WalkState->ParserState), Op, 970 &WalkState->ArgTypes, &WalkState->ArgCount); 971 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); 972 } 973 else 974 { 975 *Op = NULL; 976 } 977 978 return_ACPI_STATUS (AE_OK); 979 } 980 981 982 /******************************************************************************* 983 * 984 * FUNCTION: AcpiPsCompleteFinalOp 985 * 986 * PARAMETERS: WalkState - Current state 987 * Op - Current Op 988 * Status - Current parse status before complete last 989 * Op 990 * 991 * RETURN: Status 992 * 993 * DESCRIPTION: Complete last Op. 994 * 995 ******************************************************************************/ 996 997 static ACPI_STATUS 998 AcpiPsCompleteFinalOp ( 999 ACPI_WALK_STATE *WalkState, 1000 ACPI_PARSE_OBJECT *Op, 1001 ACPI_STATUS Status) 1002 { 1003 ACPI_STATUS Status2; 1004 1005 1006 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState); 1007 1008 1009 /* 1010 * Complete the last Op (if not completed), and clear the scope stack. 1011 * It is easily possible to end an AML "package" with an unbounded number 1012 * of open scopes (such as when several ASL blocks are closed with 1013 * sequential closing braces). We want to terminate each one cleanly. 1014 */ 1015 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); 1016 do 1017 { 1018 if (Op) 1019 { 1020 if (WalkState->AscendingCallback != NULL) 1021 { 1022 WalkState->Op = Op; 1023 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 1024 WalkState->Opcode = Op->Common.AmlOpcode; 1025 1026 Status = WalkState->AscendingCallback (WalkState); 1027 Status = AcpiPsNextParseState (WalkState, Op, Status); 1028 if (Status == AE_CTRL_PENDING) 1029 { 1030 Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK); 1031 if (ACPI_FAILURE (Status)) 1032 { 1033 return_ACPI_STATUS (Status); 1034 } 1035 } 1036 1037 if (Status == AE_CTRL_TERMINATE) 1038 { 1039 Status = AE_OK; 1040 1041 /* Clean up */ 1042 do 1043 { 1044 if (Op) 1045 { 1046 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 1047 if (ACPI_FAILURE (Status2)) 1048 { 1049 return_ACPI_STATUS (Status2); 1050 } 1051 } 1052 1053 AcpiPsPopScope (&(WalkState->ParserState), &Op, 1054 &WalkState->ArgTypes, &WalkState->ArgCount); 1055 1056 } while (Op); 1057 1058 return_ACPI_STATUS (Status); 1059 } 1060 1061 else if (ACPI_FAILURE (Status)) 1062 { 1063 /* First error is most important */ 1064 1065 (void) AcpiPsCompleteThisOp (WalkState, Op); 1066 return_ACPI_STATUS (Status); 1067 } 1068 } 1069 1070 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 1071 if (ACPI_FAILURE (Status2)) 1072 { 1073 return_ACPI_STATUS (Status2); 1074 } 1075 } 1076 1077 AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, 1078 &WalkState->ArgCount); 1079 1080 } while (Op); 1081 1082 return_ACPI_STATUS (Status); 1083 } 1084 1085 1086 /******************************************************************************* 1087 * 1088 * FUNCTION: AcpiPsParseLoop 1089 * 1090 * PARAMETERS: WalkState - Current state 1091 * 1092 * RETURN: Status 1093 * 1094 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return 1095 * a tree of ops. 1096 * 1097 ******************************************************************************/ 1098 1099 ACPI_STATUS 1100 AcpiPsParseLoop ( 1101 ACPI_WALK_STATE *WalkState) 1102 { 1103 ACPI_STATUS Status = AE_OK; 1104 ACPI_PARSE_OBJECT *Op = NULL; /* current op */ 1105 ACPI_PARSE_STATE *ParserState; 1106 UINT8 *AmlOpStart = NULL; 1107 1108 1109 ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState); 1110 1111 1112 if (WalkState->DescendingCallback == NULL) 1113 { 1114 return_ACPI_STATUS (AE_BAD_PARAMETER); 1115 } 1116 1117 ParserState = &WalkState->ParserState; 1118 WalkState->ArgTypes = 0; 1119 1120 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) 1121 1122 if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART) 1123 { 1124 /* We are restarting a preempted control method */ 1125 1126 if (AcpiPsHasCompletedScope (ParserState)) 1127 { 1128 /* 1129 * We must check if a predicate to an IF or WHILE statement 1130 * was just completed 1131 */ 1132 if ((ParserState->Scope->ParseScope.Op) && 1133 ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) || 1134 (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) && 1135 (WalkState->ControlState) && 1136 (WalkState->ControlState->Common.State == 1137 ACPI_CONTROL_PREDICATE_EXECUTING)) 1138 { 1139 /* 1140 * A predicate was just completed, get the value of the 1141 * predicate and branch based on that value 1142 */ 1143 WalkState->Op = NULL; 1144 Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE)); 1145 if (ACPI_FAILURE (Status) && 1146 ((Status & AE_CODE_MASK) != AE_CODE_CONTROL)) 1147 { 1148 if (Status == AE_AML_NO_RETURN_VALUE) 1149 { 1150 ACPI_EXCEPTION ((AE_INFO, Status, 1151 "Invoked method did not return a value")); 1152 1153 } 1154 1155 ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed")); 1156 return_ACPI_STATUS (Status); 1157 } 1158 1159 Status = AcpiPsNextParseState (WalkState, Op, Status); 1160 } 1161 1162 AcpiPsPopScope (ParserState, &Op, 1163 &WalkState->ArgTypes, &WalkState->ArgCount); 1164 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); 1165 } 1166 else if (WalkState->PrevOp) 1167 { 1168 /* We were in the middle of an op */ 1169 1170 Op = WalkState->PrevOp; 1171 WalkState->ArgTypes = WalkState->PrevArgTypes; 1172 } 1173 } 1174 #endif 1175 1176 /* Iterative parsing loop, while there is more AML to process: */ 1177 1178 while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) 1179 { 1180 AmlOpStart = ParserState->Aml; 1181 if (!Op) 1182 { 1183 Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); 1184 if (ACPI_FAILURE (Status)) 1185 { 1186 if (Status == AE_CTRL_PARSE_CONTINUE) 1187 { 1188 continue; 1189 } 1190 1191 if (Status == AE_CTRL_PARSE_PENDING) 1192 { 1193 Status = AE_OK; 1194 } 1195 1196 Status = AcpiPsCompleteOp (WalkState, &Op, Status); 1197 if (ACPI_FAILURE (Status)) 1198 { 1199 return_ACPI_STATUS (Status); 1200 } 1201 1202 continue; 1203 } 1204 1205 Op->Common.AmlOffset = WalkState->AmlOffset; 1206 1207 if (WalkState->OpInfo) 1208 { 1209 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 1210 "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", 1211 (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name, 1212 Op, ParserState->Aml, Op->Common.AmlOffset)); 1213 } 1214 } 1215 1216 1217 /* 1218 * Start ArgCount at zero because we don't know if there are 1219 * any args yet 1220 */ 1221 WalkState->ArgCount = 0; 1222 1223 /* Are there any arguments that must be processed? */ 1224 1225 if (WalkState->ArgTypes) 1226 { 1227 /* Get arguments */ 1228 1229 Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op); 1230 if (ACPI_FAILURE (Status)) 1231 { 1232 Status = AcpiPsCompleteOp (WalkState, &Op, Status); 1233 if (ACPI_FAILURE (Status)) 1234 { 1235 return_ACPI_STATUS (Status); 1236 } 1237 1238 continue; 1239 } 1240 } 1241 1242 /* Check for arguments that need to be processed */ 1243 1244 if (WalkState->ArgCount) 1245 { 1246 /* 1247 * There are arguments (complex ones), push Op and 1248 * prepare for argument 1249 */ 1250 Status = AcpiPsPushScope (ParserState, Op, 1251 WalkState->ArgTypes, WalkState->ArgCount); 1252 if (ACPI_FAILURE (Status)) 1253 { 1254 Status = AcpiPsCompleteOp (WalkState, &Op, Status); 1255 if (ACPI_FAILURE (Status)) 1256 { 1257 return_ACPI_STATUS (Status); 1258 } 1259 1260 continue; 1261 } 1262 1263 Op = NULL; 1264 continue; 1265 } 1266 1267 /* 1268 * All arguments have been processed -- Op is complete, 1269 * prepare for next 1270 */ 1271 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 1272 if (WalkState->OpInfo->Flags & AML_NAMED) 1273 { 1274 if (AcpiGbl_Depth) 1275 { 1276 AcpiGbl_Depth--; 1277 } 1278 1279 if (Op->Common.AmlOpcode == AML_REGION_OP || 1280 Op->Common.AmlOpcode == AML_DATA_REGION_OP) 1281 { 1282 /* 1283 * Skip parsing of control method or opregion body, 1284 * because we don't have enough info in the first pass 1285 * to parse them correctly. 1286 * 1287 * Completed parsing an OpRegion declaration, we now 1288 * know the length. 1289 */ 1290 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); 1291 } 1292 } 1293 1294 if (WalkState->OpInfo->Flags & AML_CREATE) 1295 { 1296 /* 1297 * Backup to beginning of CreateXXXfield declaration (1 for 1298 * Opcode) 1299 * 1300 * BodyLength is unknown until we parse the body 1301 */ 1302 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); 1303 } 1304 1305 if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) 1306 { 1307 /* 1308 * Backup to beginning of BankField declaration 1309 * 1310 * BodyLength is unknown until we parse the body 1311 */ 1312 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); 1313 } 1314 1315 /* This op complete, notify the dispatcher */ 1316 1317 if (WalkState->AscendingCallback != NULL) 1318 { 1319 WalkState->Op = Op; 1320 WalkState->Opcode = Op->Common.AmlOpcode; 1321 1322 Status = WalkState->AscendingCallback (WalkState); 1323 Status = AcpiPsNextParseState (WalkState, Op, Status); 1324 if (Status == AE_CTRL_PENDING) 1325 { 1326 Status = AE_OK; 1327 } 1328 } 1329 1330 Status = AcpiPsCompleteOp (WalkState, &Op, Status); 1331 if (ACPI_FAILURE (Status)) 1332 { 1333 return_ACPI_STATUS (Status); 1334 } 1335 1336 } /* while ParserState->Aml */ 1337 1338 Status = AcpiPsCompleteFinalOp (WalkState, Op, Status); 1339 return_ACPI_STATUS (Status); 1340 } 1341 1342