1 /******************************************************************************
3 * Module Name: psloop - Main AML parse loop
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2011, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
46 * Parse the AML and build an operation tree as most interpreters, (such as
47 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
48 * to tightly constrain stack and dynamic memory usage. Parsing is kept
49 * flexible and the code fairly compact by parsing based on a list of AML
50 * opcode templates in AmlOpInfo[].
53 #include <contrib/dev/acpica/include/acpi.h>
54 #include <contrib/dev/acpica/include/accommon.h>
55 #include <contrib/dev/acpica/include/acparser.h>
56 #include <contrib/dev/acpica/include/acdispat.h>
57 #include <contrib/dev/acpica/include/amlcode.h>
59 #define _COMPONENT ACPI_PARSER
60 ACPI_MODULE_NAME ("psloop")
62 static UINT32 AcpiGbl_Depth = 0;
65 /* Local prototypes */
69 ACPI_WALK_STATE *WalkState);
73 ACPI_WALK_STATE *WalkState,
75 ACPI_PARSE_OBJECT *UnnamedOp,
76 ACPI_PARSE_OBJECT **Op);
80 ACPI_WALK_STATE *WalkState,
82 ACPI_PARSE_OBJECT **NewOp);
86 ACPI_WALK_STATE *WalkState,
88 ACPI_PARSE_OBJECT *Op);
92 ACPI_WALK_STATE *WalkState,
93 ACPI_PARSE_OBJECT **Op,
97 AcpiPsCompleteFinalOp (
98 ACPI_WALK_STATE *WalkState,
99 ACPI_PARSE_OBJECT *Op,
103 AcpiPsLinkModuleCode (
104 ACPI_PARSE_OBJECT *ParentOp,
107 ACPI_OWNER_ID OwnerId);
110 /*******************************************************************************
112 * FUNCTION: AcpiPsGetAmlOpcode
114 * PARAMETERS: WalkState - Current state
118 * DESCRIPTION: Extract the next AML opcode from the input stream.
120 ******************************************************************************/
124 ACPI_WALK_STATE *WalkState)
127 ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
130 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
131 WalkState->ParserState.AmlStart);
132 WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
135 * First cut to determine what we have found:
136 * 1) A valid AML opcode
138 * 3) An unknown/invalid opcode
140 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
142 switch (WalkState->OpInfo->Class)
144 case AML_CLASS_ASCII:
145 case AML_CLASS_PREFIX:
147 * Starts with a valid prefix or ASCII char, this is a name
148 * string. Convert the bare name string to a namepath.
150 WalkState->Opcode = AML_INT_NAMEPATH_OP;
151 WalkState->ArgTypes = ARGP_NAMESTRING;
154 case AML_CLASS_UNKNOWN:
156 /* The opcode is unrecognized. Just skip unknown opcodes */
158 ACPI_ERROR ((AE_INFO,
159 "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring",
160 WalkState->Opcode, WalkState->ParserState.Aml, WalkState->AmlOffset));
162 ACPI_DUMP_BUFFER (WalkState->ParserState.Aml, 128);
164 /* Assume one-byte bad opcode */
166 WalkState->ParserState.Aml++;
167 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
171 /* Found opcode info, this is a normal opcode */
173 WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
174 WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
178 return_ACPI_STATUS (AE_OK);
182 /*******************************************************************************
184 * FUNCTION: AcpiPsBuildNamedOp
186 * PARAMETERS: WalkState - Current state
187 * AmlOpStart - Begin of named Op in AML
188 * UnnamedOp - Early Op (not a named Op)
193 * DESCRIPTION: Parse a named Op
195 ******************************************************************************/
199 ACPI_WALK_STATE *WalkState,
201 ACPI_PARSE_OBJECT *UnnamedOp,
202 ACPI_PARSE_OBJECT **Op)
204 ACPI_STATUS Status = AE_OK;
205 ACPI_PARSE_OBJECT *Arg = NULL;
208 ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
211 UnnamedOp->Common.Value.Arg = NULL;
212 UnnamedOp->Common.ArgListLength = 0;
213 UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
216 * Get and append arguments until we find the node that contains
217 * the name (the type ARGP_NAME).
219 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
220 (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
222 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
223 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
224 if (ACPI_FAILURE (Status))
226 return_ACPI_STATUS (Status);
229 AcpiPsAppendArg (UnnamedOp, Arg);
230 INCREMENT_ARG_LIST (WalkState->ArgTypes);
234 * Make sure that we found a NAME and didn't run out of arguments
236 if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
238 return_ACPI_STATUS (AE_AML_NO_OPERAND);
241 /* We know that this arg is a name, move to next arg */
243 INCREMENT_ARG_LIST (WalkState->ArgTypes);
246 * Find the object. This will either insert the object into
247 * the namespace or simply look it up
249 WalkState->Op = NULL;
251 Status = WalkState->DescendingCallback (WalkState, Op);
252 if (ACPI_FAILURE (Status))
254 ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
255 return_ACPI_STATUS (Status);
260 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
263 Status = AcpiPsNextParseState (WalkState, *Op, Status);
264 if (ACPI_FAILURE (Status))
266 if (Status == AE_CTRL_PENDING)
268 return_ACPI_STATUS (AE_CTRL_PARSE_PENDING);
270 return_ACPI_STATUS (Status);
273 AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
276 if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
277 (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
280 * Defer final parsing of an OperationRegion body, because we don't
281 * have enough info in the first pass to parse it correctly (i.e.,
282 * there may be method calls within the TermArg elements of the body.)
284 * However, we must continue parsing because the opregion is not a
285 * standalone package -- we don't know where the end is at this point.
287 * (Length is unknown until parse of the body complete)
289 (*Op)->Named.Data = AmlOpStart;
290 (*Op)->Named.Length = 0;
293 return_ACPI_STATUS (AE_OK);
297 /*******************************************************************************
299 * FUNCTION: AcpiPsCreateOp
301 * PARAMETERS: WalkState - Current state
302 * AmlOpStart - Op start in AML
303 * NewOp - Returned Op
307 * DESCRIPTION: Get Op from AML
309 ******************************************************************************/
313 ACPI_WALK_STATE *WalkState,
315 ACPI_PARSE_OBJECT **NewOp)
317 ACPI_STATUS Status = AE_OK;
318 ACPI_PARSE_OBJECT *Op;
319 ACPI_PARSE_OBJECT *NamedOp = NULL;
320 ACPI_PARSE_OBJECT *ParentScope;
322 const ACPI_OPCODE_INFO *OpInfo;
325 ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
328 Status = AcpiPsGetAmlOpcode (WalkState);
329 if (Status == AE_CTRL_PARSE_CONTINUE)
331 return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
334 /* Create Op structure and append to parent's argument list */
336 WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
337 Op = AcpiPsAllocOp (WalkState->Opcode);
340 return_ACPI_STATUS (AE_NO_MEMORY);
343 if (WalkState->OpInfo->Flags & AML_NAMED)
345 Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
347 if (ACPI_FAILURE (Status))
349 return_ACPI_STATUS (Status);
353 return_ACPI_STATUS (AE_OK);
356 /* Not a named opcode, just allocate Op and append to parent */
358 if (WalkState->OpInfo->Flags & AML_CREATE)
361 * Backup to beginning of CreateXXXfield declaration
362 * BodyLength is unknown until we parse the body
364 Op->Named.Data = AmlOpStart;
365 Op->Named.Length = 0;
368 if (WalkState->Opcode == AML_BANK_FIELD_OP)
371 * Backup to beginning of BankField declaration
372 * BodyLength is unknown until we parse the body
374 Op->Named.Data = AmlOpStart;
375 Op->Named.Length = 0;
378 ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
379 AcpiPsAppendArg (ParentScope, Op);
383 OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
384 if (OpInfo->Flags & AML_HAS_TARGET)
386 ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
387 if (ParentScope->Common.ArgListLength > ArgumentCount)
389 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
392 else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
394 Op->Common.Flags |= ACPI_PARSEOP_TARGET;
398 if (WalkState->DescendingCallback != NULL)
401 * Find the object. This will either insert the object into
402 * the namespace or simply look it up
404 WalkState->Op = *NewOp = Op;
406 Status = WalkState->DescendingCallback (WalkState, &Op);
407 Status = AcpiPsNextParseState (WalkState, Op, Status);
408 if (Status == AE_CTRL_PENDING)
410 Status = AE_CTRL_PARSE_PENDING;
414 return_ACPI_STATUS (Status);
418 /*******************************************************************************
420 * FUNCTION: AcpiPsGetArguments
422 * PARAMETERS: WalkState - Current state
423 * AmlOpStart - Op start in AML
428 * DESCRIPTION: Get arguments for passed Op.
430 ******************************************************************************/
434 ACPI_WALK_STATE *WalkState,
436 ACPI_PARSE_OBJECT *Op)
438 ACPI_STATUS Status = AE_OK;
439 ACPI_PARSE_OBJECT *Arg = NULL;
440 const ACPI_OPCODE_INFO *OpInfo;
443 ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState);
446 switch (Op->Common.AmlOpcode)
448 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
449 case AML_WORD_OP: /* AML_WORDDATA_ARG */
450 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
451 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
452 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
454 /* Fill in constant or string argument directly */
456 AcpiPsGetNextSimpleArg (&(WalkState->ParserState),
457 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
460 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
462 Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1);
463 if (ACPI_FAILURE (Status))
465 return_ACPI_STATUS (Status);
468 WalkState->ArgTypes = 0;
473 * Op is not a constant or string, append each argument to the Op
475 while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount)
477 WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
478 WalkState->ParserState.AmlStart);
480 Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
481 GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
482 if (ACPI_FAILURE (Status))
484 return_ACPI_STATUS (Status);
489 Arg->Common.AmlOffset = WalkState->AmlOffset;
490 AcpiPsAppendArg (Op, Arg);
493 INCREMENT_ARG_LIST (WalkState->ArgTypes);
498 * Handle executable code at "module-level". This refers to
499 * executable opcodes that appear outside of any control method.
501 if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) &&
502 ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0))
505 * We want to skip If/Else/While constructs during Pass1 because we
506 * want to actually conditionally execute the code during Pass2.
508 * Except for disassembly, where we always want to walk the
509 * If/Else/While packages
511 switch (Op->Common.AmlOpcode)
518 * Currently supported module-level opcodes are:
519 * IF/ELSE/WHILE. These appear to be the most common,
520 * and easiest to support since they open an AML
523 if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1)
525 AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart,
526 (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart),
530 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
531 "Pass1: Skipping an If/Else/While body\n"));
533 /* Skip body of if/else/while in pass 1 */
535 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
536 WalkState->ArgCount = 0;
541 * Check for an unsupported executable opcode at module
542 * level. We must be in PASS1, the parent must be a SCOPE,
543 * The opcode class must be EXECUTE, and the opcode must
544 * not be an argument to another opcode.
546 if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) &&
547 (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
549 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
550 if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
553 ACPI_WARNING ((AE_INFO,
554 "Detected an unsupported executable opcode "
555 "at module-level: [0x%.4X] at table offset 0x%.4X",
556 Op->Common.AmlOpcode,
557 (UINT32) (ACPI_PTR_DIFF (AmlOpStart,
558 WalkState->ParserState.AmlStart) +
559 sizeof (ACPI_TABLE_HEADER))));
566 /* Special processing for certain opcodes */
568 switch (Op->Common.AmlOpcode)
572 * Skip parsing of control method because we don't have enough
573 * info in the first pass to parse it correctly.
575 * Save the length and address of the body
577 Op->Named.Data = WalkState->ParserState.Aml;
578 Op->Named.Length = (UINT32)
579 (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml);
581 /* Skip body of method */
583 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
584 WalkState->ArgCount = 0;
589 case AML_VAR_PACKAGE_OP:
591 if ((Op->Common.Parent) &&
592 (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
593 (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
596 * Skip parsing of Buffers and Packages because we don't have
597 * enough info in the first pass to parse them correctly.
599 Op->Named.Data = AmlOpStart;
600 Op->Named.Length = (UINT32)
601 (WalkState->ParserState.PkgEnd - AmlOpStart);
605 WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
606 WalkState->ArgCount = 0;
612 if (WalkState->ControlState)
614 WalkState->ControlState->Control.PackageEnd =
615 WalkState->ParserState.PkgEnd;
621 /* No action for all other opcodes */
628 return_ACPI_STATUS (AE_OK);
632 /*******************************************************************************
634 * FUNCTION: AcpiPsLinkModuleCode
636 * PARAMETERS: ParentOp - Parent parser op
637 * AmlStart - Pointer to the AML
638 * AmlLength - Length of executable AML
639 * OwnerId - OwnerId of module level code
643 * DESCRIPTION: Wrap the module-level code with a method object and link the
644 * object to the global list. Note, the mutex field of the method
645 * object is used to link multiple module-level code objects.
647 ******************************************************************************/
650 AcpiPsLinkModuleCode (
651 ACPI_PARSE_OBJECT *ParentOp,
654 ACPI_OWNER_ID OwnerId)
656 ACPI_OPERAND_OBJECT *Prev;
657 ACPI_OPERAND_OBJECT *Next;
658 ACPI_OPERAND_OBJECT *MethodObj;
659 ACPI_NAMESPACE_NODE *ParentNode;
662 /* Get the tail of the list */
664 Prev = Next = AcpiGbl_ModuleCodeList;
668 Next = Next->Method.Mutex;
672 * Insert the module level code into the list. Merge it if it is
673 * adjacent to the previous element.
676 ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart))
678 /* Create, initialize, and link a new temporary method object */
680 MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
686 if (ParentOp->Common.Node)
688 ParentNode = ParentOp->Common.Node;
692 ParentNode = AcpiGbl_RootNode;
695 MethodObj->Method.AmlStart = AmlStart;
696 MethodObj->Method.AmlLength = AmlLength;
697 MethodObj->Method.OwnerId = OwnerId;
698 MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL;
701 * Save the parent node in NextObject. This is cheating, but we
702 * don't want to expand the method object.
704 MethodObj->Method.NextObject =
705 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode);
709 AcpiGbl_ModuleCodeList = MethodObj;
713 Prev->Method.Mutex = MethodObj;
718 Prev->Method.AmlLength += AmlLength;
723 /*******************************************************************************
725 * FUNCTION: AcpiPsCompleteOp
727 * PARAMETERS: WalkState - Current state
729 * Status - Parse status before complete Op
733 * DESCRIPTION: Complete Op
735 ******************************************************************************/
739 ACPI_WALK_STATE *WalkState,
740 ACPI_PARSE_OBJECT **Op,
746 ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
750 * Finished one argument of the containing scope
752 WalkState->ParserState.Scope->ParseScope.ArgCount--;
754 /* Close this Op (will result in parse subtree deletion) */
756 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
757 if (ACPI_FAILURE (Status2))
759 return_ACPI_STATUS (Status2);
770 case AE_CTRL_TRANSFER:
772 /* We are about to transfer to a called method */
774 WalkState->PrevOp = NULL;
775 WalkState->PrevArgTypes = WalkState->ArgTypes;
776 return_ACPI_STATUS (Status);
781 AcpiPsPopScope (&(WalkState->ParserState), Op,
782 &WalkState->ArgTypes, &WalkState->ArgCount);
787 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
788 WalkState->Opcode = (*Op)->Common.AmlOpcode;
790 Status = WalkState->AscendingCallback (WalkState);
791 Status = AcpiPsNextParseState (WalkState, *Op, Status);
793 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
794 if (ACPI_FAILURE (Status2))
796 return_ACPI_STATUS (Status2);
805 case AE_CTRL_CONTINUE:
807 /* Pop off scopes until we find the While */
809 while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
811 AcpiPsPopScope (&(WalkState->ParserState), Op,
812 &WalkState->ArgTypes, &WalkState->ArgCount);
815 /* Close this iteration of the While loop */
818 WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
819 WalkState->Opcode = (*Op)->Common.AmlOpcode;
821 Status = WalkState->AscendingCallback (WalkState);
822 Status = AcpiPsNextParseState (WalkState, *Op, Status);
824 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
825 if (ACPI_FAILURE (Status2))
827 return_ACPI_STATUS (Status2);
834 case AE_CTRL_TERMINATE:
841 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
842 if (ACPI_FAILURE (Status2))
844 return_ACPI_STATUS (Status2);
847 AcpiUtDeleteGenericState (
848 AcpiUtPopGenericState (&WalkState->ControlState));
851 AcpiPsPopScope (&(WalkState->ParserState), Op,
852 &WalkState->ArgTypes, &WalkState->ArgCount);
856 return_ACPI_STATUS (AE_OK);
859 default: /* All other non-AE_OK status */
865 Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
866 if (ACPI_FAILURE (Status2))
868 return_ACPI_STATUS (Status2);
872 AcpiPsPopScope (&(WalkState->ParserState), Op,
873 &WalkState->ArgTypes, &WalkState->ArgCount);
880 * TBD: Cleanup parse ops on error
884 AcpiPsPopScope (ParserState, Op,
885 &WalkState->ArgTypes, &WalkState->ArgCount);
888 WalkState->PrevOp = NULL;
889 WalkState->PrevArgTypes = WalkState->ArgTypes;
890 return_ACPI_STATUS (Status);
893 /* This scope complete? */
895 if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
897 AcpiPsPopScope (&(WalkState->ParserState), Op,
898 &WalkState->ArgTypes, &WalkState->ArgCount);
899 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
906 return_ACPI_STATUS (AE_OK);
910 /*******************************************************************************
912 * FUNCTION: AcpiPsCompleteFinalOp
914 * PARAMETERS: WalkState - Current state
916 * Status - Current parse status before complete last
921 * DESCRIPTION: Complete last Op.
923 ******************************************************************************/
926 AcpiPsCompleteFinalOp (
927 ACPI_WALK_STATE *WalkState,
928 ACPI_PARSE_OBJECT *Op,
934 ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
938 * Complete the last Op (if not completed), and clear the scope stack.
939 * It is easily possible to end an AML "package" with an unbounded number
940 * of open scopes (such as when several ASL blocks are closed with
941 * sequential closing braces). We want to terminate each one cleanly.
943 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
948 if (WalkState->AscendingCallback != NULL)
951 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
952 WalkState->Opcode = Op->Common.AmlOpcode;
954 Status = WalkState->AscendingCallback (WalkState);
955 Status = AcpiPsNextParseState (WalkState, Op, Status);
956 if (Status == AE_CTRL_PENDING)
958 Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
959 if (ACPI_FAILURE (Status))
961 return_ACPI_STATUS (Status);
965 if (Status == AE_CTRL_TERMINATE)
974 Status2 = AcpiPsCompleteThisOp (WalkState, Op);
975 if (ACPI_FAILURE (Status2))
977 return_ACPI_STATUS (Status2);
981 AcpiPsPopScope (&(WalkState->ParserState), &Op,
982 &WalkState->ArgTypes, &WalkState->ArgCount);
986 return_ACPI_STATUS (Status);
989 else if (ACPI_FAILURE (Status))
991 /* First error is most important */
993 (void) AcpiPsCompleteThisOp (WalkState, Op);
994 return_ACPI_STATUS (Status);
998 Status2 = AcpiPsCompleteThisOp (WalkState, Op);
999 if (ACPI_FAILURE (Status2))
1001 return_ACPI_STATUS (Status2);
1005 AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
1006 &WalkState->ArgCount);
1010 return_ACPI_STATUS (Status);
1014 /*******************************************************************************
1016 * FUNCTION: AcpiPsParseLoop
1018 * PARAMETERS: WalkState - Current state
1022 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
1025 ******************************************************************************/
1029 ACPI_WALK_STATE *WalkState)
1031 ACPI_STATUS Status = AE_OK;
1032 ACPI_PARSE_OBJECT *Op = NULL; /* current op */
1033 ACPI_PARSE_STATE *ParserState;
1034 UINT8 *AmlOpStart = NULL;
1037 ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState);
1040 if (WalkState->DescendingCallback == NULL)
1042 return_ACPI_STATUS (AE_BAD_PARAMETER);
1045 ParserState = &WalkState->ParserState;
1046 WalkState->ArgTypes = 0;
1048 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
1050 if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
1052 /* We are restarting a preempted control method */
1054 if (AcpiPsHasCompletedScope (ParserState))
1057 * We must check if a predicate to an IF or WHILE statement
1058 * was just completed
1060 if ((ParserState->Scope->ParseScope.Op) &&
1061 ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
1062 (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
1063 (WalkState->ControlState) &&
1064 (WalkState->ControlState->Common.State ==
1065 ACPI_CONTROL_PREDICATE_EXECUTING))
1068 * A predicate was just completed, get the value of the
1069 * predicate and branch based on that value
1071 WalkState->Op = NULL;
1072 Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
1073 if (ACPI_FAILURE (Status) &&
1074 ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
1076 if (Status == AE_AML_NO_RETURN_VALUE)
1078 ACPI_EXCEPTION ((AE_INFO, Status,
1079 "Invoked method did not return a value"));
1082 ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed"));
1083 return_ACPI_STATUS (Status);
1086 Status = AcpiPsNextParseState (WalkState, Op, Status);
1089 AcpiPsPopScope (ParserState, &Op,
1090 &WalkState->ArgTypes, &WalkState->ArgCount);
1091 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
1093 else if (WalkState->PrevOp)
1095 /* We were in the middle of an op */
1097 Op = WalkState->PrevOp;
1098 WalkState->ArgTypes = WalkState->PrevArgTypes;
1103 /* Iterative parsing loop, while there is more AML to process: */
1105 while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
1107 AmlOpStart = ParserState->Aml;
1110 Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op);
1111 if (ACPI_FAILURE (Status))
1113 if (Status == AE_CTRL_PARSE_CONTINUE)
1118 if (Status == AE_CTRL_PARSE_PENDING)
1123 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1124 if (ACPI_FAILURE (Status))
1126 return_ACPI_STATUS (Status);
1132 Op->Common.AmlOffset = WalkState->AmlOffset;
1134 if (WalkState->OpInfo)
1136 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1137 "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
1138 (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
1139 Op, ParserState->Aml, Op->Common.AmlOffset));
1145 * Start ArgCount at zero because we don't know if there are
1148 WalkState->ArgCount = 0;
1150 /* Are there any arguments that must be processed? */
1152 if (WalkState->ArgTypes)
1156 Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op);
1157 if (ACPI_FAILURE (Status))
1159 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1160 if (ACPI_FAILURE (Status))
1162 return_ACPI_STATUS (Status);
1169 /* Check for arguments that need to be processed */
1171 if (WalkState->ArgCount)
1174 * There are arguments (complex ones), push Op and
1175 * prepare for argument
1177 Status = AcpiPsPushScope (ParserState, Op,
1178 WalkState->ArgTypes, WalkState->ArgCount);
1179 if (ACPI_FAILURE (Status))
1181 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1182 if (ACPI_FAILURE (Status))
1184 return_ACPI_STATUS (Status);
1195 * All arguments have been processed -- Op is complete,
1198 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
1199 if (WalkState->OpInfo->Flags & AML_NAMED)
1206 if (Op->Common.AmlOpcode == AML_REGION_OP ||
1207 Op->Common.AmlOpcode == AML_DATA_REGION_OP)
1210 * Skip parsing of control method or opregion body,
1211 * because we don't have enough info in the first pass
1212 * to parse them correctly.
1214 * Completed parsing an OpRegion declaration, we now
1217 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1221 if (WalkState->OpInfo->Flags & AML_CREATE)
1224 * Backup to beginning of CreateXXXfield declaration (1 for
1227 * BodyLength is unknown until we parse the body
1229 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1232 if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
1235 * Backup to beginning of BankField declaration
1237 * BodyLength is unknown until we parse the body
1239 Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
1242 /* This op complete, notify the dispatcher */
1244 if (WalkState->AscendingCallback != NULL)
1247 WalkState->Opcode = Op->Common.AmlOpcode;
1249 Status = WalkState->AscendingCallback (WalkState);
1250 Status = AcpiPsNextParseState (WalkState, Op, Status);
1251 if (Status == AE_CTRL_PENDING)
1257 Status = AcpiPsCompleteOp (WalkState, &Op, Status);
1258 if (ACPI_FAILURE (Status))
1260 return_ACPI_STATUS (Status);
1263 } /* while ParserState->Aml */
1265 Status = AcpiPsCompleteFinalOp (WalkState, Op, Status);
1266 return_ACPI_STATUS (Status);