psparse.c revision 69450
1/****************************************************************************** 2 * 3 * Module Name: psparse - Parser top level AML parse routines 4 * $Revision: 65 $ 5 * 6 *****************************************************************************/ 7 8/****************************************************************************** 9 * 10 * 1. Copyright Notice 11 * 12 * Some or all of this work - Copyright (c) 1999, Intel Corp. All rights 13 * 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 134#define _COMPONENT PARSER 135 MODULE_NAME ("psparse") 136 137 138UINT32 AcpiGbl_Depth = 0; 139extern UINT32 AcpiGbl_ScopeDepth; 140 141 142/******************************************************************************* 143 * 144 * FUNCTION: AcpiPsPeekOpcode 145 * 146 * PARAMETERS: None 147 * 148 * RETURN: Status 149 * 150 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) 151 * 152 ******************************************************************************/ 153 154static UINT32 155AcpiPsGetOpcodeSize ( 156 UINT32 Opcode) 157{ 158 159 /* Extended (2-byte) opcode if > 255 */ 160 161 if (Opcode > 0x00FF) 162 { 163 return (2); 164 } 165 166 /* Otherwise, just a single byte opcode */ 167 168 return (1); 169} 170 171 172/******************************************************************************* 173 * 174 * FUNCTION: AcpiPsPeekOpcode 175 * 176 * PARAMETERS: ParserState - A parser state object 177 * 178 * RETURN: Status 179 * 180 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) 181 * 182 ******************************************************************************/ 183 184UINT16 185AcpiPsPeekOpcode ( 186 ACPI_PARSE_STATE *ParserState) 187{ 188 UINT8 *Aml; 189 UINT16 Opcode; 190 191 192 Aml = ParserState->Aml; 193 Opcode = (UINT16) GET8 (Aml); 194 195 Aml++; 196 197 198 /* 199 * Original code special cased LNOTEQUAL, LLESSEQUAL, LGREATEREQUAL. 200 * These opcodes are no longer recognized. Instead, they are broken into 201 * two opcodes. 202 * 203 * 204 * if (Opcode == AML_EXTOP 205 * || (Opcode == AML_LNOT 206 * && (GET8 (AcpiAml) == AML_LEQUAL 207 * || GET8 (AcpiAml) == AML_LGREATER 208 * || GET8 (AcpiAml) == AML_LLESS))) 209 * 210 * extended Opcode, !=, <=, or >= 211 */ 212 213 if (Opcode == AML_EXTOP) 214 { 215 /* Extended opcode */ 216 217 Opcode = (UINT16) ((Opcode << 8) | GET8 (Aml)); 218 Aml++; 219 } 220 221 /* don't convert bare name to a namepath */ 222 223 return (Opcode); 224} 225 226 227/******************************************************************************* 228 * 229 * FUNCTION: AcpiPsCreateState 230 * 231 * PARAMETERS: AcpiAml - AcpiAml code pointer 232 * AcpiAmlSize - Length of AML code 233 * 234 * RETURN: A new parser state object 235 * 236 * DESCRIPTION: Create and initialize a new parser state object 237 * 238 ******************************************************************************/ 239 240ACPI_PARSE_STATE * 241AcpiPsCreateState ( 242 UINT8 *Aml, 243 UINT32 AmlSize) 244{ 245 ACPI_PARSE_STATE *ParserState; 246 247 248 FUNCTION_TRACE ("PsCreateState"); 249 250 251 ParserState = AcpiCmCallocate (sizeof (ACPI_PARSE_STATE)); 252 if (!ParserState) 253 { 254 return_VALUE (NULL); 255 } 256 257 ParserState->Aml = Aml; 258 ParserState->AmlEnd = Aml + AmlSize; 259 ParserState->PkgEnd = ParserState->AmlEnd; 260 ParserState->AmlStart = Aml; 261 262 263 return_PTR (ParserState); 264} 265 266 267/******************************************************************************* 268 * 269 * FUNCTION: AcpiPsFindObject 270 * 271 * PARAMETERS: Opcode - Current opcode 272 * ParserState - Current state 273 * WalkState - Current state 274 * *Op - Where found/new op is returned 275 * 276 * RETURN: Status 277 * 278 * DESCRIPTION: Find a named object. Two versions - one to search the parse 279 * tree (for parser-only applications such as acpidump), another 280 * to search the ACPI internal namespace (the parse tree may no 281 * longer exist) 282 * 283 ******************************************************************************/ 284 285#ifdef PARSER_ONLY 286 287ACPI_STATUS 288AcpiPsFindObject ( 289 UINT16 Opcode, 290 ACPI_PARSE_OBJECT *Op, 291 ACPI_WALK_STATE *WalkState, 292 ACPI_PARSE_OBJECT **OutOp) 293{ 294 NATIVE_CHAR *Path; 295 296 297 /* We are only interested in opcodes that have an associated name */ 298 299 if (!AcpiPsIsNamedOp (Opcode)) 300 { 301 *OutOp = Op; 302 return (AE_OK); 303 } 304 305 /* Find the name in the parse tree */ 306 307 Path = AcpiPsGetNextNamestring (WalkState->ParserState); 308 309 *OutOp = AcpiPsFind (AcpiPsGetParentScope (WalkState->ParserState), 310 Path, Opcode, 1); 311 312 if (!(*OutOp)) 313 { 314 return (AE_NOT_FOUND); 315 } 316 317 return (AE_OK); 318} 319 320#endif 321 322 323/******************************************************************************* 324 * 325 * FUNCTION: AcpiPsCompleteThisOp 326 * 327 * PARAMETERS: WalkState - Current State 328 * Op - Op to complete 329 * 330 * RETURN: TRUE if Op and subtree was deleted 331 * 332 * DESCRIPTION: Perform any cleanup at the completion of an Op. 333 * 334 ******************************************************************************/ 335 336static BOOLEAN 337AcpiPsCompleteThisOp ( 338 ACPI_WALK_STATE *WalkState, 339 ACPI_PARSE_OBJECT *Op) 340{ 341#ifndef PARSER_ONLY 342 ACPI_PARSE_OBJECT *Prev; 343 ACPI_PARSE_OBJECT *Next; 344 ACPI_OPCODE_INFO *OpInfo; 345 ACPI_OPCODE_INFO *ParentInfo; 346 UINT32 OpcodeClass; 347 ACPI_PARSE_OBJECT *ReplacementOp = NULL; 348 349 350 FUNCTION_TRACE_PTR ("PsCompleteThisOp", Op); 351 352 353 OpInfo = AcpiPsGetOpcodeInfo (Op->Opcode); 354 OpcodeClass = ACPI_GET_OP_CLASS (OpInfo); 355 356 357 /* Delete this op and the subtree below it if asked to */ 358 359 if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) && 360 (OpcodeClass != OPTYPE_CONSTANT) && 361 (OpcodeClass != OPTYPE_LITERAL) && 362 (OpcodeClass != OPTYPE_LOCAL_VARIABLE) && 363 (OpcodeClass != OPTYPE_METHOD_ARGUMENT) && 364 (OpcodeClass != OPTYPE_DATA_TERM) && 365 (Op->Opcode != AML_NAMEPATH_OP)) 366 { 367 /* Make sure that we only delete this subtree */ 368 369 if (Op->Parent) 370 { 371 /* 372 * Check if we need to replace the operator and its subtree 373 * with a return value op 374 */ 375 376 ParentInfo = AcpiPsGetOpcodeInfo (Op->Parent->Opcode); 377 378 switch (ACPI_GET_OP_CLASS (ParentInfo)) 379 { 380 case OPTYPE_CONTROL: /* IF, ELSE, WHILE only */ 381 case OPTYPE_NAMED_OBJECT: /* Scope, method, etc. */ 382 break; 383 384 default: 385 ReplacementOp = AcpiPsAllocOp (AML_RETURN_VALUE_OP); 386 if (!ReplacementOp) 387 { 388 return_VALUE (FALSE); 389 } 390 } 391 392 /* We must unlink this op from the parent tree */ 393 394 Prev = Op->Parent->Value.Arg; 395 if (Prev == Op) 396 { 397 /* This op is the first in the list */ 398 399 if (ReplacementOp) 400 { 401 ReplacementOp->Parent = Op->Parent; 402 ReplacementOp->Value.Arg = NULL; 403 Op->Parent->Value.Arg = ReplacementOp; 404 ReplacementOp->Next = Op->Next; 405 } 406 else 407 { 408 Op->Parent->Value.Arg = Op->Next; 409 } 410 } 411 412 /* Search the parent list */ 413 414 else while (Prev) 415 { 416 /* Traverse all siblings in the parent's argument list */ 417 418 Next = Prev->Next; 419 if (Next == Op) 420 { 421 if (ReplacementOp) 422 { 423 ReplacementOp->Parent = Op->Parent; 424 ReplacementOp->Value.Arg = NULL; 425 Prev->Next = ReplacementOp; 426 ReplacementOp->Next = Op->Next; 427 Next = NULL; 428 } 429 else 430 { 431 Prev->Next = Op->Next; 432 Next = NULL; 433 } 434 } 435 436 Prev = Next; 437 } 438 439 } 440 441 /* Now we can actually delete the subtree rooted at op */ 442 443 AcpiPsDeleteParseTree (Op); 444 445 return_VALUE (TRUE); 446 } 447 448 return_VALUE (FALSE); 449 450#else 451 return (FALSE); 452#endif 453} 454 455 456/******************************************************************************* 457 * 458 * FUNCTION: AcpiPsNextParseState 459 * 460 * PARAMETERS: ParserState - Current parser state object 461 * 462 * RETURN: 463 * 464 * DESCRIPTION: 465 * 466 ******************************************************************************/ 467 468static ACPI_STATUS 469AcpiPsNextParseState ( 470 ACPI_WALK_STATE *WalkState, 471 ACPI_PARSE_OBJECT *Op, 472 ACPI_STATUS CallbackStatus) 473{ 474 ACPI_PARSE_STATE *ParserState = WalkState->ParserState; 475 ACPI_STATUS Status = AE_CTRL_PENDING; 476 UINT8 *Start; 477 UINT32 PackageLength; 478 479 480 FUNCTION_TRACE_PTR ("PsNextParseState", Op); 481 482 483 switch (CallbackStatus) 484 { 485 case AE_CTRL_TERMINATE: 486 487 /* 488 * A control method was terminated via a RETURN statement. 489 * The walk of this method is complete. 490 */ 491 492 ParserState->Aml = ParserState->AmlEnd; 493 Status = AE_CTRL_TERMINATE; 494 break; 495 496 497 case AE_CTRL_PENDING: 498 499 /* 500 * Predicate of a WHILE was true and the loop just completed an 501 * execution. Go back to the start of the loop and reevaluate the 502 * predicate. 503 */ 504/* WalkState->ControlState->Common.State = 505 CONTROL_PREDICATE_EXECUTING;*/ 506 507 /* TBD: How to handle a break within a while. */ 508 /* This code attempts it */ 509 510 ParserState->Aml = WalkState->AmlLastWhile; 511 break; 512 513 514 case AE_CTRL_TRUE: 515 /* 516 * Predicate of an IF was true, and we are at the matching ELSE. 517 * Just close out this package 518 * 519 * Note: ParserState->Aml is modified by the package length procedure 520 * TBD: [Investigate] perhaps it shouldn't, too much trouble 521 */ 522 Start = ParserState->Aml; 523 PackageLength = AcpiPsGetNextPackageLength (ParserState); 524 ParserState->Aml = Start + PackageLength; 525 break; 526 527 528 case AE_CTRL_FALSE: 529 530 /* 531 * Either an IF/WHILE Predicate was false or we encountered a BREAK 532 * opcode. In both cases, we do not execute the rest of the 533 * package; We simply close out the parent (finishing the walk of 534 * this branch of the tree) and continue execution at the parent 535 * level. 536 */ 537 538 ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd; 539 540 /* In the case of a BREAK, just force a predicate (if any) to FALSE */ 541 542 WalkState->ControlState->Common.Value = FALSE; 543 Status = AE_CTRL_END; 544 break; 545 546 547 case AE_CTRL_TRANSFER: 548 549 /* 550 * A method call (invocation) -- transfer control 551 */ 552 Status = AE_CTRL_TRANSFER; 553 WalkState->PrevOp = Op; 554 WalkState->MethodCallOp = Op; 555 WalkState->MethodCallNode = (Op->Value.Arg)->Node; 556 557 /* Will return value (if any) be used by the caller? */ 558 559 WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState); 560 break; 561 562 563 default: 564 Status = CallbackStatus; 565 if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL) 566 { 567 Status = AE_OK; 568 } 569 break; 570 } 571 572 573 return_ACPI_STATUS (Status); 574} 575 576 577/******************************************************************************* 578 * 579 * FUNCTION: AcpiPsParseLoop 580 * 581 * PARAMETERS: ParserState - Current parser state object 582 * 583 * RETURN: Status 584 * 585 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return 586 * a tree of ops. 587 * 588 ******************************************************************************/ 589 590ACPI_STATUS 591AcpiPsParseLoop ( 592 ACPI_WALK_STATE *WalkState) 593{ 594 ACPI_STATUS Status = AE_OK; 595 ACPI_PARSE_OBJECT *Op = NULL; /* current op */ 596 ACPI_OPCODE_INFO *OpInfo; 597 ACPI_PARSE_OBJECT *Arg = NULL; 598 ACPI_PARSE2_OBJECT *DeferredOp; 599 UINT32 ArgCount; /* push for fixed or var args */ 600 UINT32 ArgTypes = 0; 601 ACPI_PTRDIFF AmlOffset; 602 UINT16 Opcode; 603 ACPI_PARSE_OBJECT PreOp; 604 ACPI_PARSE_STATE *ParserState; 605 606 607 FUNCTION_TRACE_PTR ("PsParseLoop", WalkState); 608 609 610 ParserState = WalkState->ParserState; 611 612#ifndef PARSER_ONLY 613 if (WalkState->WalkType & WALK_METHOD_RESTART) 614 { 615 /* We are restarting a preempted control method */ 616 617 if (AcpiPsHasCompletedScope (ParserState)) 618 { 619 /* 620 * We must check if a predicate to an IF or WHILE statement 621 * was just completed 622 */ 623 if ((ParserState->Scope->ParseScope.Op) && 624 ((ParserState->Scope->ParseScope.Op->Opcode == AML_IF_OP) || 625 (ParserState->Scope->ParseScope.Op->Opcode == AML_WHILE_OP)) && 626 (WalkState->ControlState) && 627 (WalkState->ControlState->Common.State == 628 CONTROL_PREDICATE_EXECUTING)) 629 { 630 631 /* 632 * A predicate was just completed, get the value of the 633 * predicate and branch based on that value 634 */ 635 636 Status = AcpiDsGetPredicateValue (WalkState, NULL, TRUE); 637 if (Status == AE_AML_NO_OPERAND) 638 { 639 DEBUG_PRINT (ACPI_ERROR, 640 ("PsParseLoop: Invoked method did not return a value, %s\n", 641 AcpiCmFormatException (Status))); 642 643 } 644 Status = AcpiPsNextParseState (WalkState, Op, Status); 645 } 646 647 AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); 648 DEBUG_PRINT (TRACE_PARSE, ("ParseLoop: Popped scope, Op=%p\n", Op)); 649 } 650 651 else if (WalkState->PrevOp) 652 { 653 /* We were in the middle of an op */ 654 655 Op = WalkState->PrevOp; 656 ArgTypes = WalkState->PrevArgTypes; 657 } 658 } 659#endif 660 661 /* 662 * Iterative parsing loop, while there is more aml to process: 663 */ 664 while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) 665 { 666 if (!Op) 667 { 668 /* Get the next opcode from the AML stream */ 669 670 AmlOffset = ParserState->Aml - ParserState->AmlStart; 671 Opcode = AcpiPsPeekOpcode (ParserState); 672 673 /* 674 * First cut to determine what we have found: 675 * 1) A valid AML opcode 676 * 2) A name string 677 * 3) An unknown/invalid opcode 678 */ 679 680 OpInfo = AcpiPsGetOpcodeInfo (Opcode); 681 switch (ACPI_GET_OP_TYPE (OpInfo)) 682 { 683 case ACPI_OP_TYPE_OPCODE: 684 685 /* Found opcode info, this is a normal opcode */ 686 687 ParserState->Aml += AcpiPsGetOpcodeSize (Opcode); 688 ArgTypes = OpInfo->ParseArgs; 689 break; 690 691 case ACPI_OP_TYPE_ASCII: 692 case ACPI_OP_TYPE_PREFIX: 693 /* 694 * Starts with a valid prefix or ASCII char, this is a name 695 * string. Convert the bare name string to a namepath. 696 */ 697 698 Opcode = AML_NAMEPATH_OP; 699 ArgTypes = ARGP_NAMESTRING; 700 break; 701 702 case ACPI_OP_TYPE_UNKNOWN: 703 704 /* The opcode is unrecognized. Just skip unknown opcodes */ 705 706 DEBUG_PRINT (ACPI_ERROR, 707 ("ParseLoop: Found unknown opcode 0x%lX at AML offset 0x%X, ignoring\n", 708 Opcode, AmlOffset)); 709 710 DUMP_BUFFER (ParserState->Aml, 128); 711 712 /* Assume one-byte bad opcode */ 713 714 ParserState->Aml++; 715 continue; 716 } 717 718 719 /* Create Op structure and append to parent's argument list */ 720 721 if (AcpiPsIsNamedOp (Opcode)) 722 { 723 PreOp.Value.Arg = NULL; 724 PreOp.Opcode = Opcode; 725 726 while (GET_CURRENT_ARG_TYPE (ArgTypes) != ARGP_NAME) 727 { 728 Arg = AcpiPsGetNextArg (ParserState, 729 GET_CURRENT_ARG_TYPE (ArgTypes), 730 &ArgCount); 731 AcpiPsAppendArg (&PreOp, Arg); 732 INCREMENT_ARG_LIST (ArgTypes); 733 } 734 735 736 /* We know that this arg is a name, move to next arg */ 737 738 INCREMENT_ARG_LIST (ArgTypes); 739 740 if (WalkState->DescendingCallback != NULL) 741 { 742 /* 743 * Find the object. This will either insert the object into 744 * the namespace or simply look it up 745 */ 746 Status = WalkState->DescendingCallback (Opcode, NULL, WalkState, &Op); 747 if (Op == NULL) 748 { 749 continue; 750 } 751 Status = AcpiPsNextParseState (WalkState, Op, Status); 752 if (Status == AE_CTRL_PENDING) 753 { 754 Status = AE_OK; 755 goto CloseThisOp; 756 } 757 758 if (ACPI_FAILURE (Status)) 759 { 760 goto CloseThisOp; 761 } 762 } 763 764 AcpiPsAppendArg (Op, PreOp.Value.Arg); 765 AcpiGbl_Depth++; 766 767 768 if (Op->Opcode == AML_REGION_OP) 769 { 770 DeferredOp = AcpiPsToExtendedOp (Op); 771 if (DeferredOp) 772 { 773 /* 774 * Skip parsing of control method or opregion body, 775 * because we don't have enough info in the first pass 776 * to parse them correctly. 777 * 778 * Backup to beginning of OpRegion declaration (2 for 779 * Opcode, 4 for name) 780 * 781 * BodyLength is unknown until we parse the body 782 */ 783 784 DeferredOp->Data = ParserState->Aml - 6; 785 DeferredOp->Length = 0; 786 } 787 } 788 } 789 790 791 else 792 { 793 /* Not a named opcode, just allocate Op and append to parent */ 794 795 Op = AcpiPsAllocOp (Opcode); 796 if (!Op) 797 { 798 return_ACPI_STATUS (AE_NO_MEMORY); 799 } 800 801 802 if ((Op->Opcode == AML_CREATE_FIELD_OP) || 803 (Op->Opcode == AML_BIT_FIELD_OP) || 804 (Op->Opcode == AML_BYTE_FIELD_OP) || 805 (Op->Opcode == AML_WORD_FIELD_OP) || 806 (Op->Opcode == AML_DWORD_FIELD_OP)) 807 { 808 /* 809 * Backup to beginning of CreateXXXfield declaration (1 for 810 * Opcode) 811 * 812 * BodyLength is unknown until we parse the body 813 */ 814 DeferredOp = (ACPI_PARSE2_OBJECT *) Op; 815 816 DeferredOp->Data = ParserState->Aml -1; 817 DeferredOp->Length = 0; 818 } 819 820 AcpiPsAppendArg (AcpiPsGetParentScope (ParserState), Op); 821 822 if ((WalkState->DescendingCallback != NULL)) 823 { 824 /* 825 * Find the object. This will either insert the object into 826 * the namespace or simply look it up 827 */ 828 Status = WalkState->DescendingCallback (Opcode, Op, WalkState, &Op); 829 Status = AcpiPsNextParseState (WalkState, Op, Status); 830 if (Status == AE_CTRL_PENDING) 831 { 832 Status = AE_OK; 833 goto CloseThisOp; 834 } 835 836 if (ACPI_FAILURE (Status)) 837 { 838 goto CloseThisOp; 839 } 840 } 841 } 842 843 Op->AmlOffset = AmlOffset; 844 845 if (OpInfo) 846 { 847 DEBUG_PRINT (TRACE_PARSE, 848 ("ParseLoop: Op=%p Opcode=%4.4lX Aml %p Oft=%5.5lX\n", 849 Op, Op->Opcode, ParserState->Aml, Op->AmlOffset)); 850 } 851 } 852 853 854 /* Start ArgCount at zero because we don't know if there are any args yet */ 855 856 ArgCount = 0; 857 858 859 if (ArgTypes) /* Are there any arguments that must be processed? */ 860 { 861 /* get arguments */ 862 863 switch (Op->Opcode) 864 { 865 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ 866 case AML_WORD_OP: /* AML_WORDDATA_ARG */ 867 case AML_DWORD_OP: /* AML_DWORDATA_ARG */ 868 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ 869 870 /* fill in constant or string argument directly */ 871 872 AcpiPsGetNextSimpleArg (ParserState, 873 GET_CURRENT_ARG_TYPE (ArgTypes), Op); 874 break; 875 876 case AML_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ 877 878 AcpiPsGetNextNamepath (ParserState, Op, &ArgCount, 1); 879 ArgTypes = 0; 880 break; 881 882 883 default: 884 885 /* Op is not a constant or string, append each argument */ 886 887 while (GET_CURRENT_ARG_TYPE (ArgTypes) && !ArgCount) 888 { 889 AmlOffset = ParserState->Aml - ParserState->AmlStart; 890 Arg = AcpiPsGetNextArg (ParserState, 891 GET_CURRENT_ARG_TYPE (ArgTypes), 892 &ArgCount); 893 if (Arg) 894 { 895 Arg->AmlOffset = AmlOffset; 896 AcpiPsAppendArg (Op, Arg); 897 } 898 899 INCREMENT_ARG_LIST (ArgTypes); 900 } 901 902 903 /* For a method, save the length and address of the body */ 904 905 if (Op->Opcode == AML_METHOD_OP) 906 { 907 DeferredOp = AcpiPsToExtendedOp (Op); 908 if (DeferredOp) 909 { 910 /* 911 * Skip parsing of control method or opregion body, 912 * because we don't have enough info in the first pass 913 * to parse them correctly. 914 */ 915 916 DeferredOp->Data = ParserState->Aml; 917 DeferredOp->Length = ParserState->PkgEnd - 918 ParserState->Aml; 919 920 /* 921 * Skip body of method. For OpRegions, we must continue 922 * parsing because the opregion is not a standalone 923 * package (We don't know where the end is). 924 */ 925 ParserState->Aml = ParserState->PkgEnd; 926 ArgCount = 0; 927 } 928 } 929 930 break; 931 } 932 } 933 934 935 /* 936 * Zero ArgCount means that all arguments for this op have been processed 937 */ 938 if (!ArgCount) 939 { 940 /* completed Op, prepare for next */ 941 942 if (AcpiPsIsNamedOp (Op->Opcode)) 943 { 944 if (AcpiGbl_Depth) 945 { 946 AcpiGbl_Depth--; 947 } 948 949 if (Op->Opcode == AML_REGION_OP) 950 { 951 DeferredOp = AcpiPsToExtendedOp (Op); 952 if (DeferredOp) 953 { 954 /* 955 * Skip parsing of control method or opregion body, 956 * because we don't have enough info in the first pass 957 * to parse them correctly. 958 * 959 * Completed parsing an OpRegion declaration, we now 960 * know the length. 961 */ 962 963 DeferredOp->Length = ParserState->Aml - 964 DeferredOp->Data; 965 } 966 } 967 } 968 969 if ((Op->Opcode == AML_CREATE_FIELD_OP) || 970 (Op->Opcode == AML_BIT_FIELD_OP) || 971 (Op->Opcode == AML_BYTE_FIELD_OP) || 972 (Op->Opcode == AML_WORD_FIELD_OP) || 973 (Op->Opcode == AML_DWORD_FIELD_OP)) 974 { 975 /* 976 * Backup to beginning of CreateXXXfield declaration (1 for 977 * Opcode) 978 * 979 * BodyLength is unknown until we parse the body 980 * -4 for the name (last) -- TBD: namestring: may be longer 981 * than 4? 982 */ 983 DeferredOp = (ACPI_PARSE2_OBJECT *) Op; 984 985 DeferredOp->Length = ParserState->Aml - DeferredOp->Data; 986 } 987 988 /* This op complete, notify the dispatcher */ 989 990 if (WalkState->AscendingCallback != NULL) 991 { 992 Status = WalkState->AscendingCallback (WalkState, Op); 993 Status = AcpiPsNextParseState (WalkState, Op, Status); 994 if (Status == AE_CTRL_PENDING) 995 { 996 Status = AE_OK; 997 goto CloseThisOp; 998 } 999 } 1000 1001 1002CloseThisOp: 1003 1004 /* 1005 * Finished one argument of the containing scope 1006 */ 1007 ParserState->Scope->ParseScope.ArgCount--; 1008 1009 /* Close this Op (may result in parse subtree deletion) */ 1010 1011 if (AcpiPsCompleteThisOp (WalkState, Op)) 1012 { 1013 Op = NULL; 1014 } 1015 1016 1017 if (Status == AE_CTRL_TRANSFER) 1018 { 1019 /* 1020 * We are about to transfer to a called method. 1021 */ 1022 WalkState->PrevOp = Op; 1023 WalkState->PrevArgTypes = ArgTypes; 1024 return_ACPI_STATUS (Status); 1025 } 1026 1027 else if (Status == AE_CTRL_END) 1028 { 1029 AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); 1030 1031 Status = WalkState->AscendingCallback (WalkState, Op); 1032 Status = AcpiPsNextParseState (WalkState, Op, Status); 1033 AcpiPsCompleteThisOp (WalkState, Op); 1034 Op = NULL; 1035 Status = AE_OK; 1036 } 1037 1038 else if (Status == AE_CTRL_TERMINATE) 1039 { 1040 Status = AE_OK; 1041 1042 /* Clean up */ 1043 do 1044 { 1045 if (Op) 1046 { 1047 AcpiPsCompleteThisOp (WalkState, Op); 1048 } 1049 1050 AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); 1051 } while (Op); 1052 1053 return_ACPI_STATUS (Status); 1054 } 1055 1056 else if (ACPI_FAILURE (Status)) 1057 { 1058 if (Op == NULL) 1059 { 1060 AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); 1061 } 1062 WalkState->PrevOp = Op; 1063 WalkState->PrevArgTypes = ArgTypes; 1064 1065 /* 1066 * TEMP: 1067 */ 1068 1069 return_ACPI_STATUS (Status); 1070 } 1071 1072 1073 /* This scope complete? */ 1074 1075 if (AcpiPsHasCompletedScope (ParserState)) 1076 { 1077 AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); 1078 DEBUG_PRINT (TRACE_PARSE, ("ParseLoop: Popped scope, Op=%p\n", Op)); 1079 } 1080 1081 else 1082 { 1083 Op = NULL; 1084 } 1085 1086 } 1087 1088 1089 /* ArgCount is non-zero */ 1090 1091 else 1092 { 1093 /* complex argument, push Op and prepare for argument */ 1094 1095 AcpiPsPushScope (ParserState, Op, ArgTypes, ArgCount); 1096 Op = NULL; 1097 } 1098 1099 } /* while ParserState->Aml */ 1100 1101 1102 /* 1103 * Complete the last Op (if not completed), and clear the scope stack. 1104 * It is easily possible to end an AML "package" with an unbounded number 1105 * of open scopes (such as when several AML blocks are closed with 1106 * sequential closing braces). We want to terminate each one cleanly. 1107 */ 1108 1109 DEBUG_PRINT (TRACE_PARSE, ("PsParseLoop: Package complete at Op %p\n", Op)); 1110 do 1111 { 1112 if (Op) 1113 { 1114 if (WalkState->AscendingCallback != NULL) 1115 { 1116 Status = WalkState->AscendingCallback (WalkState, Op); 1117 Status = AcpiPsNextParseState (WalkState, Op, Status); 1118 if (Status == AE_CTRL_PENDING) 1119 { 1120 Status = AE_OK; 1121 goto CloseThisOp; 1122 } 1123 1124 if (Status == AE_CTRL_TERMINATE) 1125 { 1126 Status = AE_OK; 1127 1128 /* Clean up */ 1129 do 1130 { 1131 if (Op) 1132 { 1133 AcpiPsCompleteThisOp (WalkState, Op); 1134 } 1135 1136 AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); 1137 1138 } while (Op); 1139 1140 return_ACPI_STATUS (Status); 1141 } 1142 1143 else if (ACPI_FAILURE (Status)) 1144 { 1145 AcpiPsCompleteThisOp (WalkState, Op); 1146 return_ACPI_STATUS (Status); 1147 } 1148 } 1149 1150 AcpiPsCompleteThisOp (WalkState, Op); 1151 } 1152 1153 AcpiPsPopScope (ParserState, &Op, &ArgTypes, &ArgCount); 1154 1155 } while (Op); 1156 1157 return_ACPI_STATUS (Status); 1158} 1159 1160 1161/******************************************************************************* 1162 * 1163 * FUNCTION: AcpiPsParseAml 1164 * 1165 * PARAMETERS: StartScope - The starting point of the parse. Becomes the 1166 * root of the parsed op tree. 1167 * Aml - Pointer to the raw AML code to parse 1168 * AmlSize - Length of the AML to parse 1169 * 1170 * RETURN: Status 1171 * 1172 * DESCRIPTION: Parse raw AML and return a tree of ops 1173 * 1174 ******************************************************************************/ 1175 1176ACPI_STATUS 1177AcpiPsParseAml ( 1178 ACPI_PARSE_OBJECT *StartScope, 1179 UINT8 *Aml, 1180 UINT32 AmlSize, 1181 UINT32 ParseFlags, 1182 ACPI_NAMESPACE_NODE *MethodNode, 1183 ACPI_OPERAND_OBJECT **Params, 1184 ACPI_OPERAND_OBJECT **CallerReturnDesc, 1185 ACPI_PARSE_DOWNWARDS DescendingCallback, 1186 ACPI_PARSE_UPWARDS AscendingCallback) 1187{ 1188 ACPI_STATUS Status; 1189 ACPI_PARSE_STATE *ParserState; 1190 ACPI_WALK_STATE *WalkState; 1191 ACPI_WALK_LIST WalkList; 1192 ACPI_NAMESPACE_NODE *Node = NULL; 1193 ACPI_WALK_LIST *PrevWalkList = AcpiGbl_CurrentWalkList; 1194 ACPI_OPERAND_OBJECT *ReturnDesc; 1195 ACPI_OPERAND_OBJECT *MthDesc = NULL; 1196 ACPI_NAMESPACE_NODE *StartNode; 1197 1198 1199 FUNCTION_TRACE ("PsParseAml"); 1200 1201 DEBUG_PRINT (TRACE_PARSE, 1202 ("PsParseAml: Entered with Scope=%p Aml=%p size=%lX\n", 1203 StartScope, Aml, AmlSize)); 1204 1205 1206 /* Create and initialize a new parser state */ 1207 1208 ParserState = AcpiPsCreateState (Aml, AmlSize); 1209 if (!ParserState) 1210 { 1211 return_ACPI_STATUS (AE_NO_MEMORY); 1212 } 1213 1214 AcpiPsInitScope (ParserState, StartScope); 1215 1216 if (MethodNode) 1217 { 1218 MthDesc = AcpiNsGetAttachedObject (MethodNode); 1219 } 1220 1221 /* Create and initialize a new walk list */ 1222 1223 WalkList.WalkState = NULL; 1224 1225 WalkState = AcpiDsCreateWalkState (TABLE_ID_DSDT, ParserState->StartOp, MthDesc, &WalkList); 1226 if (!WalkState) 1227 { 1228 Status = AE_NO_MEMORY; 1229 goto Cleanup; 1230 } 1231 1232 WalkState->MethodNode = MethodNode; 1233 WalkState->ParserState = ParserState; 1234 WalkState->ParseFlags = ParseFlags; 1235 WalkState->DescendingCallback = DescendingCallback; 1236 WalkState->AscendingCallback = AscendingCallback; 1237 1238 /* TBD: [Restructure] TEMP until we pass WalkState to the interpreter 1239 */ 1240 AcpiGbl_CurrentWalkList = &WalkList; 1241 1242 1243 if (MethodNode) 1244 { 1245 StartNode = MethodNode; 1246 ParserState->StartNode = MethodNode; 1247 WalkState->WalkType = WALK_METHOD; 1248 1249 if (StartNode) 1250 { 1251 /* Push start scope on scope stack and make it current */ 1252 1253 Status = AcpiDsScopeStackPush (StartNode, ACPI_TYPE_METHOD, WalkState); 1254 if (ACPI_FAILURE (Status)) 1255 { 1256 return_ACPI_STATUS (Status); 1257 } 1258 1259 } 1260 /* Init arguments if this is a control method */ 1261 /* TBD: [Restructure] add walkstate as a param */ 1262 1263 AcpiDsMethodDataInitArgs (Params, MTH_NUM_ARGS, WalkState); 1264 } 1265 1266 else 1267 { 1268 /* Setup the current scope */ 1269 1270 Node = ParserState->StartOp->Node; 1271 if (Node) 1272 { 1273 /* Push start scope on scope stack and make it current */ 1274 1275 Status = AcpiDsScopeStackPush (Node, Node->Type, 1276 WalkState); 1277 if (ACPI_FAILURE (Status)) 1278 { 1279 goto Cleanup; 1280 } 1281 1282 } 1283 } 1284 1285 1286 Status = AE_OK; 1287 1288 /* 1289 * Execute the walk loop as long as there is a valid Walk State. This 1290 * handles nested control method invocations without recursion. 1291 */ 1292 1293 DEBUG_PRINT (TRACE_PARSE, ("PsParseAml: State=%p\n", 1294 WalkState)); 1295 1296 while (WalkState) 1297 { 1298 if (ACPI_SUCCESS (Status)) 1299 { 1300 Status = AcpiPsParseLoop (WalkState); 1301 } 1302 1303 DEBUG_PRINT (TRACE_PARSE, 1304 ("PsParseAml: Completed one call to walk loop, State=%p\n", 1305 WalkState)); 1306 1307 if (Status == AE_CTRL_TRANSFER) 1308 { 1309 /* 1310 * A method call was detected. 1311 * Transfer control to the called control method 1312 */ 1313 1314 Status = AcpiDsCallControlMethod (&WalkList, WalkState, NULL); 1315 1316 /* 1317 * If the transfer to the new method method call worked, a new walk 1318 * state was created -- get it 1319 */ 1320 1321 WalkState = AcpiDsGetCurrentWalkState (&WalkList); 1322 continue; 1323 } 1324 1325 else if (Status == AE_CTRL_TERMINATE) 1326 { 1327 Status = AE_OK; 1328 } 1329 1330 /* We are done with this walk, move on to the parent if any */ 1331 1332 1333 WalkState = AcpiDsPopWalkState (&WalkList); 1334 1335 /* Extract return value before we delete WalkState */ 1336 1337 ReturnDesc = WalkState->ReturnDesc; 1338 1339 DEBUG_PRINT (TRACE_PARSE, 1340 ("PsParseAml: ReturnValue=%p, State=%p\n", 1341 WalkState->ReturnDesc, WalkState)); 1342 1343 /* Reset the current scope to the beginning of scope stack */ 1344 1345 AcpiDsScopeStackClear (WalkState); 1346 1347 /* 1348 * If we just returned from the execution of a control method, 1349 * there's lots of cleanup to do 1350 */ 1351 1352 if ((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) 1353 { 1354 AcpiDsTerminateControlMethod (WalkState); 1355 } 1356 1357 /* Delete this walk state and all linked control states */ 1358 1359 AcpiPsCleanupScope (WalkState->ParserState); 1360 AcpiCmFree (WalkState->ParserState); 1361 AcpiDsDeleteWalkState (WalkState); 1362 1363 /* Check if we have restarted a preempted walk */ 1364 1365 WalkState = AcpiDsGetCurrentWalkState (&WalkList); 1366 if (WalkState && 1367 ACPI_SUCCESS (Status)) 1368 { 1369 /* There is another walk state, restart it */ 1370 1371 /* 1372 * If the method returned value is not used by the parent, 1373 * The object is deleted 1374 */ 1375 1376 AcpiDsRestartControlMethod (WalkState, ReturnDesc); 1377 WalkState->WalkType |= WALK_METHOD_RESTART; 1378 } 1379 1380 /* 1381 * Just completed a 1st-level method, save the final internal return 1382 * value (if any) 1383 */ 1384 1385 else if (CallerReturnDesc) 1386 { 1387 *CallerReturnDesc = ReturnDesc; /* NULL if no return value */ 1388 } 1389 1390 else if (ReturnDesc) 1391 { 1392 /* Caller doesn't want it, must delete it */ 1393 1394 AcpiCmRemoveReference (ReturnDesc); 1395 } 1396 } 1397 1398 1399 /* Normal exit */ 1400 1401 AcpiGbl_CurrentWalkList = PrevWalkList; 1402 return_ACPI_STATUS (Status); 1403 1404 1405Cleanup: 1406 1407 /* Cleanup */ 1408 1409 AcpiDsDeleteWalkState (WalkState); 1410 AcpiPsCleanupScope (ParserState); 1411 AcpiCmFree (ParserState); 1412 1413 AcpiGbl_CurrentWalkList = PrevWalkList; 1414 1415 return_ACPI_STATUS (Status); 1416} 1417 1418 1419