128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho *
328c506b8Sjruoho * Module Name: psloop - Main AML parse loop
428c506b8Sjruoho *
528c506b8Sjruoho *****************************************************************************/
628c506b8Sjruoho
7124f4c82Sjruoho /*
8*046a2985Schristos * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho * All rights reserved.
1028c506b8Sjruoho *
11124f4c82Sjruoho * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho * modification, are permitted provided that the following conditions
13124f4c82Sjruoho * are met:
14124f4c82Sjruoho * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho * notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho * without modification.
17124f4c82Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho * including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho * binary redistribution.
22124f4c82Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho * of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho * from this software without specific prior written permission.
2528c506b8Sjruoho *
26124f4c82Sjruoho * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho * Software Foundation.
2928c506b8Sjruoho *
30124f4c82Sjruoho * NO WARRANTY
31124f4c82Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho */
4328c506b8Sjruoho
4428c506b8Sjruoho /*
4528c506b8Sjruoho * Parse the AML and build an operation tree as most interpreters, (such as
4628c506b8Sjruoho * Perl) do. Parsing is done by hand rather than with a YACC generated parser
4728c506b8Sjruoho * to tightly constrain stack and dynamic memory usage. Parsing is kept
4828c506b8Sjruoho * flexible and the code fairly compact by parsing based on a list of AML
4928c506b8Sjruoho * opcode templates in AmlOpInfo[].
5028c506b8Sjruoho */
5128c506b8Sjruoho
5228c506b8Sjruoho #include "acpi.h"
5328c506b8Sjruoho #include "accommon.h"
54c72da027Schristos #include "acinterp.h"
5528c506b8Sjruoho #include "acparser.h"
5628c506b8Sjruoho #include "acdispat.h"
5728c506b8Sjruoho #include "amlcode.h"
58835858a6Schristos #include "acconvert.h"
5947315524Schristos #include "acnamesp.h"
6028c506b8Sjruoho
6128c506b8Sjruoho #define _COMPONENT ACPI_PARSER
6228c506b8Sjruoho ACPI_MODULE_NAME ("psloop")
6328c506b8Sjruoho
6428c506b8Sjruoho
6528c506b8Sjruoho /* Local prototypes */
6628c506b8Sjruoho
6728c506b8Sjruoho static ACPI_STATUS
6828c506b8Sjruoho AcpiPsGetArguments (
6928c506b8Sjruoho ACPI_WALK_STATE *WalkState,
7028c506b8Sjruoho UINT8 *AmlOpStart,
7128c506b8Sjruoho ACPI_PARSE_OBJECT *Op);
7228c506b8Sjruoho
7328c506b8Sjruoho
7428c506b8Sjruoho /*******************************************************************************
7528c506b8Sjruoho *
7628c506b8Sjruoho * FUNCTION: AcpiPsGetArguments
7728c506b8Sjruoho *
7828c506b8Sjruoho * PARAMETERS: WalkState - Current state
7928c506b8Sjruoho * AmlOpStart - Op start in AML
8028c506b8Sjruoho * Op - Current Op
8128c506b8Sjruoho *
8228c506b8Sjruoho * RETURN: Status
8328c506b8Sjruoho *
8428c506b8Sjruoho * DESCRIPTION: Get arguments for passed Op.
8528c506b8Sjruoho *
8628c506b8Sjruoho ******************************************************************************/
8728c506b8Sjruoho
8828c506b8Sjruoho static ACPI_STATUS
AcpiPsGetArguments(ACPI_WALK_STATE * WalkState,UINT8 * AmlOpStart,ACPI_PARSE_OBJECT * Op)8928c506b8Sjruoho AcpiPsGetArguments (
9028c506b8Sjruoho ACPI_WALK_STATE *WalkState,
9128c506b8Sjruoho UINT8 *AmlOpStart,
9228c506b8Sjruoho ACPI_PARSE_OBJECT *Op)
9328c506b8Sjruoho {
9428c506b8Sjruoho ACPI_STATUS Status = AE_OK;
9528c506b8Sjruoho ACPI_PARSE_OBJECT *Arg = NULL;
9628c506b8Sjruoho
9728c506b8Sjruoho
9828c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState);
9928c506b8Sjruoho
10028c506b8Sjruoho
1010b89cdedSchristos ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
1020b89cdedSchristos "Get arguments for opcode [%s]\n", Op->Common.AmlOpName));
1030b89cdedSchristos
10428c506b8Sjruoho switch (Op->Common.AmlOpcode)
10528c506b8Sjruoho {
10628c506b8Sjruoho case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
10728c506b8Sjruoho case AML_WORD_OP: /* AML_WORDDATA_ARG */
10828c506b8Sjruoho case AML_DWORD_OP: /* AML_DWORDATA_ARG */
10928c506b8Sjruoho case AML_QWORD_OP: /* AML_QWORDATA_ARG */
11028c506b8Sjruoho case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
11128c506b8Sjruoho
11228c506b8Sjruoho /* Fill in constant or string argument directly */
11328c506b8Sjruoho
11428c506b8Sjruoho AcpiPsGetNextSimpleArg (&(WalkState->ParserState),
11528c506b8Sjruoho GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
11628c506b8Sjruoho break;
11728c506b8Sjruoho
11828c506b8Sjruoho case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
11928c506b8Sjruoho
12071e38f1dSchristos Status = AcpiPsGetNextNamepath (WalkState,
12171e38f1dSchristos &(WalkState->ParserState), Op, ACPI_POSSIBLE_METHOD_CALL);
12228c506b8Sjruoho if (ACPI_FAILURE (Status))
12328c506b8Sjruoho {
12428c506b8Sjruoho return_ACPI_STATUS (Status);
12528c506b8Sjruoho }
12628c506b8Sjruoho
12728c506b8Sjruoho WalkState->ArgTypes = 0;
12828c506b8Sjruoho break;
12928c506b8Sjruoho
13028c506b8Sjruoho default:
13128c506b8Sjruoho /*
13228c506b8Sjruoho * Op is not a constant or string, append each argument to the Op
13328c506b8Sjruoho */
13471e38f1dSchristos while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
13571e38f1dSchristos !WalkState->ArgCount)
13628c506b8Sjruoho {
137c72da027Schristos WalkState->Aml = WalkState->ParserState.Aml;
13828c506b8Sjruoho
139835858a6Schristos switch (Op->Common.AmlOpcode)
140835858a6Schristos {
141835858a6Schristos case AML_METHOD_OP:
142835858a6Schristos case AML_BUFFER_OP:
143835858a6Schristos case AML_PACKAGE_OP:
144835858a6Schristos case AML_VARIABLE_PACKAGE_OP:
145835858a6Schristos case AML_WHILE_OP:
146835858a6Schristos
147835858a6Schristos break;
148835858a6Schristos
149835858a6Schristos default:
150835858a6Schristos
151835858a6Schristos ASL_CV_CAPTURE_COMMENTS (WalkState);
152835858a6Schristos break;
153835858a6Schristos }
154835858a6Schristos
15528c506b8Sjruoho Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
15628c506b8Sjruoho GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
15728c506b8Sjruoho if (ACPI_FAILURE (Status))
15828c506b8Sjruoho {
15928c506b8Sjruoho return_ACPI_STATUS (Status);
16028c506b8Sjruoho }
16128c506b8Sjruoho
16228c506b8Sjruoho if (Arg)
16328c506b8Sjruoho {
16428c506b8Sjruoho AcpiPsAppendArg (Op, Arg);
16528c506b8Sjruoho }
16628c506b8Sjruoho
16728c506b8Sjruoho INCREMENT_ARG_LIST (WalkState->ArgTypes);
16828c506b8Sjruoho }
16928c506b8Sjruoho
17089b8eb6cSchristos ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
171062782b3Schristos "Final argument count: %8.8X pass %u\n",
17289b8eb6cSchristos WalkState->ArgCount, WalkState->PassNumber));
17328c506b8Sjruoho
17428c506b8Sjruoho /* Special processing for certain opcodes */
17528c506b8Sjruoho
17628c506b8Sjruoho switch (Op->Common.AmlOpcode)
17728c506b8Sjruoho {
17828c506b8Sjruoho case AML_METHOD_OP:
17928c506b8Sjruoho /*
18028c506b8Sjruoho * Skip parsing of control method because we don't have enough
18128c506b8Sjruoho * info in the first pass to parse it correctly.
18228c506b8Sjruoho *
18328c506b8Sjruoho * Save the length and address of the body
18428c506b8Sjruoho */
18528c506b8Sjruoho Op->Named.Data = WalkState->ParserState.Aml;
18628c506b8Sjruoho Op->Named.Length = (UINT32)
18728c506b8Sjruoho (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml);
18828c506b8Sjruoho
18928c506b8Sjruoho /* Skip body of method */
19028c506b8Sjruoho
19128c506b8Sjruoho WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
19228c506b8Sjruoho WalkState->ArgCount = 0;
19328c506b8Sjruoho break;
19428c506b8Sjruoho
19528c506b8Sjruoho case AML_BUFFER_OP:
19628c506b8Sjruoho case AML_PACKAGE_OP:
197835858a6Schristos case AML_VARIABLE_PACKAGE_OP:
19828c506b8Sjruoho
19928c506b8Sjruoho if ((Op->Common.Parent) &&
20028c506b8Sjruoho (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
20128c506b8Sjruoho (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
20228c506b8Sjruoho {
20389b8eb6cSchristos ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
20489b8eb6cSchristos "Setup Package/Buffer: Pass %u, AML Ptr: %p\n",
20589b8eb6cSchristos WalkState->PassNumber, AmlOpStart));
20689b8eb6cSchristos
20728c506b8Sjruoho /*
20828c506b8Sjruoho * Skip parsing of Buffers and Packages because we don't have
20928c506b8Sjruoho * enough info in the first pass to parse them correctly.
21028c506b8Sjruoho */
21128c506b8Sjruoho Op->Named.Data = AmlOpStart;
21228c506b8Sjruoho Op->Named.Length = (UINT32)
21328c506b8Sjruoho (WalkState->ParserState.PkgEnd - AmlOpStart);
21428c506b8Sjruoho
21528c506b8Sjruoho /* Skip body */
21628c506b8Sjruoho
21728c506b8Sjruoho WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
21828c506b8Sjruoho WalkState->ArgCount = 0;
21928c506b8Sjruoho }
22028c506b8Sjruoho break;
22128c506b8Sjruoho
22228c506b8Sjruoho case AML_WHILE_OP:
22328c506b8Sjruoho
22428c506b8Sjruoho if (WalkState->ControlState)
22528c506b8Sjruoho {
22628c506b8Sjruoho WalkState->ControlState->Control.PackageEnd =
22728c506b8Sjruoho WalkState->ParserState.PkgEnd;
22828c506b8Sjruoho }
22928c506b8Sjruoho break;
23028c506b8Sjruoho
23128c506b8Sjruoho default:
23228c506b8Sjruoho
23328c506b8Sjruoho /* No action for all other opcodes */
234ff4a156dSchristos
23528c506b8Sjruoho break;
23628c506b8Sjruoho }
23728c506b8Sjruoho
23828c506b8Sjruoho break;
23928c506b8Sjruoho }
24028c506b8Sjruoho
24128c506b8Sjruoho return_ACPI_STATUS (AE_OK);
24228c506b8Sjruoho }
24328c506b8Sjruoho
24428c506b8Sjruoho
24528c506b8Sjruoho /*******************************************************************************
24628c506b8Sjruoho *
24728c506b8Sjruoho * FUNCTION: AcpiPsParseLoop
24828c506b8Sjruoho *
24928c506b8Sjruoho * PARAMETERS: WalkState - Current state
25028c506b8Sjruoho *
25128c506b8Sjruoho * RETURN: Status
25228c506b8Sjruoho *
25328c506b8Sjruoho * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
25428c506b8Sjruoho * a tree of ops.
25528c506b8Sjruoho *
25628c506b8Sjruoho ******************************************************************************/
25728c506b8Sjruoho
25828c506b8Sjruoho ACPI_STATUS
AcpiPsParseLoop(ACPI_WALK_STATE * WalkState)25928c506b8Sjruoho AcpiPsParseLoop (
26028c506b8Sjruoho ACPI_WALK_STATE *WalkState)
26128c506b8Sjruoho {
26228c506b8Sjruoho ACPI_STATUS Status = AE_OK;
26328c506b8Sjruoho ACPI_PARSE_OBJECT *Op = NULL; /* current op */
26428c506b8Sjruoho ACPI_PARSE_STATE *ParserState;
26528c506b8Sjruoho UINT8 *AmlOpStart = NULL;
2664c4e8184Schristos UINT8 OpcodeLength;
26728c506b8Sjruoho
26828c506b8Sjruoho
26928c506b8Sjruoho ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState);
27028c506b8Sjruoho
27128c506b8Sjruoho
27228c506b8Sjruoho if (WalkState->DescendingCallback == NULL)
27328c506b8Sjruoho {
27428c506b8Sjruoho return_ACPI_STATUS (AE_BAD_PARAMETER);
27528c506b8Sjruoho }
27628c506b8Sjruoho
27728c506b8Sjruoho ParserState = &WalkState->ParserState;
27828c506b8Sjruoho WalkState->ArgTypes = 0;
27928c506b8Sjruoho
2804c4e8184Schristos #ifndef ACPI_CONSTANT_EVAL_ONLY
28128c506b8Sjruoho
28228c506b8Sjruoho if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
28328c506b8Sjruoho {
28428c506b8Sjruoho /* We are restarting a preempted control method */
28528c506b8Sjruoho
28628c506b8Sjruoho if (AcpiPsHasCompletedScope (ParserState))
28728c506b8Sjruoho {
28828c506b8Sjruoho /*
28928c506b8Sjruoho * We must check if a predicate to an IF or WHILE statement
29028c506b8Sjruoho * was just completed
29128c506b8Sjruoho */
29228c506b8Sjruoho if ((ParserState->Scope->ParseScope.Op) &&
29328c506b8Sjruoho ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
29428c506b8Sjruoho (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
29528c506b8Sjruoho (WalkState->ControlState) &&
29628c506b8Sjruoho (WalkState->ControlState->Common.State ==
29728c506b8Sjruoho ACPI_CONTROL_PREDICATE_EXECUTING))
29828c506b8Sjruoho {
29928c506b8Sjruoho /*
30028c506b8Sjruoho * A predicate was just completed, get the value of the
30128c506b8Sjruoho * predicate and branch based on that value
30228c506b8Sjruoho */
30328c506b8Sjruoho WalkState->Op = NULL;
30428c506b8Sjruoho Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
30546a330b4Schristos if (ACPI_FAILURE (Status) && !ACPI_CNTL_EXCEPTION (Status))
30628c506b8Sjruoho {
30728c506b8Sjruoho if (Status == AE_AML_NO_RETURN_VALUE)
30828c506b8Sjruoho {
30928c506b8Sjruoho ACPI_EXCEPTION ((AE_INFO, Status,
31028c506b8Sjruoho "Invoked method did not return a value"));
31128c506b8Sjruoho }
31228c506b8Sjruoho
31328c506b8Sjruoho ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed"));
31428c506b8Sjruoho return_ACPI_STATUS (Status);
31528c506b8Sjruoho }
31628c506b8Sjruoho
31728c506b8Sjruoho Status = AcpiPsNextParseState (WalkState, Op, Status);
31828c506b8Sjruoho }
31928c506b8Sjruoho
32028c506b8Sjruoho AcpiPsPopScope (ParserState, &Op,
32128c506b8Sjruoho &WalkState->ArgTypes, &WalkState->ArgCount);
32228c506b8Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
32328c506b8Sjruoho }
32428c506b8Sjruoho else if (WalkState->PrevOp)
32528c506b8Sjruoho {
32628c506b8Sjruoho /* We were in the middle of an op */
32728c506b8Sjruoho
32828c506b8Sjruoho Op = WalkState->PrevOp;
32928c506b8Sjruoho WalkState->ArgTypes = WalkState->PrevArgTypes;
33028c506b8Sjruoho }
33128c506b8Sjruoho }
33228c506b8Sjruoho #endif
33328c506b8Sjruoho
33428c506b8Sjruoho /* Iterative parsing loop, while there is more AML to process: */
33528c506b8Sjruoho
33628c506b8Sjruoho while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
33728c506b8Sjruoho {
338835858a6Schristos ASL_CV_CAPTURE_COMMENTS (WalkState);
339835858a6Schristos
34028c506b8Sjruoho AmlOpStart = ParserState->Aml;
34128c506b8Sjruoho if (!Op)
34228c506b8Sjruoho {
34328c506b8Sjruoho Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op);
34428c506b8Sjruoho if (ACPI_FAILURE (Status))
34528c506b8Sjruoho {
34647315524Schristos /*
34747315524Schristos * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by
34847315524Schristos * executing it as a control method. However, if we encounter
34947315524Schristos * an error while loading the table, we need to keep trying to
35047315524Schristos * load the table rather than aborting the table load. Set the
35147315524Schristos * status to AE_OK to proceed with the table load.
35247315524Schristos */
35347315524Schristos if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) &&
3544c4e8184Schristos ((Status == AE_ALREADY_EXISTS) || (Status == AE_NOT_FOUND)))
35547315524Schristos {
35647315524Schristos Status = AE_OK;
35747315524Schristos }
35828c506b8Sjruoho if (Status == AE_CTRL_PARSE_CONTINUE)
35928c506b8Sjruoho {
36028c506b8Sjruoho continue;
36128c506b8Sjruoho }
36228c506b8Sjruoho
36328c506b8Sjruoho if (Status == AE_CTRL_PARSE_PENDING)
36428c506b8Sjruoho {
36528c506b8Sjruoho Status = AE_OK;
36628c506b8Sjruoho }
36728c506b8Sjruoho
368460301d4Schristos if (Status == AE_CTRL_TERMINATE)
369460301d4Schristos {
370460301d4Schristos return_ACPI_STATUS (Status);
371460301d4Schristos }
372460301d4Schristos
37328c506b8Sjruoho Status = AcpiPsCompleteOp (WalkState, &Op, Status);
37428c506b8Sjruoho if (ACPI_FAILURE (Status))
37528c506b8Sjruoho {
37628c506b8Sjruoho return_ACPI_STATUS (Status);
37728c506b8Sjruoho }
37847315524Schristos if (AcpiNsOpensScope (
37947315524Schristos AcpiPsGetOpcodeInfo (WalkState->Opcode)->ObjectType))
38047315524Schristos {
38147315524Schristos /*
38247315524Schristos * If the scope/device op fails to parse, skip the body of
38347315524Schristos * the scope op because the parse failure indicates that
38447315524Schristos * the device may not exist.
38547315524Schristos */
3864c4e8184Schristos ACPI_INFO (("Skipping parse of AML opcode: %s (0x%4.4X)",
3874c4e8184Schristos AcpiPsGetOpcodeName (WalkState->Opcode), WalkState->Opcode));
3884c4e8184Schristos
3894c4e8184Schristos /*
3904c4e8184Schristos * Determine the opcode length before skipping the opcode.
3914c4e8184Schristos * An opcode can be 1 byte or 2 bytes in length.
3924c4e8184Schristos */
3934c4e8184Schristos OpcodeLength = 1;
3944c4e8184Schristos if ((WalkState->Opcode & 0xFF00) == AML_EXTENDED_OPCODE)
3954c4e8184Schristos {
3964c4e8184Schristos OpcodeLength = 2;
3974c4e8184Schristos }
3984c4e8184Schristos WalkState->ParserState.Aml = WalkState->Aml + OpcodeLength;
3994c4e8184Schristos
40047315524Schristos WalkState->ParserState.Aml =
40147315524Schristos AcpiPsGetNextPackageEnd(&WalkState->ParserState);
40247315524Schristos WalkState->Aml = WalkState->ParserState.Aml;
40347315524Schristos }
40428c506b8Sjruoho
40528c506b8Sjruoho continue;
40628c506b8Sjruoho }
40728c506b8Sjruoho
408c72da027Schristos AcpiExStartTraceOpcode (Op, WalkState);
40928c506b8Sjruoho }
41028c506b8Sjruoho
41128c506b8Sjruoho /*
41228c506b8Sjruoho * Start ArgCount at zero because we don't know if there are
41328c506b8Sjruoho * any args yet
41428c506b8Sjruoho */
41528c506b8Sjruoho WalkState->ArgCount = 0;
41628c506b8Sjruoho
417835858a6Schristos switch (Op->Common.AmlOpcode)
418835858a6Schristos {
419835858a6Schristos case AML_BYTE_OP:
420835858a6Schristos case AML_WORD_OP:
421835858a6Schristos case AML_DWORD_OP:
422835858a6Schristos case AML_QWORD_OP:
423835858a6Schristos
424835858a6Schristos break;
425835858a6Schristos
426835858a6Schristos default:
427835858a6Schristos
428835858a6Schristos ASL_CV_CAPTURE_COMMENTS (WalkState);
429835858a6Schristos break;
430835858a6Schristos }
431835858a6Schristos
43228c506b8Sjruoho /* Are there any arguments that must be processed? */
43328c506b8Sjruoho
43428c506b8Sjruoho if (WalkState->ArgTypes)
43528c506b8Sjruoho {
43628c506b8Sjruoho /* Get arguments */
43728c506b8Sjruoho
43828c506b8Sjruoho Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op);
43928c506b8Sjruoho if (ACPI_FAILURE (Status))
44028c506b8Sjruoho {
44128c506b8Sjruoho Status = AcpiPsCompleteOp (WalkState, &Op, Status);
44228c506b8Sjruoho if (ACPI_FAILURE (Status))
44328c506b8Sjruoho {
44428c506b8Sjruoho return_ACPI_STATUS (Status);
44528c506b8Sjruoho }
44647315524Schristos if ((WalkState->ControlState) &&
44747315524Schristos ((WalkState->ControlState->Control.Opcode == AML_IF_OP) ||
44847315524Schristos (WalkState->ControlState->Control.Opcode == AML_WHILE_OP)))
44947315524Schristos {
45047315524Schristos /*
45147315524Schristos * If the if/while op fails to parse, we will skip parsing
45247315524Schristos * the body of the op.
45347315524Schristos */
45447315524Schristos ParserState->Aml =
45547315524Schristos WalkState->ControlState->Control.AmlPredicateStart + 1;
45647315524Schristos ParserState->Aml =
45747315524Schristos AcpiPsGetNextPackageEnd (ParserState);
45847315524Schristos WalkState->Aml = ParserState->Aml;
45928c506b8Sjruoho
46047315524Schristos ACPI_ERROR ((AE_INFO, "Skipping While/If block"));
46147315524Schristos if (*WalkState->Aml == AML_ELSE_OP)
46247315524Schristos {
46347315524Schristos ACPI_ERROR ((AE_INFO, "Skipping Else block"));
46447315524Schristos WalkState->ParserState.Aml = WalkState->Aml + 1;
46547315524Schristos WalkState->ParserState.Aml =
46647315524Schristos AcpiPsGetNextPackageEnd (ParserState);
46747315524Schristos WalkState->Aml = ParserState->Aml;
46847315524Schristos }
46947315524Schristos ACPI_FREE(AcpiUtPopGenericState (&WalkState->ControlState));
47047315524Schristos }
47147315524Schristos Op = NULL;
47228c506b8Sjruoho continue;
47328c506b8Sjruoho }
47428c506b8Sjruoho }
47528c506b8Sjruoho
47628c506b8Sjruoho /* Check for arguments that need to be processed */
47728c506b8Sjruoho
47889b8eb6cSchristos ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
479062782b3Schristos "Parseloop: argument count: %8.8X\n", WalkState->ArgCount));
48089b8eb6cSchristos
48128c506b8Sjruoho if (WalkState->ArgCount)
48228c506b8Sjruoho {
48328c506b8Sjruoho /*
48428c506b8Sjruoho * There are arguments (complex ones), push Op and
48528c506b8Sjruoho * prepare for argument
48628c506b8Sjruoho */
48728c506b8Sjruoho Status = AcpiPsPushScope (ParserState, Op,
48828c506b8Sjruoho WalkState->ArgTypes, WalkState->ArgCount);
48928c506b8Sjruoho if (ACPI_FAILURE (Status))
49028c506b8Sjruoho {
49128c506b8Sjruoho Status = AcpiPsCompleteOp (WalkState, &Op, Status);
49228c506b8Sjruoho if (ACPI_FAILURE (Status))
49328c506b8Sjruoho {
49428c506b8Sjruoho return_ACPI_STATUS (Status);
49528c506b8Sjruoho }
49628c506b8Sjruoho
49728c506b8Sjruoho continue;
49828c506b8Sjruoho }
49928c506b8Sjruoho
50028c506b8Sjruoho Op = NULL;
50128c506b8Sjruoho continue;
50228c506b8Sjruoho }
50328c506b8Sjruoho
50428c506b8Sjruoho /*
50528c506b8Sjruoho * All arguments have been processed -- Op is complete,
50628c506b8Sjruoho * prepare for next
50728c506b8Sjruoho */
50828c506b8Sjruoho WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
50928c506b8Sjruoho if (WalkState->OpInfo->Flags & AML_NAMED)
51028c506b8Sjruoho {
51128c506b8Sjruoho if (Op->Common.AmlOpcode == AML_REGION_OP ||
51228c506b8Sjruoho Op->Common.AmlOpcode == AML_DATA_REGION_OP)
51328c506b8Sjruoho {
51428c506b8Sjruoho /*
51528c506b8Sjruoho * Skip parsing of control method or opregion body,
51628c506b8Sjruoho * because we don't have enough info in the first pass
51728c506b8Sjruoho * to parse them correctly.
51828c506b8Sjruoho *
51928c506b8Sjruoho * Completed parsing an OpRegion declaration, we now
52028c506b8Sjruoho * know the length.
52128c506b8Sjruoho */
52228c506b8Sjruoho Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
52328c506b8Sjruoho }
52428c506b8Sjruoho }
52528c506b8Sjruoho
52628c506b8Sjruoho if (WalkState->OpInfo->Flags & AML_CREATE)
52728c506b8Sjruoho {
52828c506b8Sjruoho /*
52928c506b8Sjruoho * Backup to beginning of CreateXXXfield declaration (1 for
53028c506b8Sjruoho * Opcode)
53128c506b8Sjruoho *
53228c506b8Sjruoho * BodyLength is unknown until we parse the body
53328c506b8Sjruoho */
53428c506b8Sjruoho Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
53528c506b8Sjruoho }
53628c506b8Sjruoho
53728c506b8Sjruoho if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
53828c506b8Sjruoho {
53928c506b8Sjruoho /*
54028c506b8Sjruoho * Backup to beginning of BankField declaration
54128c506b8Sjruoho *
54228c506b8Sjruoho * BodyLength is unknown until we parse the body
54328c506b8Sjruoho */
54428c506b8Sjruoho Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
54528c506b8Sjruoho }
54628c506b8Sjruoho
54728c506b8Sjruoho /* This op complete, notify the dispatcher */
54828c506b8Sjruoho
54928c506b8Sjruoho if (WalkState->AscendingCallback != NULL)
55028c506b8Sjruoho {
55128c506b8Sjruoho WalkState->Op = Op;
55228c506b8Sjruoho WalkState->Opcode = Op->Common.AmlOpcode;
55328c506b8Sjruoho
55428c506b8Sjruoho Status = WalkState->AscendingCallback (WalkState);
55528c506b8Sjruoho Status = AcpiPsNextParseState (WalkState, Op, Status);
55628c506b8Sjruoho if (Status == AE_CTRL_PENDING)
55728c506b8Sjruoho {
55828c506b8Sjruoho Status = AE_OK;
55928c506b8Sjruoho }
56047315524Schristos else if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) &&
56147315524Schristos (ACPI_AML_EXCEPTION(Status) || Status == AE_ALREADY_EXISTS ||
56247315524Schristos Status == AE_NOT_FOUND))
56347315524Schristos {
56447315524Schristos /*
56547315524Schristos * ACPI_PARSE_MODULE_LEVEL flag means that we are currently
56647315524Schristos * loading a table by executing it as a control method.
56747315524Schristos * However, if we encounter an error while loading the table,
56847315524Schristos * we need to keep trying to load the table rather than
56947315524Schristos * aborting the table load (setting the status to AE_OK
57047315524Schristos * continues the table load). If we get a failure at this
57147315524Schristos * point, it means that the dispatcher got an error while
57247315524Schristos * trying to execute the Op.
57347315524Schristos */
57447315524Schristos Status = AE_OK;
57547315524Schristos }
57628c506b8Sjruoho }
57728c506b8Sjruoho
57828c506b8Sjruoho Status = AcpiPsCompleteOp (WalkState, &Op, Status);
57928c506b8Sjruoho if (ACPI_FAILURE (Status))
58028c506b8Sjruoho {
58128c506b8Sjruoho return_ACPI_STATUS (Status);
58228c506b8Sjruoho }
58328c506b8Sjruoho
58428c506b8Sjruoho } /* while ParserState->Aml */
58528c506b8Sjruoho
58628c506b8Sjruoho Status = AcpiPsCompleteFinalOp (WalkState, Op, Status);
58728c506b8Sjruoho return_ACPI_STATUS (Status);
58828c506b8Sjruoho }
589