1 /****************************************************************************** 2 * 3 * Module Name: psobject - Support for parse objects 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 #include "acconvert.h" 49 50 #define _COMPONENT ACPI_PARSER 51 ACPI_MODULE_NAME ("psobject") 52 53 54 /* Local prototypes */ 55 56 static ACPI_STATUS 57 AcpiPsGetAmlOpcode ( 58 ACPI_WALK_STATE *WalkState); 59 60 61 /******************************************************************************* 62 * 63 * FUNCTION: AcpiPsGetAmlOpcode 64 * 65 * PARAMETERS: WalkState - Current state 66 * 67 * RETURN: Status 68 * 69 * DESCRIPTION: Extract the next AML opcode from the input stream. 70 * 71 ******************************************************************************/ 72 73 static ACPI_STATUS 74 AcpiPsGetAmlOpcode ( 75 ACPI_WALK_STATE *WalkState) 76 { 77 UINT32 AmlOffset; 78 79 80 ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); 81 82 83 WalkState->Aml = WalkState->ParserState.Aml; 84 WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState)); 85 86 /* 87 * First cut to determine what we have found: 88 * 1) A valid AML opcode 89 * 2) A name string 90 * 3) An unknown/invalid opcode 91 */ 92 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 93 94 switch (WalkState->OpInfo->Class) 95 { 96 case AML_CLASS_ASCII: 97 case AML_CLASS_PREFIX: 98 /* 99 * Starts with a valid prefix or ASCII char, this is a name 100 * string. Convert the bare name string to a namepath. 101 */ 102 WalkState->Opcode = AML_INT_NAMEPATH_OP; 103 WalkState->ArgTypes = ARGP_NAMESTRING; 104 break; 105 106 case AML_CLASS_UNKNOWN: 107 108 /* The opcode is unrecognized. Complain and skip unknown opcodes */ 109 110 if (WalkState->PassNumber == 2) 111 { 112 AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml, 113 WalkState->ParserState.AmlStart); 114 115 ACPI_ERROR ((AE_INFO, 116 "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", 117 WalkState->Opcode, 118 (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER)))); 119 120 ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48); 121 122 #ifdef ACPI_ASL_COMPILER 123 /* 124 * This is executed for the disassembler only. Output goes 125 * to the disassembled ASL output file. 126 */ 127 AcpiOsPrintf ( 128 "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", 129 WalkState->Opcode, 130 (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER))); 131 132 ACPI_ERROR ((AE_INFO, 133 "Aborting disassembly, AML byte code is corrupt")); 134 135 /* Dump the context surrounding the invalid opcode */ 136 137 AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16), 138 48, DB_BYTE_DISPLAY, 139 (AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16)); 140 AcpiOsPrintf (" */\n"); 141 142 /* 143 * Just abort the disassembly, cannot continue because the 144 * parser is essentially lost. The disassembler can then 145 * randomly fail because an ill-constructed parse tree 146 * can result. 147 */ 148 return_ACPI_STATUS (AE_AML_BAD_OPCODE); 149 #endif 150 } 151 152 /* Increment past one-byte or two-byte opcode */ 153 154 WalkState->ParserState.Aml++; 155 if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */ 156 { 157 WalkState->ParserState.Aml++; 158 } 159 160 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 161 162 default: 163 164 /* Found opcode info, this is a normal opcode */ 165 166 WalkState->ParserState.Aml += 167 AcpiPsGetOpcodeSize (WalkState->Opcode); 168 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; 169 break; 170 } 171 172 return_ACPI_STATUS (AE_OK); 173 } 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: AcpiPsBuildNamedOp 179 * 180 * PARAMETERS: WalkState - Current state 181 * AmlOpStart - Begin of named Op in AML 182 * UnnamedOp - Early Op (not a named Op) 183 * Op - Returned Op 184 * 185 * RETURN: Status 186 * 187 * DESCRIPTION: Parse a named Op 188 * 189 ******************************************************************************/ 190 191 ACPI_STATUS 192 AcpiPsBuildNamedOp ( 193 ACPI_WALK_STATE *WalkState, 194 UINT8 *AmlOpStart, 195 ACPI_PARSE_OBJECT *UnnamedOp, 196 ACPI_PARSE_OBJECT **Op) 197 { 198 ACPI_STATUS Status = AE_OK; 199 ACPI_PARSE_OBJECT *Arg = NULL; 200 201 202 ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState); 203 204 205 UnnamedOp->Common.Value.Arg = NULL; 206 UnnamedOp->Common.ArgListLength = 0; 207 UnnamedOp->Common.AmlOpcode = WalkState->Opcode; 208 209 /* 210 * Get and append arguments until we find the node that contains 211 * the name (the type ARGP_NAME). 212 */ 213 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && 214 (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME)) 215 { 216 ASL_CV_CAPTURE_COMMENTS (WalkState); 217 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), 218 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); 219 if (ACPI_FAILURE (Status)) 220 { 221 return_ACPI_STATUS (Status); 222 } 223 224 AcpiPsAppendArg (UnnamedOp, Arg); 225 INCREMENT_ARG_LIST (WalkState->ArgTypes); 226 } 227 228 /* are there any inline comments associated with the NameSeg?? If so, save this. */ 229 230 ASL_CV_CAPTURE_COMMENTS (WalkState); 231 232 #ifdef ACPI_ASL_COMPILER 233 if (AcpiGbl_CurrentInlineComment != NULL) 234 { 235 UnnamedOp->Common.NameComment = AcpiGbl_CurrentInlineComment; 236 AcpiGbl_CurrentInlineComment = NULL; 237 } 238 #endif 239 240 /* 241 * Make sure that we found a NAME and didn't run out of arguments 242 */ 243 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes)) 244 { 245 return_ACPI_STATUS (AE_AML_NO_OPERAND); 246 } 247 248 /* We know that this arg is a name, move to next arg */ 249 250 INCREMENT_ARG_LIST (WalkState->ArgTypes); 251 252 /* 253 * Find the object. This will either insert the object into 254 * the namespace or simply look it up 255 */ 256 WalkState->Op = NULL; 257 258 Status = WalkState->DescendingCallback (WalkState, Op); 259 if (ACPI_FAILURE (Status)) 260 { 261 if (Status != AE_CTRL_TERMINATE) 262 { 263 ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog")); 264 } 265 return_ACPI_STATUS (Status); 266 } 267 268 if (!*Op) 269 { 270 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 271 } 272 273 Status = AcpiPsNextParseState (WalkState, *Op, Status); 274 if (ACPI_FAILURE (Status)) 275 { 276 if (Status == AE_CTRL_PENDING) 277 { 278 Status = AE_CTRL_PARSE_PENDING; 279 } 280 return_ACPI_STATUS (Status); 281 } 282 283 AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); 284 285 #ifdef ACPI_ASL_COMPILER 286 287 /* save any comments that might be associated with UnnamedOp. */ 288 289 (*Op)->Common.InlineComment = UnnamedOp->Common.InlineComment; 290 (*Op)->Common.EndNodeComment = UnnamedOp->Common.EndNodeComment; 291 (*Op)->Common.CloseBraceComment = UnnamedOp->Common.CloseBraceComment; 292 (*Op)->Common.NameComment = UnnamedOp->Common.NameComment; 293 (*Op)->Common.CommentList = UnnamedOp->Common.CommentList; 294 (*Op)->Common.EndBlkComment = UnnamedOp->Common.EndBlkComment; 295 (*Op)->Common.CvFilename = UnnamedOp->Common.CvFilename; 296 (*Op)->Common.CvParentFilename = UnnamedOp->Common.CvParentFilename; 297 (*Op)->Named.Aml = UnnamedOp->Common.Aml; 298 299 UnnamedOp->Common.InlineComment = NULL; 300 UnnamedOp->Common.EndNodeComment = NULL; 301 UnnamedOp->Common.CloseBraceComment = NULL; 302 UnnamedOp->Common.NameComment = NULL; 303 UnnamedOp->Common.CommentList = NULL; 304 UnnamedOp->Common.EndBlkComment = NULL; 305 #endif 306 307 if ((*Op)->Common.AmlOpcode == AML_REGION_OP || 308 (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP) 309 { 310 /* 311 * Defer final parsing of an OperationRegion body, because we don't 312 * have enough info in the first pass to parse it correctly (i.e., 313 * there may be method calls within the TermArg elements of the body.) 314 * 315 * However, we must continue parsing because the opregion is not a 316 * standalone package -- we don't know where the end is at this point. 317 * 318 * (Length is unknown until parse of the body complete) 319 */ 320 (*Op)->Named.Data = AmlOpStart; 321 (*Op)->Named.Length = 0; 322 } 323 324 return_ACPI_STATUS (AE_OK); 325 } 326 327 328 /******************************************************************************* 329 * 330 * FUNCTION: AcpiPsCreateOp 331 * 332 * PARAMETERS: WalkState - Current state 333 * AmlOpStart - Op start in AML 334 * NewOp - Returned Op 335 * 336 * RETURN: Status 337 * 338 * DESCRIPTION: Get Op from AML 339 * 340 ******************************************************************************/ 341 342 ACPI_STATUS 343 AcpiPsCreateOp ( 344 ACPI_WALK_STATE *WalkState, 345 UINT8 *AmlOpStart, 346 ACPI_PARSE_OBJECT **NewOp) 347 { 348 ACPI_STATUS Status = AE_OK; 349 ACPI_PARSE_OBJECT *Op; 350 ACPI_PARSE_OBJECT *NamedOp = NULL; 351 ACPI_PARSE_OBJECT *ParentScope; 352 UINT8 ArgumentCount; 353 const ACPI_OPCODE_INFO *OpInfo; 354 355 356 ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState); 357 358 359 Status = AcpiPsGetAmlOpcode (WalkState); 360 if (Status == AE_CTRL_PARSE_CONTINUE) 361 { 362 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 363 } 364 if (ACPI_FAILURE (Status)) 365 { 366 return_ACPI_STATUS (Status); 367 } 368 369 /* Create Op structure and append to parent's argument list */ 370 371 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 372 Op = AcpiPsAllocOp (WalkState->Opcode, AmlOpStart); 373 if (!Op) 374 { 375 return_ACPI_STATUS (AE_NO_MEMORY); 376 } 377 378 if (WalkState->OpInfo->Flags & AML_NAMED) 379 { 380 Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp); 381 AcpiPsFreeOp (Op); 382 383 #ifdef ACPI_ASL_COMPILER 384 if (AcpiGbl_DisasmFlag && WalkState->Opcode == AML_EXTERNAL_OP && 385 Status == AE_NOT_FOUND) 386 { 387 /* 388 * If parsing of AML_EXTERNAL_OP's name path fails, then skip 389 * past this opcode and keep parsing. This is a much better 390 * alternative than to abort the entire disassembler. At this 391 * point, the ParserState is at the end of the namepath of the 392 * external declaration opcode. Setting WalkState->Aml to 393 * WalkState->ParserState.Aml + 2 moves increments the 394 * WalkState->Aml past the object type and the paramcount of the 395 * external opcode. For the error message, only print the AML 396 * offset. We could attempt to print the name but this may cause 397 * a segmentation fault when printing the namepath because the 398 * AML may be incorrect. 399 */ 400 AcpiOsPrintf ( 401 "// Invalid external declaration at AML offset 0x%x.\n", 402 WalkState->Aml - WalkState->ParserState.AmlStart); 403 WalkState->Aml = WalkState->ParserState.Aml + 2; 404 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 405 } 406 #endif 407 if (ACPI_FAILURE (Status)) 408 { 409 return_ACPI_STATUS (Status); 410 } 411 412 *NewOp = NamedOp; 413 return_ACPI_STATUS (AE_OK); 414 } 415 416 /* Not a named opcode, just allocate Op and append to parent */ 417 418 if (WalkState->OpInfo->Flags & AML_CREATE) 419 { 420 /* 421 * Backup to beginning of CreateXXXfield declaration 422 * BodyLength is unknown until we parse the body 423 */ 424 Op->Named.Data = AmlOpStart; 425 Op->Named.Length = 0; 426 } 427 428 if (WalkState->Opcode == AML_BANK_FIELD_OP) 429 { 430 /* 431 * Backup to beginning of BankField declaration 432 * BodyLength is unknown until we parse the body 433 */ 434 Op->Named.Data = AmlOpStart; 435 Op->Named.Length = 0; 436 } 437 438 ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState)); 439 AcpiPsAppendArg (ParentScope, Op); 440 441 if (ParentScope) 442 { 443 OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode); 444 if (OpInfo->Flags & AML_HAS_TARGET) 445 { 446 ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type); 447 if (ParentScope->Common.ArgListLength > ArgumentCount) 448 { 449 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 450 } 451 } 452 453 /* 454 * Special case for both Increment() and Decrement(), where 455 * the lone argument is both a source and a target. 456 */ 457 else if ((ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) || 458 (ParentScope->Common.AmlOpcode == AML_DECREMENT_OP)) 459 { 460 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 461 } 462 } 463 464 if (WalkState->DescendingCallback != NULL) 465 { 466 /* 467 * Find the object. This will either insert the object into 468 * the namespace or simply look it up 469 */ 470 WalkState->Op = *NewOp = Op; 471 472 Status = WalkState->DescendingCallback (WalkState, &Op); 473 Status = AcpiPsNextParseState (WalkState, Op, Status); 474 if (Status == AE_CTRL_PENDING) 475 { 476 Status = AE_CTRL_PARSE_PENDING; 477 } 478 } 479 480 return_ACPI_STATUS (Status); 481 } 482 483 484 /******************************************************************************* 485 * 486 * FUNCTION: AcpiPsCompleteOp 487 * 488 * PARAMETERS: WalkState - Current state 489 * Op - Returned Op 490 * Status - Parse status before complete Op 491 * 492 * RETURN: Status 493 * 494 * DESCRIPTION: Complete Op 495 * 496 ******************************************************************************/ 497 498 ACPI_STATUS 499 AcpiPsCompleteOp ( 500 ACPI_WALK_STATE *WalkState, 501 ACPI_PARSE_OBJECT **Op, 502 ACPI_STATUS Status) 503 { 504 ACPI_STATUS Status2; 505 506 507 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); 508 509 510 /* 511 * Finished one argument of the containing scope 512 */ 513 WalkState->ParserState.Scope->ParseScope.ArgCount--; 514 515 /* Close this Op (will result in parse subtree deletion) */ 516 517 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 518 if (ACPI_FAILURE (Status2)) 519 { 520 return_ACPI_STATUS (Status2); 521 } 522 523 *Op = NULL; 524 525 switch (Status) 526 { 527 case AE_OK: 528 529 break; 530 531 case AE_CTRL_TRANSFER: 532 533 /* We are about to transfer to a called method */ 534 535 WalkState->PrevOp = NULL; 536 WalkState->PrevArgTypes = WalkState->ArgTypes; 537 return_ACPI_STATUS (Status); 538 539 case AE_CTRL_END: 540 541 AcpiPsPopScope (&(WalkState->ParserState), Op, 542 &WalkState->ArgTypes, &WalkState->ArgCount); 543 544 if (*Op) 545 { 546 WalkState->Op = *Op; 547 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 548 WalkState->Opcode = (*Op)->Common.AmlOpcode; 549 550 Status = WalkState->AscendingCallback (WalkState); 551 Status = AcpiPsNextParseState (WalkState, *Op, Status); 552 553 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 554 if (ACPI_FAILURE (Status2)) 555 { 556 return_ACPI_STATUS (Status2); 557 } 558 } 559 560 Status = AE_OK; 561 break; 562 563 case AE_CTRL_BREAK: 564 case AE_CTRL_CONTINUE: 565 566 /* Pop off scopes until we find the While */ 567 568 while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) 569 { 570 AcpiPsPopScope (&(WalkState->ParserState), Op, 571 &WalkState->ArgTypes, &WalkState->ArgCount); 572 } 573 574 /* Close this iteration of the While loop */ 575 576 WalkState->Op = *Op; 577 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 578 WalkState->Opcode = (*Op)->Common.AmlOpcode; 579 580 Status = WalkState->AscendingCallback (WalkState); 581 Status = AcpiPsNextParseState (WalkState, *Op, Status); 582 583 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 584 if (ACPI_FAILURE (Status2)) 585 { 586 return_ACPI_STATUS (Status2); 587 } 588 589 Status = AE_OK; 590 break; 591 592 case AE_CTRL_TERMINATE: 593 594 /* Clean up */ 595 do 596 { 597 if (*Op) 598 { 599 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 600 if (ACPI_FAILURE (Status2)) 601 { 602 return_ACPI_STATUS (Status2); 603 } 604 605 AcpiUtDeleteGenericState ( 606 AcpiUtPopGenericState (&WalkState->ControlState)); 607 } 608 609 AcpiPsPopScope (&(WalkState->ParserState), Op, 610 &WalkState->ArgTypes, &WalkState->ArgCount); 611 612 } while (*Op); 613 614 return_ACPI_STATUS (AE_OK); 615 616 default: /* All other non-AE_OK status */ 617 618 do 619 { 620 if (*Op) 621 { 622 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 623 if (ACPI_FAILURE (Status2)) 624 { 625 return_ACPI_STATUS (Status2); 626 } 627 } 628 629 AcpiPsPopScope (&(WalkState->ParserState), Op, 630 &WalkState->ArgTypes, &WalkState->ArgCount); 631 632 } while (*Op); 633 634 635 #if 0 636 /* 637 * TBD: Cleanup parse ops on error 638 */ 639 if (*Op == NULL) 640 { 641 AcpiPsPopScope (ParserState, Op, 642 &WalkState->ArgTypes, &WalkState->ArgCount); 643 } 644 #endif 645 WalkState->PrevOp = NULL; 646 WalkState->PrevArgTypes = WalkState->ArgTypes; 647 return_ACPI_STATUS (Status); 648 } 649 650 /* This scope complete? */ 651 652 if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) 653 { 654 AcpiPsPopScope (&(WalkState->ParserState), Op, 655 &WalkState->ArgTypes, &WalkState->ArgCount); 656 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); 657 } 658 else 659 { 660 *Op = NULL; 661 } 662 663 return_ACPI_STATUS (AE_OK); 664 } 665 666 667 /******************************************************************************* 668 * 669 * FUNCTION: AcpiPsCompleteFinalOp 670 * 671 * PARAMETERS: WalkState - Current state 672 * Op - Current Op 673 * Status - Current parse status before complete last 674 * Op 675 * 676 * RETURN: Status 677 * 678 * DESCRIPTION: Complete last Op. 679 * 680 ******************************************************************************/ 681 682 ACPI_STATUS 683 AcpiPsCompleteFinalOp ( 684 ACPI_WALK_STATE *WalkState, 685 ACPI_PARSE_OBJECT *Op, 686 ACPI_STATUS Status) 687 { 688 ACPI_STATUS Status2; 689 690 691 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState); 692 693 694 /* 695 * Complete the last Op (if not completed), and clear the scope stack. 696 * It is easily possible to end an AML "package" with an unbounded number 697 * of open scopes (such as when several ASL blocks are closed with 698 * sequential closing braces). We want to terminate each one cleanly. 699 */ 700 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); 701 do 702 { 703 if (Op) 704 { 705 if (WalkState->AscendingCallback != NULL) 706 { 707 WalkState->Op = Op; 708 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 709 WalkState->Opcode = Op->Common.AmlOpcode; 710 711 Status = WalkState->AscendingCallback (WalkState); 712 Status = AcpiPsNextParseState (WalkState, Op, Status); 713 if (Status == AE_CTRL_PENDING) 714 { 715 Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK); 716 if (ACPI_FAILURE (Status)) 717 { 718 return_ACPI_STATUS (Status); 719 } 720 } 721 722 if (Status == AE_CTRL_TERMINATE) 723 { 724 Status = AE_OK; 725 726 /* Clean up */ 727 do 728 { 729 if (Op) 730 { 731 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 732 if (ACPI_FAILURE (Status2)) 733 { 734 return_ACPI_STATUS (Status2); 735 } 736 } 737 738 AcpiPsPopScope (&(WalkState->ParserState), &Op, 739 &WalkState->ArgTypes, &WalkState->ArgCount); 740 741 } while (Op); 742 743 return_ACPI_STATUS (Status); 744 } 745 746 else if (ACPI_FAILURE (Status)) 747 { 748 /* First error is most important */ 749 750 (void) AcpiPsCompleteThisOp (WalkState, Op); 751 return_ACPI_STATUS (Status); 752 } 753 } 754 755 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 756 if (ACPI_FAILURE (Status2)) 757 { 758 return_ACPI_STATUS (Status2); 759 } 760 } 761 762 AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, 763 &WalkState->ArgCount); 764 765 } while (Op); 766 767 return_ACPI_STATUS (Status); 768 } 769