1db2bae30SDana Myers /******************************************************************************
2db2bae30SDana Myers *
3db2bae30SDana Myers * Module Name: psloop - Main AML parse loop
4db2bae30SDana Myers *
5db2bae30SDana Myers *****************************************************************************/
6db2bae30SDana Myers
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp.
9db2bae30SDana Myers * All rights reserved.
10db2bae30SDana Myers *
1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross * are met:
1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross * without modification.
1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross * binary redistribution.
2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross * from this software without specific prior written permission.
25db2bae30SDana Myers *
2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross * Software Foundation.
29db2bae30SDana Myers *
3026f3cdf0SGordon Ross * NO WARRANTY
3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross */
43db2bae30SDana Myers
44db2bae30SDana Myers /*
45db2bae30SDana Myers * Parse the AML and build an operation tree as most interpreters, (such as
46db2bae30SDana Myers * Perl) do. Parsing is done by hand rather than with a YACC generated parser
47db2bae30SDana Myers * to tightly constrain stack and dynamic memory usage. Parsing is kept
48db2bae30SDana Myers * flexible and the code fairly compact by parsing based on a list of AML
49db2bae30SDana Myers * opcode templates in AmlOpInfo[].
50db2bae30SDana Myers */
51db2bae30SDana Myers
52db2bae30SDana Myers #include "acpi.h"
53aa2aa9a6SDana Myers #include "accommon.h"
54*385cc6b4SJerry Jelinek #include "acinterp.h"
55db2bae30SDana Myers #include "acparser.h"
56db2bae30SDana Myers #include "acdispat.h"
57db2bae30SDana Myers #include "amlcode.h"
58db2bae30SDana Myers
59db2bae30SDana Myers #define _COMPONENT ACPI_PARSER
60db2bae30SDana Myers ACPI_MODULE_NAME ("psloop")
61db2bae30SDana Myers
62db2bae30SDana Myers
63db2bae30SDana Myers /* Local prototypes */
64db2bae30SDana Myers
65db2bae30SDana Myers static ACPI_STATUS
66db2bae30SDana Myers AcpiPsGetArguments (
67db2bae30SDana Myers ACPI_WALK_STATE *WalkState,
68db2bae30SDana Myers UINT8 *AmlOpStart,
69db2bae30SDana Myers ACPI_PARSE_OBJECT *Op);
70db2bae30SDana Myers
7157190917SDana Myers static void
7257190917SDana Myers AcpiPsLinkModuleCode (
7357190917SDana Myers ACPI_PARSE_OBJECT *ParentOp,
7457190917SDana Myers UINT8 *AmlStart,
7557190917SDana Myers UINT32 AmlLength,
7657190917SDana Myers ACPI_OWNER_ID OwnerId);
7757190917SDana Myers
78db2bae30SDana Myers
79db2bae30SDana Myers /*******************************************************************************
80db2bae30SDana Myers *
81db2bae30SDana Myers * FUNCTION: AcpiPsGetArguments
82db2bae30SDana Myers *
83db2bae30SDana Myers * PARAMETERS: WalkState - Current state
84db2bae30SDana Myers * AmlOpStart - Op start in AML
85db2bae30SDana Myers * Op - Current Op
86db2bae30SDana Myers *
87db2bae30SDana Myers * RETURN: Status
88db2bae30SDana Myers *
89db2bae30SDana Myers * DESCRIPTION: Get arguments for passed Op.
90db2bae30SDana Myers *
91db2bae30SDana Myers ******************************************************************************/
92db2bae30SDana Myers
93db2bae30SDana Myers static ACPI_STATUS
AcpiPsGetArguments(ACPI_WALK_STATE * WalkState,UINT8 * AmlOpStart,ACPI_PARSE_OBJECT * Op)94db2bae30SDana Myers AcpiPsGetArguments (
95db2bae30SDana Myers ACPI_WALK_STATE *WalkState,
96db2bae30SDana Myers UINT8 *AmlOpStart,
97db2bae30SDana Myers ACPI_PARSE_OBJECT *Op)
98db2bae30SDana Myers {
99db2bae30SDana Myers ACPI_STATUS Status = AE_OK;
100db2bae30SDana Myers ACPI_PARSE_OBJECT *Arg = NULL;
10157190917SDana Myers const ACPI_OPCODE_INFO *OpInfo;
102db2bae30SDana Myers
103db2bae30SDana Myers
104db2bae30SDana Myers ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState);
105db2bae30SDana Myers
106db2bae30SDana Myers
107db2bae30SDana Myers switch (Op->Common.AmlOpcode)
108db2bae30SDana Myers {
109db2bae30SDana Myers case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
110db2bae30SDana Myers case AML_WORD_OP: /* AML_WORDDATA_ARG */
111db2bae30SDana Myers case AML_DWORD_OP: /* AML_DWORDATA_ARG */
112db2bae30SDana Myers case AML_QWORD_OP: /* AML_QWORDATA_ARG */
113db2bae30SDana Myers case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
114db2bae30SDana Myers
115db2bae30SDana Myers /* Fill in constant or string argument directly */
116db2bae30SDana Myers
117db2bae30SDana Myers AcpiPsGetNextSimpleArg (&(WalkState->ParserState),
118db2bae30SDana Myers GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
119db2bae30SDana Myers break;
120db2bae30SDana Myers
121db2bae30SDana Myers case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
122db2bae30SDana Myers
123*385cc6b4SJerry Jelinek Status = AcpiPsGetNextNamepath (WalkState,
124*385cc6b4SJerry Jelinek &(WalkState->ParserState), Op, ACPI_POSSIBLE_METHOD_CALL);
125db2bae30SDana Myers if (ACPI_FAILURE (Status))
126db2bae30SDana Myers {
127db2bae30SDana Myers return_ACPI_STATUS (Status);
128db2bae30SDana Myers }
129db2bae30SDana Myers
130db2bae30SDana Myers WalkState->ArgTypes = 0;
131db2bae30SDana Myers break;
132db2bae30SDana Myers
133db2bae30SDana Myers default:
134db2bae30SDana Myers /*
135db2bae30SDana Myers * Op is not a constant or string, append each argument to the Op
136db2bae30SDana Myers */
137*385cc6b4SJerry Jelinek while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
138*385cc6b4SJerry Jelinek !WalkState->ArgCount)
139db2bae30SDana Myers {
140*385cc6b4SJerry Jelinek WalkState->Aml = WalkState->ParserState.Aml;
141db2bae30SDana Myers
142db2bae30SDana Myers Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
143db2bae30SDana Myers GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
144db2bae30SDana Myers if (ACPI_FAILURE (Status))
145db2bae30SDana Myers {
146db2bae30SDana Myers return_ACPI_STATUS (Status);
147db2bae30SDana Myers }
148db2bae30SDana Myers
149db2bae30SDana Myers if (Arg)
150db2bae30SDana Myers {
151db2bae30SDana Myers AcpiPsAppendArg (Op, Arg);
152db2bae30SDana Myers }
153db2bae30SDana Myers
154db2bae30SDana Myers INCREMENT_ARG_LIST (WalkState->ArgTypes);
155db2bae30SDana Myers }
156db2bae30SDana Myers
157db2bae30SDana Myers
15857190917SDana Myers /*
15957190917SDana Myers * Handle executable code at "module-level". This refers to
16057190917SDana Myers * executable opcodes that appear outside of any control method.
16157190917SDana Myers */
16257190917SDana Myers if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) &&
163db2bae30SDana Myers ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0))
164db2bae30SDana Myers {
165db2bae30SDana Myers /*
166db2bae30SDana Myers * We want to skip If/Else/While constructs during Pass1 because we
167db2bae30SDana Myers * want to actually conditionally execute the code during Pass2.
168db2bae30SDana Myers *
169db2bae30SDana Myers * Except for disassembly, where we always want to walk the
170db2bae30SDana Myers * If/Else/While packages
171db2bae30SDana Myers */
172db2bae30SDana Myers switch (Op->Common.AmlOpcode)
173db2bae30SDana Myers {
174db2bae30SDana Myers case AML_IF_OP:
175db2bae30SDana Myers case AML_ELSE_OP:
176db2bae30SDana Myers case AML_WHILE_OP:
17757190917SDana Myers /*
17857190917SDana Myers * Currently supported module-level opcodes are:
17957190917SDana Myers * IF/ELSE/WHILE. These appear to be the most common,
18057190917SDana Myers * and easiest to support since they open an AML
18157190917SDana Myers * package.
18257190917SDana Myers */
18357190917SDana Myers if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1)
18457190917SDana Myers {
18557190917SDana Myers AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart,
18657190917SDana Myers (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart),
18757190917SDana Myers WalkState->OwnerId);
18857190917SDana Myers }
18957190917SDana Myers
190db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
191db2bae30SDana Myers "Pass1: Skipping an If/Else/While body\n"));
192db2bae30SDana Myers
193db2bae30SDana Myers /* Skip body of if/else/while in pass 1 */
194db2bae30SDana Myers
195db2bae30SDana Myers WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
196db2bae30SDana Myers WalkState->ArgCount = 0;
197db2bae30SDana Myers break;
198db2bae30SDana Myers
199db2bae30SDana Myers default:
20057190917SDana Myers /*
20157190917SDana Myers * Check for an unsupported executable opcode at module
20257190917SDana Myers * level. We must be in PASS1, the parent must be a SCOPE,
20357190917SDana Myers * The opcode class must be EXECUTE, and the opcode must
20457190917SDana Myers * not be an argument to another opcode.
20557190917SDana Myers */
20657190917SDana Myers if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) &&
20757190917SDana Myers (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
20857190917SDana Myers {
20957190917SDana Myers OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
21057190917SDana Myers if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
21157190917SDana Myers (!Arg))
21257190917SDana Myers {
21357190917SDana Myers ACPI_WARNING ((AE_INFO,
214*385cc6b4SJerry Jelinek "Unsupported module-level executable opcode "
215*385cc6b4SJerry Jelinek "0x%.2X at table offset 0x%.4X",
21657190917SDana Myers Op->Common.AmlOpcode,
21757190917SDana Myers (UINT32) (ACPI_PTR_DIFF (AmlOpStart,
21857190917SDana Myers WalkState->ParserState.AmlStart) +
21957190917SDana Myers sizeof (ACPI_TABLE_HEADER))));
22057190917SDana Myers }
22157190917SDana Myers }
222db2bae30SDana Myers break;
223db2bae30SDana Myers }
224db2bae30SDana Myers }
22557190917SDana Myers
22657190917SDana Myers /* Special processing for certain opcodes */
227db2bae30SDana Myers
228db2bae30SDana Myers switch (Op->Common.AmlOpcode)
229db2bae30SDana Myers {
230db2bae30SDana Myers case AML_METHOD_OP:
231db2bae30SDana Myers /*
232db2bae30SDana Myers * Skip parsing of control method because we don't have enough
233db2bae30SDana Myers * info in the first pass to parse it correctly.
234db2bae30SDana Myers *
235db2bae30SDana Myers * Save the length and address of the body
236db2bae30SDana Myers */
237db2bae30SDana Myers Op->Named.Data = WalkState->ParserState.Aml;
238db2bae30SDana Myers Op->Named.Length = (UINT32)
239db2bae30SDana Myers (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml);
240db2bae30SDana Myers
241db2bae30SDana Myers /* Skip body of method */
242db2bae30SDana Myers
243db2bae30SDana Myers WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
244db2bae30SDana Myers WalkState->ArgCount = 0;
245db2bae30SDana Myers break;
246db2bae30SDana Myers
247db2bae30SDana Myers case AML_BUFFER_OP:
248db2bae30SDana Myers case AML_PACKAGE_OP:
249db2bae30SDana Myers case AML_VAR_PACKAGE_OP:
250db2bae30SDana Myers
251db2bae30SDana Myers if ((Op->Common.Parent) &&
252db2bae30SDana Myers (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
253db2bae30SDana Myers (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
254db2bae30SDana Myers {
255db2bae30SDana Myers /*
256db2bae30SDana Myers * Skip parsing of Buffers and Packages because we don't have
257db2bae30SDana Myers * enough info in the first pass to parse them correctly.
258db2bae30SDana Myers */
259db2bae30SDana Myers Op->Named.Data = AmlOpStart;
260db2bae30SDana Myers Op->Named.Length = (UINT32)
261db2bae30SDana Myers (WalkState->ParserState.PkgEnd - AmlOpStart);
262db2bae30SDana Myers
263db2bae30SDana Myers /* Skip body */
264db2bae30SDana Myers
265db2bae30SDana Myers WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
266db2bae30SDana Myers WalkState->ArgCount = 0;
267db2bae30SDana Myers }
268db2bae30SDana Myers break;
269db2bae30SDana Myers
270db2bae30SDana Myers case AML_WHILE_OP:
271db2bae30SDana Myers
272db2bae30SDana Myers if (WalkState->ControlState)
273db2bae30SDana Myers {
274db2bae30SDana Myers WalkState->ControlState->Control.PackageEnd =
275db2bae30SDana Myers WalkState->ParserState.PkgEnd;
276db2bae30SDana Myers }
277db2bae30SDana Myers break;
278db2bae30SDana Myers
279db2bae30SDana Myers default:
280db2bae30SDana Myers
281db2bae30SDana Myers /* No action for all other opcodes */
282*385cc6b4SJerry Jelinek
283db2bae30SDana Myers break;
284db2bae30SDana Myers }
285db2bae30SDana Myers
286db2bae30SDana Myers break;
287db2bae30SDana Myers }
288db2bae30SDana Myers
289db2bae30SDana Myers return_ACPI_STATUS (AE_OK);
290db2bae30SDana Myers }
291db2bae30SDana Myers
292db2bae30SDana Myers
293db2bae30SDana Myers /*******************************************************************************
294db2bae30SDana Myers *
29557190917SDana Myers * FUNCTION: AcpiPsLinkModuleCode
29657190917SDana Myers *
29757190917SDana Myers * PARAMETERS: ParentOp - Parent parser op
29857190917SDana Myers * AmlStart - Pointer to the AML
29957190917SDana Myers * AmlLength - Length of executable AML
30057190917SDana Myers * OwnerId - OwnerId of module level code
30157190917SDana Myers *
30257190917SDana Myers * RETURN: None.
30357190917SDana Myers *
30457190917SDana Myers * DESCRIPTION: Wrap the module-level code with a method object and link the
30557190917SDana Myers * object to the global list. Note, the mutex field of the method
30657190917SDana Myers * object is used to link multiple module-level code objects.
30757190917SDana Myers *
30857190917SDana Myers ******************************************************************************/
30957190917SDana Myers
31057190917SDana Myers static void
AcpiPsLinkModuleCode(ACPI_PARSE_OBJECT * ParentOp,UINT8 * AmlStart,UINT32 AmlLength,ACPI_OWNER_ID OwnerId)31157190917SDana Myers AcpiPsLinkModuleCode (
31257190917SDana Myers ACPI_PARSE_OBJECT *ParentOp,
31357190917SDana Myers UINT8 *AmlStart,
31457190917SDana Myers UINT32 AmlLength,
31557190917SDana Myers ACPI_OWNER_ID OwnerId)
31657190917SDana Myers {
31757190917SDana Myers ACPI_OPERAND_OBJECT *Prev;
31857190917SDana Myers ACPI_OPERAND_OBJECT *Next;
31957190917SDana Myers ACPI_OPERAND_OBJECT *MethodObj;
32057190917SDana Myers ACPI_NAMESPACE_NODE *ParentNode;
32157190917SDana Myers
32257190917SDana Myers
323*385cc6b4SJerry Jelinek ACPI_FUNCTION_TRACE (PsLinkModuleCode);
324*385cc6b4SJerry Jelinek
325*385cc6b4SJerry Jelinek
32657190917SDana Myers /* Get the tail of the list */
32757190917SDana Myers
32857190917SDana Myers Prev = Next = AcpiGbl_ModuleCodeList;
32957190917SDana Myers while (Next)
33057190917SDana Myers {
33157190917SDana Myers Prev = Next;
33257190917SDana Myers Next = Next->Method.Mutex;
33357190917SDana Myers }
33457190917SDana Myers
33557190917SDana Myers /*
33657190917SDana Myers * Insert the module level code into the list. Merge it if it is
33757190917SDana Myers * adjacent to the previous element.
33857190917SDana Myers */
33957190917SDana Myers if (!Prev ||
34057190917SDana Myers ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart))
34157190917SDana Myers {
34257190917SDana Myers /* Create, initialize, and link a new temporary method object */
34357190917SDana Myers
34457190917SDana Myers MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
34557190917SDana Myers if (!MethodObj)
34657190917SDana Myers {
347*385cc6b4SJerry Jelinek return_VOID;
34857190917SDana Myers }
34957190917SDana Myers
350*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
351*385cc6b4SJerry Jelinek "Create/Link new code block: %p\n", MethodObj));
352*385cc6b4SJerry Jelinek
35357190917SDana Myers if (ParentOp->Common.Node)
35457190917SDana Myers {
35557190917SDana Myers ParentNode = ParentOp->Common.Node;
35657190917SDana Myers }
35757190917SDana Myers else
35857190917SDana Myers {
35957190917SDana Myers ParentNode = AcpiGbl_RootNode;
36057190917SDana Myers }
36157190917SDana Myers
36257190917SDana Myers MethodObj->Method.AmlStart = AmlStart;
36357190917SDana Myers MethodObj->Method.AmlLength = AmlLength;
36457190917SDana Myers MethodObj->Method.OwnerId = OwnerId;
36526f3cdf0SGordon Ross MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL;
36657190917SDana Myers
36757190917SDana Myers /*
36857190917SDana Myers * Save the parent node in NextObject. This is cheating, but we
36957190917SDana Myers * don't want to expand the method object.
37057190917SDana Myers */
37157190917SDana Myers MethodObj->Method.NextObject =
37257190917SDana Myers ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode);
37357190917SDana Myers
37457190917SDana Myers if (!Prev)
37557190917SDana Myers {
37657190917SDana Myers AcpiGbl_ModuleCodeList = MethodObj;
37757190917SDana Myers }
37857190917SDana Myers else
37957190917SDana Myers {
38057190917SDana Myers Prev->Method.Mutex = MethodObj;
38157190917SDana Myers }
38257190917SDana Myers }
38357190917SDana Myers else
38457190917SDana Myers {
385*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
386*385cc6b4SJerry Jelinek "Appending to existing code block: %p\n", Prev));
387*385cc6b4SJerry Jelinek
38857190917SDana Myers Prev->Method.AmlLength += AmlLength;
38957190917SDana Myers }
390*385cc6b4SJerry Jelinek
391*385cc6b4SJerry Jelinek return_VOID;
39257190917SDana Myers }
39357190917SDana Myers
394db2bae30SDana Myers /*******************************************************************************
395db2bae30SDana Myers *
396db2bae30SDana Myers * FUNCTION: AcpiPsParseLoop
397db2bae30SDana Myers *
398db2bae30SDana Myers * PARAMETERS: WalkState - Current state
399db2bae30SDana Myers *
400db2bae30SDana Myers * RETURN: Status
401db2bae30SDana Myers *
402db2bae30SDana Myers * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
403db2bae30SDana Myers * a tree of ops.
404db2bae30SDana Myers *
405db2bae30SDana Myers ******************************************************************************/
406db2bae30SDana Myers
407db2bae30SDana Myers ACPI_STATUS
AcpiPsParseLoop(ACPI_WALK_STATE * WalkState)408db2bae30SDana Myers AcpiPsParseLoop (
409db2bae30SDana Myers ACPI_WALK_STATE *WalkState)
410db2bae30SDana Myers {
411db2bae30SDana Myers ACPI_STATUS Status = AE_OK;
412db2bae30SDana Myers ACPI_PARSE_OBJECT *Op = NULL; /* current op */
413db2bae30SDana Myers ACPI_PARSE_STATE *ParserState;
414db2bae30SDana Myers UINT8 *AmlOpStart = NULL;
415db2bae30SDana Myers
416db2bae30SDana Myers
417db2bae30SDana Myers ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState);
418db2bae30SDana Myers
419db2bae30SDana Myers
420db2bae30SDana Myers if (WalkState->DescendingCallback == NULL)
421db2bae30SDana Myers {
422db2bae30SDana Myers return_ACPI_STATUS (AE_BAD_PARAMETER);
423db2bae30SDana Myers }
424db2bae30SDana Myers
425db2bae30SDana Myers ParserState = &WalkState->ParserState;
426db2bae30SDana Myers WalkState->ArgTypes = 0;
427db2bae30SDana Myers
428db2bae30SDana Myers #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
429db2bae30SDana Myers
430db2bae30SDana Myers if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
431db2bae30SDana Myers {
432db2bae30SDana Myers /* We are restarting a preempted control method */
433db2bae30SDana Myers
434db2bae30SDana Myers if (AcpiPsHasCompletedScope (ParserState))
435db2bae30SDana Myers {
436db2bae30SDana Myers /*
437db2bae30SDana Myers * We must check if a predicate to an IF or WHILE statement
438db2bae30SDana Myers * was just completed
439db2bae30SDana Myers */
440db2bae30SDana Myers if ((ParserState->Scope->ParseScope.Op) &&
441db2bae30SDana Myers ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
442db2bae30SDana Myers (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
443db2bae30SDana Myers (WalkState->ControlState) &&
444db2bae30SDana Myers (WalkState->ControlState->Common.State ==
445db2bae30SDana Myers ACPI_CONTROL_PREDICATE_EXECUTING))
446db2bae30SDana Myers {
447db2bae30SDana Myers /*
448db2bae30SDana Myers * A predicate was just completed, get the value of the
449db2bae30SDana Myers * predicate and branch based on that value
450db2bae30SDana Myers */
451db2bae30SDana Myers WalkState->Op = NULL;
452db2bae30SDana Myers Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
453db2bae30SDana Myers if (ACPI_FAILURE (Status) &&
454db2bae30SDana Myers ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
455db2bae30SDana Myers {
456db2bae30SDana Myers if (Status == AE_AML_NO_RETURN_VALUE)
457db2bae30SDana Myers {
458db2bae30SDana Myers ACPI_EXCEPTION ((AE_INFO, Status,
459db2bae30SDana Myers "Invoked method did not return a value"));
460db2bae30SDana Myers }
461db2bae30SDana Myers
462db2bae30SDana Myers ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed"));
463db2bae30SDana Myers return_ACPI_STATUS (Status);
464db2bae30SDana Myers }
465db2bae30SDana Myers
466db2bae30SDana Myers Status = AcpiPsNextParseState (WalkState, Op, Status);
467db2bae30SDana Myers }
468db2bae30SDana Myers
469db2bae30SDana Myers AcpiPsPopScope (ParserState, &Op,
470db2bae30SDana Myers &WalkState->ArgTypes, &WalkState->ArgCount);
471db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
472db2bae30SDana Myers }
473db2bae30SDana Myers else if (WalkState->PrevOp)
474db2bae30SDana Myers {
475db2bae30SDana Myers /* We were in the middle of an op */
476db2bae30SDana Myers
477db2bae30SDana Myers Op = WalkState->PrevOp;
478db2bae30SDana Myers WalkState->ArgTypes = WalkState->PrevArgTypes;
479db2bae30SDana Myers }
480db2bae30SDana Myers }
481db2bae30SDana Myers #endif
482db2bae30SDana Myers
483db2bae30SDana Myers /* Iterative parsing loop, while there is more AML to process: */
484db2bae30SDana Myers
485db2bae30SDana Myers while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
486db2bae30SDana Myers {
487db2bae30SDana Myers AmlOpStart = ParserState->Aml;
488db2bae30SDana Myers if (!Op)
489db2bae30SDana Myers {
490db2bae30SDana Myers Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op);
491db2bae30SDana Myers if (ACPI_FAILURE (Status))
492db2bae30SDana Myers {
493db2bae30SDana Myers if (Status == AE_CTRL_PARSE_CONTINUE)
494db2bae30SDana Myers {
495db2bae30SDana Myers continue;
496db2bae30SDana Myers }
497db2bae30SDana Myers
498db2bae30SDana Myers if (Status == AE_CTRL_PARSE_PENDING)
499db2bae30SDana Myers {
500db2bae30SDana Myers Status = AE_OK;
501db2bae30SDana Myers }
502db2bae30SDana Myers
503*385cc6b4SJerry Jelinek if (Status == AE_CTRL_TERMINATE)
504*385cc6b4SJerry Jelinek {
505*385cc6b4SJerry Jelinek return_ACPI_STATUS (Status);
506*385cc6b4SJerry Jelinek }
507*385cc6b4SJerry Jelinek
508db2bae30SDana Myers Status = AcpiPsCompleteOp (WalkState, &Op, Status);
509db2bae30SDana Myers if (ACPI_FAILURE (Status))
510db2bae30SDana Myers {
511db2bae30SDana Myers return_ACPI_STATUS (Status);
512db2bae30SDana Myers }
513db2bae30SDana Myers
514db2bae30SDana Myers continue;
515db2bae30SDana Myers }
516db2bae30SDana Myers
517*385cc6b4SJerry Jelinek AcpiExStartTraceOpcode (Op, WalkState);
518db2bae30SDana Myers }
519db2bae30SDana Myers
520db2bae30SDana Myers
521db2bae30SDana Myers /*
522db2bae30SDana Myers * Start ArgCount at zero because we don't know if there are
523db2bae30SDana Myers * any args yet
524db2bae30SDana Myers */
525db2bae30SDana Myers WalkState->ArgCount = 0;
526db2bae30SDana Myers
527db2bae30SDana Myers /* Are there any arguments that must be processed? */
528db2bae30SDana Myers
529db2bae30SDana Myers if (WalkState->ArgTypes)
530db2bae30SDana Myers {
531db2bae30SDana Myers /* Get arguments */
532db2bae30SDana Myers
533db2bae30SDana Myers Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op);
534db2bae30SDana Myers if (ACPI_FAILURE (Status))
535db2bae30SDana Myers {
536db2bae30SDana Myers Status = AcpiPsCompleteOp (WalkState, &Op, Status);
537db2bae30SDana Myers if (ACPI_FAILURE (Status))
538db2bae30SDana Myers {
539db2bae30SDana Myers return_ACPI_STATUS (Status);
540db2bae30SDana Myers }
541db2bae30SDana Myers
542db2bae30SDana Myers continue;
543db2bae30SDana Myers }
544db2bae30SDana Myers }
545db2bae30SDana Myers
546db2bae30SDana Myers /* Check for arguments that need to be processed */
547db2bae30SDana Myers
548db2bae30SDana Myers if (WalkState->ArgCount)
549db2bae30SDana Myers {
550db2bae30SDana Myers /*
551db2bae30SDana Myers * There are arguments (complex ones), push Op and
552db2bae30SDana Myers * prepare for argument
553db2bae30SDana Myers */
554db2bae30SDana Myers Status = AcpiPsPushScope (ParserState, Op,
555db2bae30SDana Myers WalkState->ArgTypes, WalkState->ArgCount);
556db2bae30SDana Myers if (ACPI_FAILURE (Status))
557db2bae30SDana Myers {
558db2bae30SDana Myers Status = AcpiPsCompleteOp (WalkState, &Op, Status);
559db2bae30SDana Myers if (ACPI_FAILURE (Status))
560db2bae30SDana Myers {
561db2bae30SDana Myers return_ACPI_STATUS (Status);
562db2bae30SDana Myers }
563db2bae30SDana Myers
564db2bae30SDana Myers continue;
565db2bae30SDana Myers }
566db2bae30SDana Myers
567db2bae30SDana Myers Op = NULL;
568db2bae30SDana Myers continue;
569db2bae30SDana Myers }
570db2bae30SDana Myers
571db2bae30SDana Myers /*
572db2bae30SDana Myers * All arguments have been processed -- Op is complete,
573db2bae30SDana Myers * prepare for next
574db2bae30SDana Myers */
575db2bae30SDana Myers WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
576db2bae30SDana Myers if (WalkState->OpInfo->Flags & AML_NAMED)
577db2bae30SDana Myers {
578db2bae30SDana Myers if (Op->Common.AmlOpcode == AML_REGION_OP ||
579db2bae30SDana Myers Op->Common.AmlOpcode == AML_DATA_REGION_OP)
580db2bae30SDana Myers {
581db2bae30SDana Myers /*
582db2bae30SDana Myers * Skip parsing of control method or opregion body,
583db2bae30SDana Myers * because we don't have enough info in the first pass
584db2bae30SDana Myers * to parse them correctly.
585db2bae30SDana Myers *
586db2bae30SDana Myers * Completed parsing an OpRegion declaration, we now
587db2bae30SDana Myers * know the length.
588db2bae30SDana Myers */
589db2bae30SDana Myers Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
590db2bae30SDana Myers }
591db2bae30SDana Myers }
592db2bae30SDana Myers
593db2bae30SDana Myers if (WalkState->OpInfo->Flags & AML_CREATE)
594db2bae30SDana Myers {
595db2bae30SDana Myers /*
596db2bae30SDana Myers * Backup to beginning of CreateXXXfield declaration (1 for
597db2bae30SDana Myers * Opcode)
598db2bae30SDana Myers *
599db2bae30SDana Myers * BodyLength is unknown until we parse the body
600db2bae30SDana Myers */
601db2bae30SDana Myers Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
602db2bae30SDana Myers }
603db2bae30SDana Myers
604db2bae30SDana Myers if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
605db2bae30SDana Myers {
606db2bae30SDana Myers /*
607db2bae30SDana Myers * Backup to beginning of BankField declaration
608db2bae30SDana Myers *
609db2bae30SDana Myers * BodyLength is unknown until we parse the body
610db2bae30SDana Myers */
611db2bae30SDana Myers Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
612db2bae30SDana Myers }
613db2bae30SDana Myers
614db2bae30SDana Myers /* This op complete, notify the dispatcher */
615db2bae30SDana Myers
616db2bae30SDana Myers if (WalkState->AscendingCallback != NULL)
617db2bae30SDana Myers {
618db2bae30SDana Myers WalkState->Op = Op;
619db2bae30SDana Myers WalkState->Opcode = Op->Common.AmlOpcode;
620db2bae30SDana Myers
621db2bae30SDana Myers Status = WalkState->AscendingCallback (WalkState);
622db2bae30SDana Myers Status = AcpiPsNextParseState (WalkState, Op, Status);
623db2bae30SDana Myers if (Status == AE_CTRL_PENDING)
624db2bae30SDana Myers {
625db2bae30SDana Myers Status = AE_OK;
626db2bae30SDana Myers }
627db2bae30SDana Myers }
628db2bae30SDana Myers
629db2bae30SDana Myers Status = AcpiPsCompleteOp (WalkState, &Op, Status);
630db2bae30SDana Myers if (ACPI_FAILURE (Status))
631db2bae30SDana Myers {
632db2bae30SDana Myers return_ACPI_STATUS (Status);
633db2bae30SDana Myers }
634db2bae30SDana Myers
635db2bae30SDana Myers } /* while ParserState->Aml */
636db2bae30SDana Myers
637db2bae30SDana Myers Status = AcpiPsCompleteFinalOp (WalkState, Op, Status);
638db2bae30SDana Myers return_ACPI_STATUS (Status);
639db2bae30SDana Myers }
640