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 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 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 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