psparse.c revision 99146
1/****************************************************************************** 2 * 3 * Module Name: psparse - Parser top level AML parse routines 4 * $Revision: 121 $ 5 * 6 *****************************************************************************/ 7 8/****************************************************************************** 9 * 10 * 1. Copyright Notice 11 * 12 * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp. 13 * All rights reserved. 14 * 15 * 2. License 16 * 17 * 2.1. This is your license from Intel Corp. under its intellectual property 18 * rights. You may have additional license terms from the party that provided 19 * you this software, covering your right to use that party's intellectual 20 * property rights. 21 * 22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23 * copy of the source code appearing in this file ("Covered Code") an 24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25 * base code distributed originally by Intel ("Original Intel Code") to copy, 26 * make derivatives, distribute, use and display any portion of the Covered 27 * Code in any form, with the right to sublicense such rights; and 28 * 29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30 * license (with the right to sublicense), under only those claims of Intel 31 * patents that are infringed by the Original Intel Code, to make, use, sell, 32 * offer to sell, and import the Covered Code and derivative works thereof 33 * solely to the minimum extent necessary to exercise the above copyright 34 * license, and in no event shall the patent license extend to any additions 35 * to or modifications of the Original Intel Code. No other license or right 36 * is granted directly or by implication, estoppel or otherwise; 37 * 38 * The above copyright and patent license is granted only if the following 39 * conditions are met: 40 * 41 * 3. Conditions 42 * 43 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44 * Redistribution of source code of any substantial portion of the Covered 45 * Code or modification with rights to further distribute source must include 46 * the above Copyright Notice, the above License, this list of Conditions, 47 * and the following Disclaimer and Export Compliance provision. In addition, 48 * Licensee must cause all Covered Code to which Licensee contributes to 49 * contain a file documenting the changes Licensee made to create that Covered 50 * Code and the date of any change. Licensee must include in that file the 51 * documentation of any changes made by any predecessor Licensee. Licensee 52 * must include a prominent statement that the modification is derived, 53 * directly or indirectly, from Original Intel Code. 54 * 55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56 * Redistribution of source code of any substantial portion of the Covered 57 * Code or modification without rights to further distribute source must 58 * include the following Disclaimer and Export Compliance provision in the 59 * documentation and/or other materials provided with distribution. In 60 * addition, Licensee may not authorize further sublicense of source of any 61 * portion of the Covered Code, and must include terms to the effect that the 62 * license from Licensee to its licensee is limited to the intellectual 63 * property embodied in the software Licensee provides to its licensee, and 64 * not to intellectual property embodied in modifications its licensee may 65 * make. 66 * 67 * 3.3. Redistribution of Executable. Redistribution in executable form of any 68 * substantial portion of the Covered Code or modification must reproduce the 69 * above Copyright Notice, and the following Disclaimer and Export Compliance 70 * provision in the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3.4. Intel retains all right, title, and interest in and to the Original 74 * Intel Code. 75 * 76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77 * Intel shall be used in advertising or otherwise to promote the sale, use or 78 * other dealings in products derived from or relating to the Covered Code 79 * without prior written authorization from Intel. 80 * 81 * 4. Disclaimer and Export Compliance 82 * 83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89 * PARTICULAR PURPOSE. 90 * 91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98 * LIMITED REMEDY. 99 * 100 * 4.3. Licensee shall not export, either directly or indirectly, any of this 101 * software or system incorporating such software without first obtaining any 102 * required license or other approval from the U. S. Department of Commerce or 103 * any other agency or department of the United States Government. In the 104 * event Licensee exports any such software from the United States or 105 * re-exports any such software from a foreign destination, Licensee shall 106 * ensure that the distribution and export/re-export of the software is in 107 * compliance with all laws, regulations, orders, or other restrictions of the 108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109 * any of its subsidiaries will export/re-export any technical data, process, 110 * software, or service, directly or indirectly, to any country for which the 111 * United States government or any agency thereof requires an export license, 112 * other governmental approval, or letter of assurance, without first obtaining 113 * such license, approval or letter. 114 * 115 *****************************************************************************/ 116 117 118/* 119 * Parse the AML and build an operation tree as most interpreters, 120 * like Perl, do. Parsing is done by hand rather than with a YACC 121 * generated parser to tightly constrain stack and dynamic memory 122 * usage. At the same time, parsing is kept flexible and the code 123 * fairly compact by parsing based on a list of AML opcode 124 * templates in AmlOpInfo[] 125 */ 126 127#include "acpi.h" 128#include "acparser.h" 129#include "acdispat.h" 130#include "amlcode.h" 131#include "acnamesp.h" 132#include "acdebug.h" 133#include "acinterp.h" 134 135#define _COMPONENT ACPI_PARSER 136 ACPI_MODULE_NAME ("psparse") 137 138 139UINT32 AcpiGbl_Depth = 0; 140extern UINT32 AcpiGbl_ScopeDepth; 141 142 143/******************************************************************************* 144 * 145 * FUNCTION: AcpiPsGetOpcodeSize 146 * 147 * PARAMETERS: Opcode - An AML opcode 148 * 149 * RETURN: Size of the opcode, in bytes (1 or 2) 150 * 151 * DESCRIPTION: Get the size of the current opcode. 152 * 153 ******************************************************************************/ 154 155UINT32 156AcpiPsGetOpcodeSize ( 157 UINT32 Opcode) 158{ 159 160 /* Extended (2-byte) opcode if > 255 */ 161 162 if (Opcode > 0x00FF) 163 { 164 return (2); 165 } 166 167 /* Otherwise, just a single byte opcode */ 168 169 return (1); 170} 171 172 173/******************************************************************************* 174 * 175 * FUNCTION: AcpiPsPeekOpcode 176 * 177 * PARAMETERS: ParserState - A parser state object 178 * 179 * RETURN: Status 180 * 181 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) 182 * 183 ******************************************************************************/ 184 185UINT16 186AcpiPsPeekOpcode ( 187 ACPI_PARSE_STATE *ParserState) 188{ 189 UINT8 *Aml; 190 UINT16 Opcode; 191 192 193 Aml = ParserState->Aml; 194 Opcode = (UINT16) ACPI_GET8 (Aml); 195 196 197 if (Opcode == AML_EXTOP) 198 { 199 /* Extended opcode */ 200 201 Aml++; 202 Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml)); 203 } 204 205 return (Opcode); 206} 207 208 209/******************************************************************************* 210 * 211 * FUNCTION: AcpiPsFindObject 212 * 213 * PARAMETERS: Opcode - Current opcode 214 * ParserState - Current state 215 * WalkState - Current state 216 * *Op - Where found/new op is returned 217 * 218 * RETURN: Status 219 * 220 * DESCRIPTION: Find a named object. Two versions - one to search the parse 221 * tree (for parser-only applications such as acpidump), another 222 * to search the ACPI internal namespace (the parse tree may no 223 * longer exist) 224 * 225 ******************************************************************************/ 226 227#ifdef PARSER_ONLY 228 229ACPI_STATUS 230AcpiPsFindObject ( 231 ACPI_WALK_STATE *WalkState, 232 ACPI_PARSE_OBJECT **OutOp) 233{ 234 NATIVE_CHAR *Path; 235 236 237 /* We are only interested in opcodes that have an associated name */ 238 239 if (!(WalkState->OpInfo->Flags & AML_NAMED)) 240 { 241 *OutOp = WalkState->Op; 242 return (AE_OK); 243 } 244 245 /* Find the name in the parse tree */ 246 247 Path = AcpiPsGetNextNamestring (&WalkState->ParserState); 248 249 *OutOp = AcpiPsFind (AcpiPsGetParentScope (&WalkState->ParserState), 250 Path, WalkState->Opcode, 1); 251 252 if (!(*OutOp)) 253 { 254 return (AE_NOT_FOUND); 255 } 256 257 return (AE_OK); 258} 259 260#endif 261 262 263/******************************************************************************* 264 * 265 * FUNCTION: AcpiPsCompleteThisOp 266 * 267 * PARAMETERS: WalkState - Current State 268 * Op - Op to complete 269 * 270 * RETURN: TRUE if Op and subtree was deleted 271 * 272 * DESCRIPTION: Perform any cleanup at the completion of an Op. 273 * 274 ******************************************************************************/ 275 276BOOLEAN 277AcpiPsCompleteThisOp ( 278 ACPI_WALK_STATE *WalkState, 279 ACPI_PARSE_OBJECT *Op) 280{ 281#ifndef PARSER_ONLY 282 ACPI_PARSE_OBJECT *Prev; 283 ACPI_PARSE_OBJECT *Next; 284 const ACPI_OPCODE_INFO *ParentInfo; 285 ACPI_PARSE_OBJECT *ReplacementOp = NULL; 286 287 288 ACPI_FUNCTION_TRACE_PTR ("PsCompleteThisOp", Op); 289 290 291 /* Check for null Op, can happen if AML code is corrupt */ 292 293 if (!Op) 294 { 295 return_VALUE (TRUE); 296 } 297 298 /* Delete this op and the subtree below it if asked to */ 299 300 if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) && 301 (WalkState->OpInfo->Class != AML_CLASS_ARGUMENT)) 302 { 303 /* Make sure that we only delete this subtree */ 304 305 if (Op->Parent) 306 { 307 /* 308 * Check if we need to replace the operator and its subtree 309 * with a return value op (placeholder op) 310 */ 311 ParentInfo = AcpiPsGetOpcodeInfo (Op->Parent->Opcode); 312 313 switch (ParentInfo->Class) 314 { 315 case AML_CLASS_CONTROL: 316 break; 317 318 case AML_CLASS_CREATE: 319 320 /* 321 * These opcodes contain TermArg operands. The current 322 * op must be replaced by a placeholder return op 323 */ 324 ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); 325 if (!ReplacementOp) 326 { 327 return_VALUE (FALSE); 328 } 329 break; 330 331 case AML_CLASS_NAMED_OBJECT: 332 333 /* 334 * These opcodes contain TermArg operands. The current 335 * op must be replaced by a placeholder return op 336 */ 337 if ((Op->Parent->Opcode == AML_REGION_OP) || 338 (Op->Parent->Opcode == AML_DATA_REGION_OP) || 339 (Op->Parent->Opcode == AML_BUFFER_OP) || 340 (Op->Parent->Opcode == AML_PACKAGE_OP) || 341 (Op->Parent->Opcode == AML_VAR_PACKAGE_OP)) 342 { 343 ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); 344 if (!ReplacementOp) 345 { 346 return_VALUE (FALSE); 347 } 348 } 349 350 if ((Op->Parent->Opcode == AML_NAME_OP) && 351 (WalkState->DescendingCallback != AcpiDsExecBeginOp)) 352 353 { 354 if ((Op->Opcode == AML_BUFFER_OP) || 355 (Op->Opcode == AML_PACKAGE_OP) || 356 (Op->Opcode == AML_VAR_PACKAGE_OP)) 357 { 358 ReplacementOp = AcpiPsAllocOp (Op->Opcode); 359 if (!ReplacementOp) 360 { 361 return_VALUE (FALSE); 362 } 363 364 ((ACPI_PARSE2_OBJECT *) ReplacementOp)->Data = 365 ((ACPI_PARSE2_OBJECT *) Op)->Data; 366 ((ACPI_PARSE2_OBJECT *) ReplacementOp)->Length = 367 ((ACPI_PARSE2_OBJECT *) Op)->Length; 368 } 369 } 370 break; 371 372 default: 373 ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP); 374 if (!ReplacementOp) 375 { 376 return_VALUE (FALSE); 377 } 378 } 379 380 /* We must unlink this op from the parent tree */ 381 382 Prev = Op->Parent->Value.Arg; 383 if (Prev == Op) 384 { 385 /* This op is the first in the list */ 386 387 if (ReplacementOp) 388 { 389 ReplacementOp->Parent = Op->Parent; 390 ReplacementOp->Value.Arg = NULL; 391 ReplacementOp->Node = Op->Node; 392 Op->Parent->Value.Arg = ReplacementOp; 393 ReplacementOp->Next = Op->Next; 394 } 395 else 396 { 397 Op->Parent->Value.Arg = Op->Next; 398 } 399 } 400 401 /* Search the parent list */ 402 403 else while (Prev) 404 { 405 /* Traverse all siblings in the parent's argument list */ 406 407 Next = Prev->Next; 408 if (Next == Op) 409 { 410 if (ReplacementOp) 411 { 412 ReplacementOp->Parent = Op->Parent; 413 ReplacementOp->Value.Arg = NULL; 414 ReplacementOp->Node = Op->Node; 415 Prev->Next = ReplacementOp; 416 ReplacementOp->Next = Op->Next; 417 Next = NULL; 418 } 419 else 420 { 421 Prev->Next = Op->Next; 422 Next = NULL; 423 } 424 } 425 426 Prev = Next; 427 } 428 } 429 430 /* Now we can actually delete the subtree rooted at op */ 431 432 AcpiPsDeleteParseTree (Op); 433 434 return_VALUE (TRUE); 435 } 436 437 return_VALUE (FALSE); 438 439#else 440 return (FALSE); 441#endif 442} 443 444 445/******************************************************************************* 446 * 447 * FUNCTION: AcpiPsNextParseState 448 * 449 * PARAMETERS: ParserState - Current parser state object 450 * 451 * RETURN: Status 452 * 453 * DESCRIPTION: Update the parser state based upon the return exception from 454 * the parser callback. 455 * 456 ******************************************************************************/ 457 458ACPI_STATUS 459AcpiPsNextParseState ( 460 ACPI_WALK_STATE *WalkState, 461 ACPI_PARSE_OBJECT *Op, 462 ACPI_STATUS CallbackStatus) 463{ 464 ACPI_PARSE_STATE *ParserState = &WalkState->ParserState; 465 ACPI_STATUS Status = AE_CTRL_PENDING; 466 467 468 ACPI_FUNCTION_TRACE_PTR ("PsNextParseState", Op); 469 470 471 switch (CallbackStatus) 472 { 473 case AE_CTRL_TERMINATE: 474 475 /* 476 * A control method was terminated via a RETURN statement. 477 * The walk of this method is complete. 478 */ 479 ParserState->Aml = ParserState->AmlEnd; 480 Status = AE_CTRL_TERMINATE; 481 break; 482 483 484 case AE_CTRL_BREAK: 485 486 ParserState->Aml = WalkState->AmlLastWhile; 487 WalkState->ControlState->Common.Value = FALSE; 488 Status = AE_CTRL_BREAK; 489 break; 490 491 case AE_CTRL_CONTINUE: 492 493 494 ParserState->Aml = WalkState->AmlLastWhile; 495 Status = AE_CTRL_CONTINUE; 496 break; 497 498 case AE_CTRL_PENDING: 499 500 ParserState->Aml = WalkState->AmlLastWhile; 501 break; 502 503 504 case AE_CTRL_TRUE: 505 506 /* 507 * Predicate of an IF was true, and we are at the matching ELSE. 508 * Just close out this package 509 */ 510 ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState); 511 break; 512 513 514 case AE_CTRL_FALSE: 515 516 /* 517 * Either an IF/WHILE Predicate was false or we encountered a BREAK 518 * opcode. In both cases, we do not execute the rest of the 519 * package; We simply close out the parent (finishing the walk of 520 * this branch of the tree) and continue execution at the parent 521 * level. 522 */ 523 ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd; 524 525 /* In the case of a BREAK, just force a predicate (if any) to FALSE */ 526 527 WalkState->ControlState->Common.Value = FALSE; 528 Status = AE_CTRL_END; 529 break; 530 531 532 case AE_CTRL_TRANSFER: 533 534 /* 535 * A method call (invocation) -- transfer control 536 */ 537 Status = AE_CTRL_TRANSFER; 538 WalkState->PrevOp = Op; 539 WalkState->MethodCallOp = Op; 540 WalkState->MethodCallNode = (Op->Value.Arg)->Node; 541 542 /* Will return value (if any) be used by the caller? */ 543 544 WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState); 545 break; 546 547 548 default: 549 Status = CallbackStatus; 550 if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL) 551 { 552 Status = AE_OK; 553 } 554 break; 555 } 556 557 return_ACPI_STATUS (Status); 558} 559 560 561/******************************************************************************* 562 * 563 * FUNCTION: AcpiPsParseLoop 564 * 565 * PARAMETERS: ParserState - Current parser state object 566 * 567 * RETURN: Status 568 * 569 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return 570 * a tree of ops. 571 * 572 ******************************************************************************/ 573 574ACPI_STATUS 575AcpiPsParseLoop ( 576 ACPI_WALK_STATE *WalkState) 577{ 578 ACPI_STATUS Status = AE_OK; 579 ACPI_PARSE_OBJECT *Op = NULL; /* current op */ 580 ACPI_PARSE_OBJECT *Arg = NULL; 581 ACPI_PARSE_OBJECT PreOp; 582 ACPI_PARSE_STATE *ParserState; 583 UINT8 *AmlOpStart = NULL; 584 585 586 ACPI_FUNCTION_TRACE_PTR ("PsParseLoop", WalkState); 587 588 589 ParserState = &WalkState->ParserState; 590 WalkState->ArgTypes = 0; 591 592#ifndef PARSER_ONLY 593 if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART) 594 { 595 /* We are restarting a preempted control method */ 596 597 if (AcpiPsHasCompletedScope (ParserState)) 598 { 599 /* 600 * We must check if a predicate to an IF or WHILE statement 601 * was just completed 602 */ 603 if ((ParserState->Scope->ParseScope.Op) && 604 ((ParserState->Scope->ParseScope.Op->Opcode == AML_IF_OP) || 605 (ParserState->Scope->ParseScope.Op->Opcode == AML_WHILE_OP)) && 606 (WalkState->ControlState) && 607 (WalkState->ControlState->Common.State == 608 ACPI_CONTROL_PREDICATE_EXECUTING)) 609 { 610 /* 611 * A predicate was just completed, get the value of the 612 * predicate and branch based on that value 613 */ 614 WalkState->Op = NULL; 615 Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE)); 616 if (ACPI_FAILURE (Status) && 617 ((Status & AE_CODE_MASK) != AE_CODE_CONTROL)) 618 { 619 if (Status == AE_AML_NO_RETURN_VALUE) 620 { 621 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 622 "Invoked method did not return a value, %s\n", 623 AcpiFormatException (Status))); 624 625 } 626 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "GetPredicate Failed, %s\n", 627 AcpiFormatException (Status))); 628 return_ACPI_STATUS (Status); 629 } 630 631 Status = AcpiPsNextParseState (WalkState, Op, Status); 632 } 633 634 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 635 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); 636 } 637 else if (WalkState->PrevOp) 638 { 639 /* We were in the middle of an op */ 640 641 Op = WalkState->PrevOp; 642 WalkState->ArgTypes = WalkState->PrevArgTypes; 643 } 644 } 645#endif 646 647 /* 648 * Iterative parsing loop, while there is more aml to process: 649 */ 650 while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) 651 { 652 if (!Op) 653 { 654 /* Get the next opcode from the AML stream */ 655 656 AmlOpStart = ParserState->Aml; 657 WalkState->AmlOffset = ParserState->Aml - ParserState->AmlStart; 658 WalkState->Opcode = AcpiPsPeekOpcode (ParserState); 659 660 /* 661 * First cut to determine what we have found: 662 * 1) A valid AML opcode 663 * 2) A name string 664 * 3) An unknown/invalid opcode 665 */ 666 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 667 switch (WalkState->OpInfo->Class) 668 { 669 case AML_CLASS_ASCII: 670 case AML_CLASS_PREFIX: 671 /* 672 * Starts with a valid prefix or ASCII char, this is a name 673 * string. Convert the bare name string to a namepath. 674 */ 675 WalkState->Opcode = AML_INT_NAMEPATH_OP; 676 WalkState->ArgTypes = ARGP_NAMESTRING; 677 break; 678 679 case AML_CLASS_UNKNOWN: 680 681 /* The opcode is unrecognized. Just skip unknown opcodes */ 682 683 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 684 "Found unknown opcode %X at AML address %p offset %X, ignoring\n", 685 WalkState->Opcode, ParserState->Aml, WalkState->AmlOffset)); 686 687 ACPI_DUMP_BUFFER (ParserState->Aml, 128); 688 689 /* Assume one-byte bad opcode */ 690 691 ParserState->Aml++; 692 continue; 693 694 default: 695 696 /* Found opcode info, this is a normal opcode */ 697 698 ParserState->Aml += AcpiPsGetOpcodeSize (WalkState->Opcode); 699 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs; 700 break; 701 } 702 703 /* Create Op structure and append to parent's argument list */ 704 705 if (WalkState->OpInfo->Flags & AML_NAMED) 706 { 707 PreOp.Value.Arg = NULL; 708 PreOp.Opcode = WalkState->Opcode; 709 710 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME) 711 { 712 Arg = AcpiPsGetNextArg (ParserState, 713 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), 714 &WalkState->ArgCount); 715 AcpiPsAppendArg (&PreOp, Arg); 716 INCREMENT_ARG_LIST (WalkState->ArgTypes); 717 } 718 719 /* We know that this arg is a name, move to next arg */ 720 721 INCREMENT_ARG_LIST (WalkState->ArgTypes); 722 723 if (WalkState->DescendingCallback != NULL) 724 { 725 /* 726 * Find the object. This will either insert the object into 727 * the namespace or simply look it up 728 */ 729 WalkState->Op = NULL; 730 731 Status = WalkState->DescendingCallback (WalkState, &Op); 732 if (ACPI_FAILURE (Status)) 733 { 734 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "During name lookup/catalog, %s\n", 735 AcpiFormatException (Status))); 736 goto CloseThisOp; 737 } 738 739 if (Op == NULL) 740 { 741 continue; 742 } 743 744 Status = AcpiPsNextParseState (WalkState, Op, Status); 745 if (Status == AE_CTRL_PENDING) 746 { 747 Status = AE_OK; 748 goto CloseThisOp; 749 } 750 751 if (ACPI_FAILURE (Status)) 752 { 753 goto CloseThisOp; 754 } 755 } 756 757 AcpiPsAppendArg (Op, PreOp.Value.Arg); 758 AcpiGbl_Depth++; 759 760 if (Op->Opcode == AML_REGION_OP) 761 { 762 /* 763 * Defer final parsing of an OperationRegion body, 764 * because we don't have enough info in the first pass 765 * to parse it correctly (i.e., there may be method 766 * calls within the TermArg elements of the body. 767 * 768 * However, we must continue parsing because 769 * the opregion is not a standalone package -- 770 * we don't know where the end is at this point. 771 * 772 * (Length is unknown until parse of the body complete) 773 */ 774 ((ACPI_PARSE2_OBJECT * ) Op)->Data = AmlOpStart; 775 ((ACPI_PARSE2_OBJECT * ) Op)->Length = 0; 776 } 777 } 778 else 779 { 780 /* Not a named opcode, just allocate Op and append to parent */ 781 782 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); 783 Op = AcpiPsAllocOp (WalkState->Opcode); 784 if (!Op) 785 { 786 return_ACPI_STATUS (AE_NO_MEMORY); 787 } 788 789 if (WalkState->OpInfo->Flags & AML_CREATE) 790 { 791 /* 792 * Backup to beginning of CreateXXXfield declaration 793 * BodyLength is unknown until we parse the body 794 */ 795 ((ACPI_PARSE2_OBJECT * ) Op)->Data = AmlOpStart; 796 ((ACPI_PARSE2_OBJECT * ) Op)->Length = 0; 797 } 798 799 AcpiPsAppendArg (AcpiPsGetParentScope (ParserState), Op); 800 801 if ((WalkState->DescendingCallback != NULL)) 802 { 803 /* 804 * Find the object. This will either insert the object into 805 * the namespace or simply look it up 806 */ 807 WalkState->Op = Op; 808 809 Status = WalkState->DescendingCallback (WalkState, &Op); 810 Status = AcpiPsNextParseState (WalkState, Op, Status); 811 if (Status == AE_CTRL_PENDING) 812 { 813 Status = AE_OK; 814 goto CloseThisOp; 815 } 816 817 if (ACPI_FAILURE (Status)) 818 { 819 goto CloseThisOp; 820 } 821 } 822 } 823 824 Op->AmlOffset = WalkState->AmlOffset; 825 826 if (WalkState->OpInfo) 827 { 828 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 829 "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", 830 Op->Opcode, WalkState->OpInfo->Name, Op, ParserState->Aml, Op->AmlOffset)); 831 } 832 } 833 834 835 /* Start ArgCount at zero because we don't know if there are any args yet */ 836 837 WalkState->ArgCount = 0; 838 839 if (WalkState->ArgTypes) /* Are there any arguments that must be processed? */ 840 { 841 /* Get arguments */ 842 843 switch (Op->Opcode) 844 { 845 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ 846 case AML_WORD_OP: /* AML_WORDDATA_ARG */ 847 case AML_DWORD_OP: /* AML_DWORDATA_ARG */ 848 case AML_QWORD_OP: /* AML_QWORDATA_ARG */ 849 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ 850 851 /* Fill in constant or string argument directly */ 852 853 AcpiPsGetNextSimpleArg (ParserState, 854 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op); 855 break; 856 857 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ 858 859 AcpiPsGetNextNamepath (ParserState, Op, &WalkState->ArgCount, 1); 860 WalkState->ArgTypes = 0; 861 break; 862 863 864 default: 865 866 /* Op is not a constant or string, append each argument */ 867 868 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount) 869 { 870 WalkState->AmlOffset = ParserState->Aml - ParserState->AmlStart; 871 Arg = AcpiPsGetNextArg (ParserState, 872 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), 873 &WalkState->ArgCount); 874 if (Arg) 875 { 876 Arg->AmlOffset = WalkState->AmlOffset; 877 AcpiPsAppendArg (Op, Arg); 878 } 879 880 INCREMENT_ARG_LIST (WalkState->ArgTypes); 881 } 882 883 switch (Op->Opcode) 884 { 885 case AML_METHOD_OP: 886 887 /* For a method, save the length and address of the body */ 888 889 /* 890 * Skip parsing of control method or opregion body, 891 * because we don't have enough info in the first pass 892 * to parse them correctly. 893 */ 894 ((ACPI_PARSE2_OBJECT * ) Op)->Data = ParserState->Aml; 895 ((ACPI_PARSE2_OBJECT * ) Op)->Length = (UINT32) (ParserState->PkgEnd - 896 ParserState->Aml); 897 /* 898 * Skip body of method. For OpRegions, we must continue 899 * parsing because the opregion is not a standalone 900 * package (We don't know where the end is). 901 */ 902 ParserState->Aml = ParserState->PkgEnd; 903 WalkState->ArgCount = 0; 904 break; 905 906 case AML_BUFFER_OP: 907 case AML_PACKAGE_OP: 908 case AML_VAR_PACKAGE_OP: 909 910 if ((Op->Parent) && 911 (Op->Parent->Opcode == AML_NAME_OP) && 912 (WalkState->DescendingCallback != AcpiDsExecBeginOp)) 913 { 914 /* 915 * Skip parsing of 916 * because we don't have enough info in the first pass 917 * to parse them correctly. 918 */ 919 ((ACPI_PARSE2_OBJECT * ) Op)->Data = AmlOpStart; 920 ((ACPI_PARSE2_OBJECT * ) Op)->Length = (UINT32) (ParserState->PkgEnd - 921 AmlOpStart); 922 /* 923 * Skip body 924 */ 925 ParserState->Aml = ParserState->PkgEnd; 926 WalkState->ArgCount = 0; 927 } 928 break; 929 930 case AML_WHILE_OP: 931 932 if (WalkState->ControlState) 933 { 934 WalkState->ControlState->Control.PackageEnd = ParserState->PkgEnd; 935 } 936 break; 937 } 938 break; 939 } 940 } 941 942 /* Check for arguments that need to be processed */ 943 944 if (WalkState->ArgCount) 945 { 946 /* There are arguments (complex ones), push Op and prepare for argument */ 947 948 AcpiPsPushScope (ParserState, Op, WalkState->ArgTypes, WalkState->ArgCount); 949 Op = NULL; 950 continue; 951 } 952 953 /* All arguments have been processed -- Op is complete, prepare for next */ 954 955 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Opcode); 956 if (WalkState->OpInfo->Flags & AML_NAMED) 957 { 958 if (AcpiGbl_Depth) 959 { 960 AcpiGbl_Depth--; 961 } 962 963 if (Op->Opcode == AML_REGION_OP) 964 { 965 /* 966 * Skip parsing of control method or opregion body, 967 * because we don't have enough info in the first pass 968 * to parse them correctly. 969 * 970 * Completed parsing an OpRegion declaration, we now 971 * know the length. 972 */ 973 ((ACPI_PARSE2_OBJECT * ) Op)->Length = (UINT32) (ParserState->Aml - 974 ((ACPI_PARSE2_OBJECT * ) Op)->Data); 975 } 976 } 977 978 if (WalkState->OpInfo->Flags & AML_CREATE) 979 { 980 /* 981 * Backup to beginning of CreateXXXfield declaration (1 for 982 * Opcode) 983 * 984 * BodyLength is unknown until we parse the body 985 */ 986 ((ACPI_PARSE2_OBJECT * ) Op)->Length = (UINT32) (ParserState->Aml - 987 ((ACPI_PARSE2_OBJECT * ) Op)->Data); 988 } 989 990 /* This op complete, notify the dispatcher */ 991 992 if (WalkState->AscendingCallback != NULL) 993 { 994 WalkState->Op = Op; 995 WalkState->Opcode = Op->Opcode; 996 997 Status = WalkState->AscendingCallback (WalkState); 998 Status = AcpiPsNextParseState (WalkState, Op, Status); 999 if (Status == AE_CTRL_PENDING) 1000 { 1001 Status = AE_OK; 1002 goto CloseThisOp; 1003 } 1004 } 1005 1006 1007CloseThisOp: 1008 /* 1009 * Finished one argument of the containing scope 1010 */ 1011 ParserState->Scope->ParseScope.ArgCount--; 1012 1013 /* Close this Op (may result in parse subtree deletion) */ 1014 1015 if (AcpiPsCompleteThisOp (WalkState, Op)) 1016 { 1017 Op = NULL; 1018 } 1019 1020 switch (Status) 1021 { 1022 case AE_OK: 1023 break; 1024 1025 1026 case AE_CTRL_TRANSFER: 1027 1028 /* 1029 * We are about to transfer to a called method. 1030 */ 1031 WalkState->PrevOp = Op; 1032 WalkState->PrevArgTypes = WalkState->ArgTypes; 1033 return_ACPI_STATUS (Status); 1034 1035 1036 case AE_CTRL_END: 1037 1038 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1039 1040 WalkState->Op = Op; 1041 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Opcode); 1042 WalkState->Opcode = Op->Opcode; 1043 1044 Status = WalkState->AscendingCallback (WalkState); 1045 Status = AcpiPsNextParseState (WalkState, Op, Status); 1046 1047 AcpiPsCompleteThisOp (WalkState, Op); 1048 Op = NULL; 1049 Status = AE_OK; 1050 break; 1051 1052 1053 case AE_CTRL_BREAK: 1054 case AE_CTRL_CONTINUE: 1055 1056 /* Pop off scopes until we find the While */ 1057 1058 while (!Op || (Op->Opcode != AML_WHILE_OP)) 1059 { 1060 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1061 } 1062 1063 /* Close this iteration of the While loop */ 1064 1065 WalkState->Op = Op; 1066 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Opcode); 1067 WalkState->Opcode = Op->Opcode; 1068 1069 Status = WalkState->AscendingCallback (WalkState); 1070 Status = AcpiPsNextParseState (WalkState, Op, Status); 1071 1072 AcpiPsCompleteThisOp (WalkState, Op); 1073 Op = NULL; 1074 1075 Status = AE_OK; 1076 break; 1077 1078 1079 case AE_CTRL_TERMINATE: 1080 1081 Status = AE_OK; 1082 1083 /* Clean up */ 1084 do 1085 { 1086 if (Op) 1087 { 1088 AcpiPsCompleteThisOp (WalkState, Op); 1089 } 1090 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1091 1092 } while (Op); 1093 1094 return_ACPI_STATUS (Status); 1095 1096 1097 default: /* All other non-AE_OK status */ 1098 1099 do 1100 { 1101 if (Op) 1102 { 1103 AcpiPsCompleteThisOp (WalkState, Op); 1104 } 1105 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1106 1107 } while (Op); 1108 1109 1110 /* 1111 * TBD: Cleanup parse ops on error 1112 */ 1113#if 0 1114 if (Op == NULL) 1115 { 1116 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1117 } 1118#endif 1119 WalkState->PrevOp = Op; 1120 WalkState->PrevArgTypes = WalkState->ArgTypes; 1121 return_ACPI_STATUS (Status); 1122 } 1123 1124 /* This scope complete? */ 1125 1126 if (AcpiPsHasCompletedScope (ParserState)) 1127 { 1128 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1129 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); 1130 } 1131 else 1132 { 1133 Op = NULL; 1134 } 1135 1136 } /* while ParserState->Aml */ 1137 1138 1139 /* 1140 * Complete the last Op (if not completed), and clear the scope stack. 1141 * It is easily possible to end an AML "package" with an unbounded number 1142 * of open scopes (such as when several ASL blocks are closed with 1143 * sequential closing braces). We want to terminate each one cleanly. 1144 */ 1145 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op)); 1146 do 1147 { 1148 if (Op) 1149 { 1150 if (WalkState->AscendingCallback != NULL) 1151 { 1152 WalkState->Op = Op; 1153 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Opcode); 1154 WalkState->Opcode = Op->Opcode; 1155 1156 Status = WalkState->AscendingCallback (WalkState); 1157 Status = AcpiPsNextParseState (WalkState, Op, Status); 1158 if (Status == AE_CTRL_PENDING) 1159 { 1160 Status = AE_OK; 1161 goto CloseThisOp; 1162 } 1163 1164 if (Status == AE_CTRL_TERMINATE) 1165 { 1166 Status = AE_OK; 1167 1168 /* Clean up */ 1169 do 1170 { 1171 if (Op) 1172 { 1173 AcpiPsCompleteThisOp (WalkState, Op); 1174 } 1175 1176 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1177 1178 } while (Op); 1179 1180 return_ACPI_STATUS (Status); 1181 } 1182 1183 else if (ACPI_FAILURE (Status)) 1184 { 1185 AcpiPsCompleteThisOp (WalkState, Op); 1186 return_ACPI_STATUS (Status); 1187 } 1188 } 1189 1190 AcpiPsCompleteThisOp (WalkState, Op); 1191 } 1192 1193 AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); 1194 1195 } while (Op); 1196 1197 return_ACPI_STATUS (Status); 1198} 1199 1200 1201/******************************************************************************* 1202 * 1203 * FUNCTION: AcpiPsParseAml 1204 * 1205 * PARAMETERS: StartScope - The starting point of the parse. Becomes the 1206 * root of the parsed op tree. 1207 * Aml - Pointer to the raw AML code to parse 1208 * AmlSize - Length of the AML to parse 1209 * 1210 * 1211 * RETURN: Status 1212 * 1213 * DESCRIPTION: Parse raw AML and return a tree of ops 1214 * 1215 ******************************************************************************/ 1216 1217ACPI_STATUS 1218AcpiPsParseAml ( 1219 ACPI_WALK_STATE *WalkState) 1220{ 1221 ACPI_STATUS Status; 1222 ACPI_THREAD_STATE *Thread; 1223 ACPI_THREAD_STATE *PrevWalkList = AcpiGbl_CurrentWalkList; 1224 ACPI_WALK_STATE *PreviousWalkState; 1225 1226 1227 ACPI_FUNCTION_TRACE ("PsParseAml"); 1228 1229 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Entered with WalkState=%p Aml=%p size=%X\n", 1230 WalkState, WalkState->ParserState.Aml, WalkState->ParserState.AmlSize)); 1231 1232 1233 /* Create and initialize a new thread state */ 1234 1235 Thread = AcpiUtCreateThreadState (); 1236 if (!Thread) 1237 { 1238 return_ACPI_STATUS (AE_NO_MEMORY); 1239 } 1240 1241 WalkState->Thread = Thread; 1242 AcpiDsPushWalkState (WalkState, Thread); 1243 1244 /* 1245 * This global allows the AML debugger to get a handle to the currently 1246 * executing control method. 1247 */ 1248 AcpiGbl_CurrentWalkList = Thread; 1249 1250 /* 1251 * Execute the walk loop as long as there is a valid Walk State. This 1252 * handles nested control method invocations without recursion. 1253 */ 1254 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState)); 1255 1256 Status = AE_OK; 1257 while (WalkState) 1258 { 1259 if (ACPI_SUCCESS (Status)) 1260 { 1261 /* 1262 * The ParseLoop executes AML until the method terminates 1263 * or calls another method. 1264 */ 1265 Status = AcpiPsParseLoop (WalkState); 1266 } 1267 1268 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 1269 "Completed one call to walk loop, State=%p\n", WalkState)); 1270 1271 if (Status == AE_CTRL_TRANSFER) 1272 { 1273 /* 1274 * A method call was detected. 1275 * Transfer control to the called control method 1276 */ 1277 Status = AcpiDsCallControlMethod (Thread, WalkState, NULL); 1278 1279 /* 1280 * If the transfer to the new method method call worked, a new walk 1281 * state was created -- get it 1282 */ 1283 WalkState = AcpiDsGetCurrentWalkState (Thread); 1284 continue; 1285 } 1286 1287 else if (Status == AE_CTRL_TERMINATE) 1288 { 1289 Status = AE_OK; 1290 } 1291 1292 /* We are done with this walk, move on to the parent if any */ 1293 1294 WalkState = AcpiDsPopWalkState (Thread); 1295 1296 /* Reset the current scope to the beginning of scope stack */ 1297 1298 AcpiDsScopeStackClear (WalkState); 1299 1300 /* 1301 * If we just returned from the execution of a control method, 1302 * there's lots of cleanup to do 1303 */ 1304 if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) 1305 { 1306 AcpiDsTerminateControlMethod (WalkState); 1307 } 1308 1309 /* Delete this walk state and all linked control states */ 1310 1311 AcpiPsCleanupScope (&WalkState->ParserState); 1312 1313 PreviousWalkState = WalkState; 1314 1315 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "ReturnValue=%p, State=%p\n", 1316 WalkState->ReturnDesc, WalkState)); 1317 1318 /* Check if we have restarted a preempted walk */ 1319 1320 WalkState = AcpiDsGetCurrentWalkState (Thread); 1321 if (WalkState) 1322 { 1323 if (ACPI_SUCCESS (Status)) 1324 { 1325 /* 1326 * There is another walk state, restart it. 1327 * If the method return value is not used by the parent, 1328 * The object is deleted 1329 */ 1330 AcpiDsRestartControlMethod (WalkState, PreviousWalkState->ReturnDesc); 1331 WalkState->WalkType |= ACPI_WALK_METHOD_RESTART; 1332 } 1333 else 1334 { 1335 /* On error, delete any return object */ 1336 1337 AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); 1338 1339 ACPI_REPORT_ERROR (("Method execution failed, %s\n", AcpiFormatException (Status))); 1340 ACPI_DUMP_PATHNAME (WalkState->MethodNode, "Method pathname: ", 1341 ACPI_LV_ERROR, _COMPONENT); 1342 } 1343 } 1344 1345 /* 1346 * Just completed a 1st-level method, save the final internal return 1347 * value (if any) 1348 */ 1349 else if (PreviousWalkState->CallerReturnDesc) 1350 { 1351 *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ReturnDesc; /* NULL if no return value */ 1352 } 1353 1354 else if (PreviousWalkState->ReturnDesc) 1355 { 1356 /* Caller doesn't want it, must delete it */ 1357 1358 AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); 1359 } 1360 1361 AcpiDsDeleteWalkState (PreviousWalkState); 1362 } 1363 1364 /* Normal exit */ 1365 1366 AcpiExReleaseAllMutexes (Thread); 1367 AcpiUtDeleteGenericState ((ACPI_GENERIC_STATE *) Thread); 1368 AcpiGbl_CurrentWalkList = PrevWalkList; 1369 return_ACPI_STATUS (Status); 1370} 1371 1372 1373