1 /******************************************************************************
3 * Module Name: psloop - Main AML parse loop
6 *****************************************************************************/
8 /******************************************************************************
12 * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
13 * All rights reserved.
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
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
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;
38 * The above copyright and patent license is granted only if the following
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.
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
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
73 * 3.4. Intel retains all right, title, and interest in and to the Original
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.
81 * 4. Disclaimer and Export Compliance
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
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
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.
115 *****************************************************************************/
119 * Parse the AML and build an operation tree as most interpreters, (such as
120 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
121 * to tightly constrain stack and dynamic memory usage. Parsing is kept
122 * flexible and the code fairly compact by parsing based on a list of AML
123 * opcode templates in AmlOpInfo[].
126 #include <contrib/dev/acpica/acpi.h>
127 #include <contrib/dev/acpica/acparser.h>
128 #include <contrib/dev/acpica/acdispat.h>
129 #include <contrib/dev/acpica/amlcode.h>
131 #define _COMPONENT ACPI_PARSER
132 ACPI_MODULE_NAME ("psloop")
134 static UINT32 AcpiGbl_Depth = 0;
137 /* Local prototypes */
141 ACPI_WALK_STATE *WalkState);
145 ACPI_WALK_STATE *WalkState,
147 ACPI_PARSE_OBJECT *UnnamedOp,
148 ACPI_PARSE_OBJECT **Op);
152 ACPI_WALK_STATE *WalkState,
154 ACPI_PARSE_OBJECT **NewOp);
158 ACPI_WALK_STATE *WalkState,
160 ACPI_PARSE_OBJECT *Op);
164 ACPI_WALK_STATE *WalkState,
165 ACPI_PARSE_OBJECT **Op,
169 AcpiPsCompleteFinalOp (
170 ACPI_WALK_STATE *WalkState,
171 ACPI_PARSE_OBJECT *Op,
175 /*******************************************************************************
177 * FUNCTION: AcpiPsGetAmlOpcode
179 * PARAMETERS: WalkState - Current state
183 * DESCRIPTION: Extract the next AML opcode from the input stream.
185 ******************************************************************************/
189 ACPI_WALK_STATE *WalkState)
192 ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
195 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
196 WalkState->ParserState.AmlStart);
197 WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
200 * First cut to determine what we have found:
201 * 1) A valid AML opcode
203 * 3) An unknown/invalid opcode
205 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
207 switch (WalkState->OpInfo->Class)
209 case AML_CLASS_ASCII:
210 case AML_CLASS_PREFIX:
212 * Starts with a valid prefix or ASCII char, this is a name
213 * string. Convert the bare name string to a namepath.
215 WalkState->Opcode = AML_INT_NAMEPATH_OP;
216 WalkState->ArgTypes = ARGP_NAMESTRING;
219 case AML_CLASS_UNKNOWN:
221 /* The opcode is unrecognized. Just skip unknown opcodes */
223 ACPI_ERROR ((AE_INFO,
224 "Found unknown opcode %X at AML address %p offset %X, ignoring",
225 WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset));
227 ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128);
229 /* Assume one-byte bad opcode */
231 WalkState->ParserState.Aml++;
232 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
236 /* Found opcode info, this is a normal opcode */
238 WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
239 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
243 return_ACPI_STATUS (AE_OK);
247 /*******************************************************************************
249 * FUNCTION: AcpiPsBuildNamedOp
251 * PARAMETERS: WalkState - Current state
252 * AmlOpStart - Begin of named Op in AML
253 * UnnamedOp - Early Op (not a named Op)
258 * DESCRIPTION: Parse a named Op
260 ******************************************************************************/
264 ACPI_WALK_STATE *WalkState,
266 ACPI_PARSE_OBJECT *UnnamedOp,
267 ACPI_PARSE_OBJECT **Op)
269 ACPI_STATUS Status = AE_OK;
270 ACPI_PARSE_OBJECT *Arg = NULL;
273 ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
276 UnnamedOp->Common.Value.Arg = NULL;
277 UnnamedOp->Common.ArgListLength = 0;
278 UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
281 * Get and append arguments until we find the node that contains
282 * the name (the type ARGP_NAME).
284 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
285 (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
287 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
288 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
289 if (ACPI_FAILURE (Status))
291 return_ACPI_STATUS (Status);
294 AcpiPsAppendArg (UnnamedOp, Arg);
295 INCREMENT_ARG_LIST (WalkState->ArgTypes);
299 * Make sure that we found a NAME and didn't run out of arguments
301 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
303 return_ACPI_STATUS (AE_AML_NO_OPERAND);
306 /* We know that this arg is a name, move to next arg */
308 INCREMENT_ARG_LIST (WalkState->ArgTypes);
311 * Find the object. This will either insert the object into
312 * the namespace or simply look it up
314 WalkState->Op = NULL;
316 Status = WalkState->DescendingCallback (WalkState, Op);
317 if (ACPI_FAILURE (Status))
319 ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
320 return_ACPI_STATUS (Status);
325 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
328 Status = AcpiPsNextParseState (WalkState, *Op, Status);
329 if (ACPI_FAILURE (Status))
331 if (Status == AE_CTRL_PENDING)
333 return_ACPI_STATUS (AE_CTRL_PARSE_PENDING);
335 return_ACPI_STATUS (Status);
338 AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
341 if ((*Op)->Common.AmlOpcode == AML_REGION_OP)
344 * Defer final parsing of an OperationRegion body, because we don't
345 * have enough info in the first pass to parse it correctly (i.e.,
346 * there may be method calls within the TermArg elements of the body.)
348 * However, we must continue parsing because the opregion is not a
349 * standalone package -- we don't know where the end is at this point.
351 * (Length is unknown until parse of the body complete)
353 (*Op)->Named.Data = AmlOpStart;
354 (*Op)->Named.Length = 0;
357 return_ACPI_STATUS (AE_OK);
361 /*******************************************************************************
363 * FUNCTION: AcpiPsCreateOp
365 * PARAMETERS: WalkState - Current state
366 * AmlOpStart - Op start in AML
367 * NewOp - Returned Op
371 * DESCRIPTION: Get Op from AML
373 ******************************************************************************/
377 ACPI_WALK_STATE *WalkState,
379 ACPI_PARSE_OBJECT **NewOp)
381 ACPI_STATUS Status = AE_OK;
382 ACPI_PARSE_OBJECT *Op;
383 ACPI_PARSE_OBJECT *NamedOp = NULL;
384 ACPI_PARSE_OBJECT *ParentScope;
386 const ACPI_OPCODE_INFO *OpInfo;
389 ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
392 Status = AcpiPsGetAmlOpcode (WalkState);
393 if (Status == AE_CTRL_PARSE_CONTINUE)
395 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
398 /* Create Op structure and append to parent's argument list */
400 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
401 Op = AcpiPsAllocOp (WalkState->Opcode);
404 return_ACPI_STATUS (AE_NO_MEMORY);
407 if (WalkState->OpInfo->Flags & AML_NAMED)
409 Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
411 if (ACPI_FAILURE (Status))
413 return_ACPI_STATUS (Status);
417 return_ACPI_STATUS (AE_OK);
420 /* Not a named opcode, just allocate Op and append to parent */
422 if (WalkState->OpInfo->Flags & AML_CREATE)
425 * Backup to beginning of CreateXXXfield declaration
426 * BodyLength is unknown until we parse the body
428 Op->Named.Data = AmlOpStart;
429 Op->Named.Length = 0;
432 ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
433 AcpiPsAppendArg (ParentScope, Op);
437 OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
438 if (OpInfo->Flags & AML_HAS_TARGET)
440 ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
441 if (ParentScope->Common.ArgListLength > ArgumentCount)
443 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
446 else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
448 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
452 if (WalkState->DescendingCallback != NULL)
455 * Find the object. This will either insert the object into
456 * the namespace or simply look it up
458 WalkState->Op = *NewOp = Op;
460 Status = WalkState->DescendingCallback (WalkState, &Op);
461 Status = AcpiPsNextParseState (WalkState, Op, Status);
462 if (Status == AE_CTRL_PENDING)
464 Status = AE_CTRL_PARSE_PENDING;
468 return_ACPI_STATUS (Status);
472 /*******************************************************************************
474 * FUNCTION: AcpiPsGetArguments
476 * PARAMETERS: WalkState - Current state
477 * AmlOpStart - Op start in AML
482 * DESCRIPTION: Get arguments for passed Op.
484 ******************************************************************************/
488 ACPI_WALK_STATE *WalkState,
490 ACPI_PARSE_OBJECT *Op)
492 ACPI_STATUS Status = AE_OK;
493 ACPI_PARSE_OBJECT *Arg = NULL;
496 ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState);
499 switch (Op->Common.AmlOpcode)
501 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
502 case AML_WORD_OP: /* AML_WORDDATA_ARG */
503 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
504 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
505 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
507 /* Fill in constant or string argument directly */
509 AcpiPsGetNextSimpleArg (&(WalkState->ParserState),
510 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
513 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
515 Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1);
516 if (ACPI_FAILURE (Status))
518 return_ACPI_STATUS (Status);
521 WalkState->ArgTypes = 0;
526 * Op is not a constant or string, append each argument to the Op
528 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount)
530 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
531 WalkState->ParserState.AmlStart);
533 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
534 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
535 if (ACPI_FAILURE (Status))
537 return_ACPI_STATUS (Status);
542 Arg->Common.AmlOffset = WalkState->AmlOffset;
543 AcpiPsAppendArg (Op, Arg);
546 INCREMENT_ARG_LIST (WalkState->ArgTypes);
550 /* Special processing for certain opcodes */
552 /* TBD (remove): Temporary mechanism to disable this code if needed */
554 #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
556 if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS1) &&
557 ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0))
560 * We want to skip If/Else/While constructs during Pass1 because we
561 * want to actually conditionally execute the code during Pass2.
563 * Except for disassembly, where we always want to walk the
564 * If/Else/While packages
566 switch (Op->Common.AmlOpcode)
572 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
573 "Pass1: Skipping an If/Else/While body\n"));
575 /* Skip body of if/else/while in pass 1 */
577 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
578 WalkState->ArgCount = 0;
587 switch (Op->Common.AmlOpcode)
591 * Skip parsing of control method because we don't have enough
592 * info in the first pass to parse it correctly.
594 * Save the length and address of the body
596 Op->Named.Data = WalkState->ParserState.Aml;
597 Op->Named.Length = (UINT32)
598 (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml);
600 /* Skip body of method */
602 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
603 WalkState->ArgCount = 0;
608 case AML_VAR_PACKAGE_OP:
610 if ((Op->Common.Parent) &&
611 (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
612 (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
615 * Skip parsing of Buffers and Packages because we don't have
616 * enough info in the first pass to parse them correctly.
618 Op->Named.Data = AmlOpStart;
619 Op->Named.Length = (UINT32)
620 (WalkState->ParserState.PkgEnd - AmlOpStart);
624 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
625 WalkState->ArgCount = 0;
631 if (WalkState->ControlState)
633 WalkState->ControlState->Control.PackageEnd =
634 WalkState->ParserState.PkgEnd;
640 /* No action for all other opcodes */
647 return_ACPI_STATUS (AE_OK);
651 /*******************************************************************************
653 * FUNCTION: AcpiPsCompleteOp
655 * PARAMETERS: WalkState - Current state
657 * Status - Parse status before complete Op
661 * DESCRIPTION: Complete Op
663 ******************************************************************************/
667 ACPI_WALK_STATE *WalkState,
668 ACPI_PARSE_OBJECT **Op,
674 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
678 * Finished one argument of the containing scope
680 WalkState->ParserState.Scope->ParseScope.ArgCount--;
682 /* Close this Op (will result in parse subtree deletion) */
684 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
685 if (ACPI_FAILURE (Status2))
687 return_ACPI_STATUS (Status2);
698 case AE_CTRL_TRANSFER:
700 /* We are about to transfer to a called method */
702 WalkState->PrevOp = NULL;
703 WalkState->PrevArgTypes = WalkState->ArgTypes;
704 return_ACPI_STATUS (Status);
709 AcpiPsPopScope (&(WalkState->ParserState), Op,
710 &WalkState->ArgTypes, &WalkState->ArgCount);
715 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
716 WalkState->Opcode = (*Op)->Common.AmlOpcode;
718 Status = WalkState->AscendingCallback (WalkState);
719 Status = AcpiPsNextParseState (WalkState, *Op, Status);
721 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
722 if (ACPI_FAILURE (Status2))
724 return_ACPI_STATUS (Status2);
733 case AE_CTRL_CONTINUE:
735 /* Pop off scopes until we find the While */
737 while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
739 AcpiPsPopScope (&(WalkState->ParserState), Op,
740 &WalkState->ArgTypes, &WalkState->ArgCount);
743 /* Close this iteration of the While loop */
746 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
747 WalkState->Opcode = (*Op)->Common.AmlOpcode;
749 Status = WalkState->AscendingCallback (WalkState);
750 Status = AcpiPsNextParseState (WalkState, *Op, Status);
752 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
753 if (ACPI_FAILURE (Status2))
755 return_ACPI_STATUS (Status2);
762 case AE_CTRL_TERMINATE:
769 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
770 if (ACPI_FAILURE (Status2))
772 return_ACPI_STATUS (Status2);
775 AcpiUtDeleteGenericState (
776 AcpiUtPopGenericState (&WalkState->ControlState));
779 AcpiPsPopScope (&(WalkState->ParserState), Op,
780 &WalkState->ArgTypes, &WalkState->ArgCount);
784 return_ACPI_STATUS (AE_OK);
787 default: /* All other non-AE_OK status */
793 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
794 if (ACPI_FAILURE (Status2))
796 return_ACPI_STATUS (Status2);
800 AcpiPsPopScope (&(WalkState->ParserState), Op,
801 &WalkState->ArgTypes, &WalkState->ArgCount);
808 * TBD: Cleanup parse ops on error
812 AcpiPsPopScope (ParserState, Op,
813 &WalkState->ArgTypes, &WalkState->ArgCount);
816 WalkState->PrevOp = NULL;
817 WalkState->PrevArgTypes = WalkState->ArgTypes;
818 return_ACPI_STATUS (Status);
821 /* This scope complete? */
823 if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
825 AcpiPsPopScope (&(WalkState->ParserState), Op,
826 &WalkState->ArgTypes, &WalkState->ArgCount);
827 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
834 return_ACPI_STATUS (AE_OK);
838 /*******************************************************************************
840 * FUNCTION: AcpiPsCompleteFinalOp
842 * PARAMETERS: WalkState - Current state
844 * Status - Current parse status before complete last
849 * DESCRIPTION: Complete last Op.
851 ******************************************************************************/
854 AcpiPsCompleteFinalOp (
855 ACPI_WALK_STATE *WalkState,
856 ACPI_PARSE_OBJECT *Op,
862 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
866 * Complete the last Op (if not completed), and clear the scope stack.
867 * It is easily possible to end an AML "package" with an unbounded number
868 * of open scopes (such as when several ASL blocks are closed with
869 * sequential closing braces). We want to terminate each one cleanly.
871 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
876 if (WalkState->AscendingCallback != NULL)
879 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
880 WalkState->Opcode = Op->Common.AmlOpcode;
882 Status = WalkState->AscendingCallback (WalkState);
883 Status = AcpiPsNextParseState (WalkState, Op, Status);
884 if (Status == AE_CTRL_PENDING)
886 Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
887 if (ACPI_FAILURE (Status))
889 return_ACPI_STATUS (Status);
893 if (Status == AE_CTRL_TERMINATE)
902 Status2 = AcpiPsCompleteThisOp (WalkState, Op);
903 if (ACPI_FAILURE (Status2))
905 return_ACPI_STATUS (Status2);
909 AcpiPsPopScope (&(WalkState->ParserState), &Op,
910 &WalkState->ArgTypes, &WalkState->ArgCount);
914 return_ACPI_STATUS (Status);
917 else if (ACPI_FAILURE (Status))
919 /* First error is most important */
921 (void) AcpiPsCompleteThisOp (WalkState, Op);
922 return_ACPI_STATUS (Status);
926 Status2 = AcpiPsCompleteThisOp (WalkState, Op);
927 if (ACPI_FAILURE (Status2))
929 return_ACPI_STATUS (Status2);
933 AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
934 &WalkState->ArgCount);
938 return_ACPI_STATUS (Status);
942 /*******************************************************************************
944 * FUNCTION: AcpiPsParseLoop
946 * PARAMETERS: WalkState - Current state
950 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
953 ******************************************************************************/
957 ACPI_WALK_STATE *WalkState)
959 ACPI_STATUS Status = AE_OK;
960 ACPI_PARSE_OBJECT *Op = NULL; /* current op */
961 ACPI_PARSE_STATE *ParserState;
962 UINT8 *AmlOpStart = NULL;
965 ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState);
968 if (WalkState->DescendingCallback == NULL)
970 return_ACPI_STATUS (AE_BAD_PARAMETER);
973 ParserState = &WalkState->ParserState;
974 WalkState->ArgTypes = 0;
976 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
978 if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
980 /* We are restarting a preempted control method */
982 if (AcpiPsHasCompletedScope (ParserState))
985 * We must check if a predicate to an IF or WHILE statement
988 if ((ParserState->Scope->ParseScope.Op) &&
989 ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
990 (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
991 (WalkState->ControlState) &&
992 (WalkState->ControlState->Common.State ==
993 ACPI_CONTROL_PREDICATE_EXECUTING))
996 * A predicate was just completed, get the value of the
997 * predicate and branch based on that value
999 WalkState->Op = NULL;
1000 Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
1001 if (ACPI_FAILURE (Status) &&
1002 ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
1004 if (Status == AE_AML_NO_RETURN_VALUE)
1006 ACPI_EXCEPTION ((AE_INFO, Status,
1007 "Invoked method did not return a value"));
1011 ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed"));
1012 return_ACPI_STATUS (Status);
1015 Status = AcpiPsNextParseState (WalkState, Op, Status);
1018 AcpiPsPopScope (ParserState, &Op,
1019 &WalkState->ArgTypes, &WalkState->ArgCount);
1020 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
1022 else if (WalkState->PrevOp)
1024 /* We were in the middle of an op */
1026 Op = WalkState->PrevOp;
1027 WalkState->ArgTypes = WalkState->PrevArgTypes;
1032 /* Iterative parsing loop, while there is more AML to process: */
1034 while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
1036 AmlOpStart = ParserState->Aml;
1039 Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op);
1040 if (ACPI_FAILURE (Status))
1042 if (Status == AE_CTRL_PARSE_CONTINUE)
1047 if (Status == AE_CTRL_PARSE_PENDING)
1052 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1053 if (ACPI_FAILURE (Status))
1055 return_ACPI_STATUS (Status);
1061 Op->Common.AmlOffset = WalkState->AmlOffset;
1063 if (WalkState->OpInfo)
1065 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1066 "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
1067 (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
1068 Op, ParserState->Aml, Op->Common.AmlOffset));
1074 * Start ArgCount at zero because we don't know if there are
1077 WalkState->ArgCount = 0;
1079 /* Are there any arguments that must be processed? */
1081 if (WalkState->ArgTypes)
1085 Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op);
1086 if (ACPI_FAILURE (Status))
1088 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1089 if (ACPI_FAILURE (Status))
1091 return_ACPI_STATUS (Status);
1098 /* Check for arguments that need to be processed */
1100 if (WalkState->ArgCount)
1103 * There are arguments (complex ones), push Op and
1104 * prepare for argument
1106 Status = AcpiPsPushScope (ParserState, Op,
1107 WalkState->ArgTypes, WalkState->ArgCount);
1108 if (ACPI_FAILURE (Status))
1110 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1111 if (ACPI_FAILURE (Status))
1113 return_ACPI_STATUS (Status);
1124 * All arguments have been processed -- Op is complete,
1127 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1128 if (WalkState->OpInfo->Flags & AML_NAMED)
1135 if (Op->Common.AmlOpcode == AML_REGION_OP)
1138 * Skip parsing of control method or opregion body,
1139 * because we don't have enough info in the first pass
1140 * to parse them correctly.
1142 * Completed parsing an OpRegion declaration, we now
1145 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1149 if (WalkState->OpInfo->Flags & AML_CREATE)
1152 * Backup to beginning of CreateXXXfield declaration (1 for
1155 * BodyLength is unknown until we parse the body
1157 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1160 /* This op complete, notify the dispatcher */
1162 if (WalkState->AscendingCallback != NULL)
1165 WalkState->Opcode = Op->Common.AmlOpcode;
1167 Status = WalkState->AscendingCallback (WalkState);
1168 Status = AcpiPsNextParseState (WalkState, Op, Status);
1169 if (Status == AE_CTRL_PENDING)
1175 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1176 if (ACPI_FAILURE (Status))
1178 return_ACPI_STATUS (Status);
1181 } /* while ParserState->Aml */
1183 Status = AcpiPsCompleteFinalOp (WalkState, Op, Status);
1184 return_ACPI_STATUS (Status);