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