1 /****************************************************************************** 2 * 3 * Module Name: psobject - Support for parse objects 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 ACPI_ERROR_ONLY (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 ACPI_ERROR_ONLY(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. 396 */ 397 WalkState->Aml = WalkState->ParserState.Aml + 2; 398 WalkState->ParserState.Aml = WalkState->Aml; 399 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); 400 } 401 #endif 402 if (ACPI_FAILURE (Status)) 403 { 404 return_ACPI_STATUS (Status); 405 } 406 407 *NewOp = NamedOp; 408 return_ACPI_STATUS (AE_OK); 409 } 410 411 /* Not a named opcode, just allocate Op and append to parent */ 412 413 if (WalkState->OpInfo->Flags & AML_CREATE) 414 { 415 /* 416 * Backup to beginning of CreateXXXfield declaration 417 * BodyLength is unknown until we parse the body 418 */ 419 Op->Named.Data = AmlOpStart; 420 Op->Named.Length = 0; 421 } 422 423 if (WalkState->Opcode == AML_BANK_FIELD_OP) 424 { 425 /* 426 * Backup to beginning of BankField declaration 427 * BodyLength is unknown until we parse the body 428 */ 429 Op->Named.Data = AmlOpStart; 430 Op->Named.Length = 0; 431 } 432 433 ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState)); 434 AcpiPsAppendArg (ParentScope, Op); 435 436 if (ParentScope) 437 { 438 OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode); 439 if (OpInfo->Flags & AML_HAS_TARGET) 440 { 441 ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type); 442 if (ParentScope->Common.ArgListLength > ArgumentCount) 443 { 444 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 445 } 446 } 447 448 /* 449 * Special case for both Increment() and Decrement(), where 450 * the lone argument is both a source and a target. 451 */ 452 else if ((ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) || 453 (ParentScope->Common.AmlOpcode == AML_DECREMENT_OP)) 454 { 455 Op->Common.Flags |= ACPI_PARSEOP_TARGET; 456 } 457 } 458 459 if (WalkState->DescendingCallback != NULL) 460 { 461 /* 462 * Find the object. This will either insert the object into 463 * the namespace or simply look it up 464 */ 465 WalkState->Op = *NewOp = Op; 466 467 Status = WalkState->DescendingCallback (WalkState, &Op); 468 Status = AcpiPsNextParseState (WalkState, Op, Status); 469 if (Status == AE_CTRL_PENDING) 470 { 471 Status = AE_CTRL_PARSE_PENDING; 472 } 473 } 474 475 return_ACPI_STATUS (Status); 476 } 477 478 479 /******************************************************************************* 480 * 481 * FUNCTION: AcpiPsCompleteOp 482 * 483 * PARAMETERS: WalkState - Current state 484 * Op - Returned Op 485 * Status - Parse status before complete Op 486 * 487 * RETURN: Status 488 * 489 * DESCRIPTION: Complete Op 490 * 491 ******************************************************************************/ 492 493 ACPI_STATUS 494 AcpiPsCompleteOp ( 495 ACPI_WALK_STATE *WalkState, 496 ACPI_PARSE_OBJECT **Op, 497 ACPI_STATUS Status) 498 { 499 ACPI_STATUS Status2; 500 501 502 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState); 503 504 505 /* 506 * Finished one argument of the containing scope 507 */ 508 WalkState->ParserState.Scope->ParseScope.ArgCount--; 509 510 /* Close this Op (will result in parse subtree deletion) */ 511 512 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 513 if (ACPI_FAILURE (Status2)) 514 { 515 return_ACPI_STATUS (Status2); 516 } 517 518 *Op = NULL; 519 520 switch (Status) 521 { 522 case AE_OK: 523 524 break; 525 526 case AE_CTRL_TRANSFER: 527 528 /* We are about to transfer to a called method */ 529 530 WalkState->PrevOp = NULL; 531 WalkState->PrevArgTypes = WalkState->ArgTypes; 532 return_ACPI_STATUS (Status); 533 534 case AE_CTRL_END: 535 536 AcpiPsPopScope (&(WalkState->ParserState), Op, 537 &WalkState->ArgTypes, &WalkState->ArgCount); 538 539 if (*Op) 540 { 541 WalkState->Op = *Op; 542 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 543 WalkState->Opcode = (*Op)->Common.AmlOpcode; 544 545 Status = WalkState->AscendingCallback (WalkState); 546 Status = AcpiPsNextParseState (WalkState, *Op, Status); 547 548 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 549 if (ACPI_FAILURE (Status2)) 550 { 551 return_ACPI_STATUS (Status2); 552 } 553 } 554 555 Status = AE_OK; 556 break; 557 558 case AE_CTRL_BREAK: 559 case AE_CTRL_CONTINUE: 560 561 /* Pop off scopes until we find the While */ 562 563 while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP)) 564 { 565 AcpiPsPopScope (&(WalkState->ParserState), Op, 566 &WalkState->ArgTypes, &WalkState->ArgCount); 567 } 568 569 /* Close this iteration of the While loop */ 570 571 WalkState->Op = *Op; 572 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode); 573 WalkState->Opcode = (*Op)->Common.AmlOpcode; 574 575 Status = WalkState->AscendingCallback (WalkState); 576 Status = AcpiPsNextParseState (WalkState, *Op, Status); 577 578 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 579 if (ACPI_FAILURE (Status2)) 580 { 581 return_ACPI_STATUS (Status2); 582 } 583 584 Status = AE_OK; 585 break; 586 587 case AE_CTRL_TERMINATE: 588 589 /* Clean up */ 590 do 591 { 592 if (*Op) 593 { 594 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 595 if (ACPI_FAILURE (Status2)) 596 { 597 return_ACPI_STATUS (Status2); 598 } 599 600 AcpiUtDeleteGenericState ( 601 AcpiUtPopGenericState (&WalkState->ControlState)); 602 } 603 604 AcpiPsPopScope (&(WalkState->ParserState), Op, 605 &WalkState->ArgTypes, &WalkState->ArgCount); 606 607 } while (*Op); 608 609 return_ACPI_STATUS (AE_OK); 610 611 default: /* All other non-AE_OK status */ 612 613 do 614 { 615 if (*Op) 616 { 617 Status2 = AcpiPsCompleteThisOp (WalkState, *Op); 618 if (ACPI_FAILURE (Status2)) 619 { 620 return_ACPI_STATUS (Status2); 621 } 622 } 623 624 AcpiPsPopScope (&(WalkState->ParserState), Op, 625 &WalkState->ArgTypes, &WalkState->ArgCount); 626 627 } while (*Op); 628 629 630 #if 0 631 /* 632 * TBD: Cleanup parse ops on error 633 */ 634 if (*Op == NULL) 635 { 636 AcpiPsPopScope (ParserState, Op, 637 &WalkState->ArgTypes, &WalkState->ArgCount); 638 } 639 #endif 640 WalkState->PrevOp = NULL; 641 WalkState->PrevArgTypes = WalkState->ArgTypes; 642 return_ACPI_STATUS (Status); 643 } 644 645 /* This scope complete? */ 646 647 if (AcpiPsHasCompletedScope (&(WalkState->ParserState))) 648 { 649 AcpiPsPopScope (&(WalkState->ParserState), Op, 650 &WalkState->ArgTypes, &WalkState->ArgCount); 651 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op)); 652 } 653 else 654 { 655 *Op = NULL; 656 } 657 658 return_ACPI_STATUS (AE_OK); 659 } 660 661 662 /******************************************************************************* 663 * 664 * FUNCTION: AcpiPsCompleteFinalOp 665 * 666 * PARAMETERS: WalkState - Current state 667 * Op - Current Op 668 * Status - Current parse status before complete last 669 * Op 670 * 671 * RETURN: Status 672 * 673 * DESCRIPTION: Complete last Op. 674 * 675 ******************************************************************************/ 676 677 ACPI_STATUS 678 AcpiPsCompleteFinalOp ( 679 ACPI_WALK_STATE *WalkState, 680 ACPI_PARSE_OBJECT *Op, 681 ACPI_STATUS Status) 682 { 683 ACPI_STATUS Status2; 684 685 686 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState); 687 688 689 /* 690 * Complete the last Op (if not completed), and clear the scope stack. 691 * It is easily possible to end an AML "package" with an unbounded number 692 * of open scopes (such as when several ASL blocks are closed with 693 * sequential closing braces). We want to terminate each one cleanly. 694 */ 695 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); 696 do 697 { 698 if (Op) 699 { 700 if (WalkState->AscendingCallback != NULL) 701 { 702 WalkState->Op = Op; 703 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 704 WalkState->Opcode = Op->Common.AmlOpcode; 705 706 Status = WalkState->AscendingCallback (WalkState); 707 Status = AcpiPsNextParseState (WalkState, Op, Status); 708 if (Status == AE_CTRL_PENDING) 709 { 710 Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK); 711 if (ACPI_FAILURE (Status)) 712 { 713 return_ACPI_STATUS (Status); 714 } 715 } 716 717 if (Status == AE_CTRL_TERMINATE) 718 { 719 Status = AE_OK; 720 721 /* Clean up */ 722 do 723 { 724 if (Op) 725 { 726 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 727 if (ACPI_FAILURE (Status2)) 728 { 729 return_ACPI_STATUS (Status2); 730 } 731 } 732 733 AcpiPsPopScope (&(WalkState->ParserState), &Op, 734 &WalkState->ArgTypes, &WalkState->ArgCount); 735 736 } while (Op); 737 738 return_ACPI_STATUS (Status); 739 } 740 741 else if (ACPI_FAILURE (Status)) 742 { 743 /* First error is most important */ 744 745 (void) AcpiPsCompleteThisOp (WalkState, Op); 746 return_ACPI_STATUS (Status); 747 } 748 } 749 750 Status2 = AcpiPsCompleteThisOp (WalkState, Op); 751 if (ACPI_FAILURE (Status2)) 752 { 753 return_ACPI_STATUS (Status2); 754 } 755 } 756 757 AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, 758 &WalkState->ArgCount); 759 760 } while (Op); 761 762 return_ACPI_STATUS (Status); 763 } 764