xref: /netbsd-src/sys/external/bsd/acpica/dist/parser/psloop.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
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