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