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