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