1db2bae30SDana Myers /****************************************************************************** 2db2bae30SDana Myers * 3db2bae30SDana Myers * Module Name: psparse - Parser top level AML parse routines 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, 46db2bae30SDana Myers * like Perl, do. Parsing is done by hand rather than with a YACC 47db2bae30SDana Myers * generated parser to tightly constrain stack and dynamic memory 48db2bae30SDana Myers * usage. At the same time, parsing is kept flexible and the code 49db2bae30SDana Myers * fairly compact by parsing based on a list of AML opcode 50db2bae30SDana Myers * templates in AmlOpInfo[] 51db2bae30SDana Myers */ 52db2bae30SDana Myers 53db2bae30SDana Myers #include "acpi.h" 54aa2aa9a6SDana Myers #include "accommon.h" 55db2bae30SDana Myers #include "acparser.h" 56db2bae30SDana Myers #include "acdispat.h" 57db2bae30SDana Myers #include "amlcode.h" 58db2bae30SDana Myers #include "acinterp.h" 59db2bae30SDana Myers 60db2bae30SDana Myers #define _COMPONENT ACPI_PARSER 61db2bae30SDana Myers ACPI_MODULE_NAME ("psparse") 62db2bae30SDana Myers 63db2bae30SDana Myers 64db2bae30SDana Myers /******************************************************************************* 65db2bae30SDana Myers * 66db2bae30SDana Myers * FUNCTION: AcpiPsGetOpcodeSize 67db2bae30SDana Myers * 68db2bae30SDana Myers * PARAMETERS: Opcode - An AML opcode 69db2bae30SDana Myers * 70db2bae30SDana Myers * RETURN: Size of the opcode, in bytes (1 or 2) 71db2bae30SDana Myers * 72db2bae30SDana Myers * DESCRIPTION: Get the size of the current opcode. 73db2bae30SDana Myers * 74db2bae30SDana Myers ******************************************************************************/ 75db2bae30SDana Myers 76db2bae30SDana Myers UINT32 77db2bae30SDana Myers AcpiPsGetOpcodeSize ( 78db2bae30SDana Myers UINT32 Opcode) 79db2bae30SDana Myers { 80db2bae30SDana Myers 81db2bae30SDana Myers /* Extended (2-byte) opcode if > 255 */ 82db2bae30SDana Myers 83db2bae30SDana Myers if (Opcode > 0x00FF) 84db2bae30SDana Myers { 85db2bae30SDana Myers return (2); 86db2bae30SDana Myers } 87db2bae30SDana Myers 88db2bae30SDana Myers /* Otherwise, just a single byte opcode */ 89db2bae30SDana Myers 90db2bae30SDana Myers return (1); 91db2bae30SDana Myers } 92db2bae30SDana Myers 93db2bae30SDana Myers 94db2bae30SDana Myers /******************************************************************************* 95db2bae30SDana Myers * 96db2bae30SDana Myers * FUNCTION: AcpiPsPeekOpcode 97db2bae30SDana Myers * 98db2bae30SDana Myers * PARAMETERS: ParserState - A parser state object 99db2bae30SDana Myers * 100db2bae30SDana Myers * RETURN: Next AML opcode 101db2bae30SDana Myers * 102db2bae30SDana Myers * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) 103db2bae30SDana Myers * 104db2bae30SDana Myers ******************************************************************************/ 105db2bae30SDana Myers 106db2bae30SDana Myers UINT16 107db2bae30SDana Myers AcpiPsPeekOpcode ( 108db2bae30SDana Myers ACPI_PARSE_STATE *ParserState) 109db2bae30SDana Myers { 110db2bae30SDana Myers UINT8 *Aml; 111db2bae30SDana Myers UINT16 Opcode; 112db2bae30SDana Myers 113db2bae30SDana Myers 114db2bae30SDana Myers Aml = ParserState->Aml; 115db2bae30SDana Myers Opcode = (UINT16) ACPI_GET8 (Aml); 116db2bae30SDana Myers 117db2bae30SDana Myers if (Opcode == AML_EXTENDED_OP_PREFIX) 118db2bae30SDana Myers { 119db2bae30SDana Myers /* Extended opcode, get the second opcode byte */ 120db2bae30SDana Myers 121db2bae30SDana Myers Aml++; 122db2bae30SDana Myers Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml)); 123db2bae30SDana Myers } 124db2bae30SDana Myers 125db2bae30SDana Myers return (Opcode); 126db2bae30SDana Myers } 127db2bae30SDana Myers 128db2bae30SDana Myers 129db2bae30SDana Myers /******************************************************************************* 130db2bae30SDana Myers * 131db2bae30SDana Myers * FUNCTION: AcpiPsCompleteThisOp 132db2bae30SDana Myers * 133db2bae30SDana Myers * PARAMETERS: WalkState - Current State 134db2bae30SDana Myers * Op - Op to complete 135db2bae30SDana Myers * 136db2bae30SDana Myers * RETURN: Status 137db2bae30SDana Myers * 138db2bae30SDana Myers * DESCRIPTION: Perform any cleanup at the completion of an Op. 139db2bae30SDana Myers * 140db2bae30SDana Myers ******************************************************************************/ 141db2bae30SDana Myers 142db2bae30SDana Myers ACPI_STATUS 143db2bae30SDana Myers AcpiPsCompleteThisOp ( 144db2bae30SDana Myers ACPI_WALK_STATE *WalkState, 145db2bae30SDana Myers ACPI_PARSE_OBJECT *Op) 146db2bae30SDana Myers { 147db2bae30SDana Myers ACPI_PARSE_OBJECT *Prev; 148db2bae30SDana Myers ACPI_PARSE_OBJECT *Next; 149db2bae30SDana Myers const ACPI_OPCODE_INFO *ParentInfo; 150db2bae30SDana Myers ACPI_PARSE_OBJECT *ReplacementOp = NULL; 151aa2aa9a6SDana Myers ACPI_STATUS Status = AE_OK; 152db2bae30SDana Myers 153db2bae30SDana Myers 154db2bae30SDana Myers ACPI_FUNCTION_TRACE_PTR (PsCompleteThisOp, Op); 155db2bae30SDana Myers 156db2bae30SDana Myers 157db2bae30SDana Myers /* Check for null Op, can happen if AML code is corrupt */ 158db2bae30SDana Myers 159db2bae30SDana Myers if (!Op) 160db2bae30SDana Myers { 161db2bae30SDana Myers return_ACPI_STATUS (AE_OK); /* OK for now */ 162db2bae30SDana Myers } 163db2bae30SDana Myers 164*385cc6b4SJerry Jelinek AcpiExStopTraceOpcode (Op, WalkState); 165*385cc6b4SJerry Jelinek 166db2bae30SDana Myers /* Delete this op and the subtree below it if asked to */ 167db2bae30SDana Myers 168db2bae30SDana Myers if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || 169db2bae30SDana Myers (WalkState->OpInfo->Class == AML_CLASS_ARGUMENT)) 170db2bae30SDana Myers { 171db2bae30SDana Myers return_ACPI_STATUS (AE_OK); 172db2bae30SDana Myers } 173db2bae30SDana Myers 174db2bae30SDana Myers /* Make sure that we only delete this subtree */ 175db2bae30SDana Myers 176db2bae30SDana Myers if (Op->Common.Parent) 177db2bae30SDana Myers { 178db2bae30SDana Myers Prev = Op->Common.Parent->Common.Value.Arg; 179db2bae30SDana Myers if (!Prev) 180db2bae30SDana Myers { 181db2bae30SDana Myers /* Nothing more to do */ 182db2bae30SDana Myers 183db2bae30SDana Myers goto Cleanup; 184db2bae30SDana Myers } 185db2bae30SDana Myers 186db2bae30SDana Myers /* 187db2bae30SDana Myers * Check if we need to replace the operator and its subtree 188db2bae30SDana Myers * with a return value op (placeholder op) 189db2bae30SDana Myers */ 190db2bae30SDana Myers ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode); 191db2bae30SDana Myers 192db2bae30SDana Myers switch (ParentInfo->Class) 193db2bae30SDana Myers { 194db2bae30SDana Myers case AML_CLASS_CONTROL: 195*385cc6b4SJerry Jelinek 196db2bae30SDana Myers break; 197db2bae30SDana Myers 198db2bae30SDana Myers case AML_CLASS_CREATE: 199db2bae30SDana Myers /* 200db2bae30SDana Myers * These opcodes contain TermArg operands. The current 201db2bae30SDana Myers * op must be replaced by a placeholder return op 202db2bae30SDana Myers */ 203*385cc6b4SJerry Jelinek ReplacementOp = AcpiPsAllocOp ( 204*385cc6b4SJerry Jelinek AML_INT_RETURN_VALUE_OP, Op->Common.Aml); 205db2bae30SDana Myers if (!ReplacementOp) 206db2bae30SDana Myers { 207aa2aa9a6SDana Myers Status = AE_NO_MEMORY; 208db2bae30SDana Myers } 209db2bae30SDana Myers break; 210db2bae30SDana Myers 211db2bae30SDana Myers case AML_CLASS_NAMED_OBJECT: 212db2bae30SDana Myers /* 213db2bae30SDana Myers * These opcodes contain TermArg operands. The current 214db2bae30SDana Myers * op must be replaced by a placeholder return op 215db2bae30SDana Myers */ 216db2bae30SDana Myers if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || 217db2bae30SDana Myers (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || 218db2bae30SDana Myers (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || 219db2bae30SDana Myers (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 220db2bae30SDana Myers (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP) || 221db2bae30SDana Myers (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) 222db2bae30SDana Myers { 223*385cc6b4SJerry Jelinek ReplacementOp = AcpiPsAllocOp ( 224*385cc6b4SJerry Jelinek AML_INT_RETURN_VALUE_OP, Op->Common.Aml); 225db2bae30SDana Myers if (!ReplacementOp) 226db2bae30SDana Myers { 227aa2aa9a6SDana Myers Status = AE_NO_MEMORY; 228db2bae30SDana Myers } 229db2bae30SDana Myers } 230db2bae30SDana Myers else if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && 231db2bae30SDana Myers (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) 232db2bae30SDana Myers { 233db2bae30SDana Myers if ((Op->Common.AmlOpcode == AML_BUFFER_OP) || 234db2bae30SDana Myers (Op->Common.AmlOpcode == AML_PACKAGE_OP) || 235db2bae30SDana Myers (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) 236db2bae30SDana Myers { 237*385cc6b4SJerry Jelinek ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode, 238*385cc6b4SJerry Jelinek Op->Common.Aml); 239db2bae30SDana Myers if (!ReplacementOp) 240db2bae30SDana Myers { 241aa2aa9a6SDana Myers Status = AE_NO_MEMORY; 242db2bae30SDana Myers } 243aa2aa9a6SDana Myers else 244aa2aa9a6SDana Myers { 245db2bae30SDana Myers ReplacementOp->Named.Data = Op->Named.Data; 246db2bae30SDana Myers ReplacementOp->Named.Length = Op->Named.Length; 247db2bae30SDana Myers } 248db2bae30SDana Myers } 249aa2aa9a6SDana Myers } 250db2bae30SDana Myers break; 251db2bae30SDana Myers 252db2bae30SDana Myers default: 253db2bae30SDana Myers 254*385cc6b4SJerry Jelinek ReplacementOp = AcpiPsAllocOp ( 255*385cc6b4SJerry Jelinek AML_INT_RETURN_VALUE_OP, Op->Common.Aml); 256db2bae30SDana Myers if (!ReplacementOp) 257db2bae30SDana Myers { 258aa2aa9a6SDana Myers Status = AE_NO_MEMORY; 259db2bae30SDana Myers } 260db2bae30SDana Myers } 261db2bae30SDana Myers 262db2bae30SDana Myers /* We must unlink this op from the parent tree */ 263db2bae30SDana Myers 264db2bae30SDana Myers if (Prev == Op) 265db2bae30SDana Myers { 266db2bae30SDana Myers /* This op is the first in the list */ 267db2bae30SDana Myers 268db2bae30SDana Myers if (ReplacementOp) 269db2bae30SDana Myers { 270db2bae30SDana Myers ReplacementOp->Common.Parent = Op->Common.Parent; 271db2bae30SDana Myers ReplacementOp->Common.Value.Arg = NULL; 272db2bae30SDana Myers ReplacementOp->Common.Node = Op->Common.Node; 273db2bae30SDana Myers Op->Common.Parent->Common.Value.Arg = ReplacementOp; 274db2bae30SDana Myers ReplacementOp->Common.Next = Op->Common.Next; 275db2bae30SDana Myers } 276db2bae30SDana Myers else 277db2bae30SDana Myers { 278db2bae30SDana Myers Op->Common.Parent->Common.Value.Arg = Op->Common.Next; 279db2bae30SDana Myers } 280db2bae30SDana Myers } 281db2bae30SDana Myers 282db2bae30SDana Myers /* Search the parent list */ 283db2bae30SDana Myers 284db2bae30SDana Myers else while (Prev) 285db2bae30SDana Myers { 286db2bae30SDana Myers /* Traverse all siblings in the parent's argument list */ 287db2bae30SDana Myers 288db2bae30SDana Myers Next = Prev->Common.Next; 289db2bae30SDana Myers if (Next == Op) 290db2bae30SDana Myers { 291db2bae30SDana Myers if (ReplacementOp) 292db2bae30SDana Myers { 293db2bae30SDana Myers ReplacementOp->Common.Parent = Op->Common.Parent; 294db2bae30SDana Myers ReplacementOp->Common.Value.Arg = NULL; 295db2bae30SDana Myers ReplacementOp->Common.Node = Op->Common.Node; 296db2bae30SDana Myers Prev->Common.Next = ReplacementOp; 297db2bae30SDana Myers ReplacementOp->Common.Next = Op->Common.Next; 298db2bae30SDana Myers Next = NULL; 299db2bae30SDana Myers } 300db2bae30SDana Myers else 301db2bae30SDana Myers { 302db2bae30SDana Myers Prev->Common.Next = Op->Common.Next; 303db2bae30SDana Myers Next = NULL; 304db2bae30SDana Myers } 305db2bae30SDana Myers } 306db2bae30SDana Myers Prev = Next; 307db2bae30SDana Myers } 308db2bae30SDana Myers } 309db2bae30SDana Myers 310db2bae30SDana Myers 311db2bae30SDana Myers Cleanup: 312db2bae30SDana Myers 313db2bae30SDana Myers /* Now we can actually delete the subtree rooted at Op */ 314db2bae30SDana Myers 315db2bae30SDana Myers AcpiPsDeleteParseTree (Op); 316aa2aa9a6SDana Myers return_ACPI_STATUS (Status); 317db2bae30SDana Myers } 318db2bae30SDana Myers 319db2bae30SDana Myers 320db2bae30SDana Myers /******************************************************************************* 321db2bae30SDana Myers * 322db2bae30SDana Myers * FUNCTION: AcpiPsNextParseState 323db2bae30SDana Myers * 324db2bae30SDana Myers * PARAMETERS: WalkState - Current state 325db2bae30SDana Myers * Op - Current parse op 326db2bae30SDana Myers * CallbackStatus - Status from previous operation 327db2bae30SDana Myers * 328db2bae30SDana Myers * RETURN: Status 329db2bae30SDana Myers * 330db2bae30SDana Myers * DESCRIPTION: Update the parser state based upon the return exception from 331db2bae30SDana Myers * the parser callback. 332db2bae30SDana Myers * 333db2bae30SDana Myers ******************************************************************************/ 334db2bae30SDana Myers 335db2bae30SDana Myers ACPI_STATUS 336db2bae30SDana Myers AcpiPsNextParseState ( 337db2bae30SDana Myers ACPI_WALK_STATE *WalkState, 338db2bae30SDana Myers ACPI_PARSE_OBJECT *Op, 339db2bae30SDana Myers ACPI_STATUS CallbackStatus) 340db2bae30SDana Myers { 341db2bae30SDana Myers ACPI_PARSE_STATE *ParserState = &WalkState->ParserState; 342db2bae30SDana Myers ACPI_STATUS Status = AE_CTRL_PENDING; 343db2bae30SDana Myers 344db2bae30SDana Myers 345db2bae30SDana Myers ACPI_FUNCTION_TRACE_PTR (PsNextParseState, Op); 346db2bae30SDana Myers 347db2bae30SDana Myers 348db2bae30SDana Myers switch (CallbackStatus) 349db2bae30SDana Myers { 350db2bae30SDana Myers case AE_CTRL_TERMINATE: 351db2bae30SDana Myers /* 352db2bae30SDana Myers * A control method was terminated via a RETURN statement. 353db2bae30SDana Myers * The walk of this method is complete. 354db2bae30SDana Myers */ 355db2bae30SDana Myers ParserState->Aml = ParserState->AmlEnd; 356db2bae30SDana Myers Status = AE_CTRL_TERMINATE; 357db2bae30SDana Myers break; 358db2bae30SDana Myers 359db2bae30SDana Myers case AE_CTRL_BREAK: 360db2bae30SDana Myers 361db2bae30SDana Myers ParserState->Aml = WalkState->AmlLastWhile; 362db2bae30SDana Myers WalkState->ControlState->Common.Value = FALSE; 363db2bae30SDana Myers Status = AE_CTRL_BREAK; 364db2bae30SDana Myers break; 365db2bae30SDana Myers 366db2bae30SDana Myers case AE_CTRL_CONTINUE: 367db2bae30SDana Myers 368db2bae30SDana Myers ParserState->Aml = WalkState->AmlLastWhile; 369db2bae30SDana Myers Status = AE_CTRL_CONTINUE; 370db2bae30SDana Myers break; 371db2bae30SDana Myers 372db2bae30SDana Myers case AE_CTRL_PENDING: 373db2bae30SDana Myers 374db2bae30SDana Myers ParserState->Aml = WalkState->AmlLastWhile; 375db2bae30SDana Myers break; 376db2bae30SDana Myers 377db2bae30SDana Myers #if 0 378db2bae30SDana Myers case AE_CTRL_SKIP: 379db2bae30SDana Myers 380db2bae30SDana Myers ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd; 381db2bae30SDana Myers Status = AE_OK; 382db2bae30SDana Myers break; 383db2bae30SDana Myers #endif 384db2bae30SDana Myers 385db2bae30SDana Myers case AE_CTRL_TRUE: 386db2bae30SDana Myers /* 387db2bae30SDana Myers * Predicate of an IF was true, and we are at the matching ELSE. 388db2bae30SDana Myers * Just close out this package 389db2bae30SDana Myers */ 390db2bae30SDana Myers ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState); 391db2bae30SDana Myers Status = AE_CTRL_PENDING; 392db2bae30SDana Myers break; 393db2bae30SDana Myers 394db2bae30SDana Myers case AE_CTRL_FALSE: 395db2bae30SDana Myers /* 396db2bae30SDana Myers * Either an IF/WHILE Predicate was false or we encountered a BREAK 397db2bae30SDana Myers * opcode. In both cases, we do not execute the rest of the 398db2bae30SDana Myers * package; We simply close out the parent (finishing the walk of 399db2bae30SDana Myers * this branch of the tree) and continue execution at the parent 400db2bae30SDana Myers * level. 401db2bae30SDana Myers */ 402db2bae30SDana Myers ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd; 403db2bae30SDana Myers 404db2bae30SDana Myers /* In the case of a BREAK, just force a predicate (if any) to FALSE */ 405db2bae30SDana Myers 406db2bae30SDana Myers WalkState->ControlState->Common.Value = FALSE; 407db2bae30SDana Myers Status = AE_CTRL_END; 408db2bae30SDana Myers break; 409db2bae30SDana Myers 410db2bae30SDana Myers case AE_CTRL_TRANSFER: 411db2bae30SDana Myers 412db2bae30SDana Myers /* A method call (invocation) -- transfer control */ 413db2bae30SDana Myers 414db2bae30SDana Myers Status = AE_CTRL_TRANSFER; 415db2bae30SDana Myers WalkState->PrevOp = Op; 416db2bae30SDana Myers WalkState->MethodCallOp = Op; 417db2bae30SDana Myers WalkState->MethodCallNode = (Op->Common.Value.Arg)->Common.Node; 418db2bae30SDana Myers 419db2bae30SDana Myers /* Will return value (if any) be used by the caller? */ 420db2bae30SDana Myers 421db2bae30SDana Myers WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState); 422db2bae30SDana Myers break; 423db2bae30SDana Myers 424db2bae30SDana Myers default: 425db2bae30SDana Myers 426db2bae30SDana Myers Status = CallbackStatus; 427db2bae30SDana Myers if ((CallbackStatus & AE_CODE_MASK) == AE_CODE_CONTROL) 428db2bae30SDana Myers { 429db2bae30SDana Myers Status = AE_OK; 430db2bae30SDana Myers } 431db2bae30SDana Myers break; 432db2bae30SDana Myers } 433db2bae30SDana Myers 434db2bae30SDana Myers return_ACPI_STATUS (Status); 435db2bae30SDana Myers } 436db2bae30SDana Myers 437db2bae30SDana Myers 438db2bae30SDana Myers /******************************************************************************* 439db2bae30SDana Myers * 440db2bae30SDana Myers * FUNCTION: AcpiPsParseAml 441db2bae30SDana Myers * 442db2bae30SDana Myers * PARAMETERS: WalkState - Current state 443db2bae30SDana Myers * 444db2bae30SDana Myers * 445db2bae30SDana Myers * RETURN: Status 446db2bae30SDana Myers * 447db2bae30SDana Myers * DESCRIPTION: Parse raw AML and return a tree of ops 448db2bae30SDana Myers * 449db2bae30SDana Myers ******************************************************************************/ 450db2bae30SDana Myers 451db2bae30SDana Myers ACPI_STATUS 452db2bae30SDana Myers AcpiPsParseAml ( 453db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 454db2bae30SDana Myers { 455db2bae30SDana Myers ACPI_STATUS Status; 456db2bae30SDana Myers ACPI_THREAD_STATE *Thread; 457db2bae30SDana Myers ACPI_THREAD_STATE *PrevWalkList = AcpiGbl_CurrentWalkList; 458db2bae30SDana Myers ACPI_WALK_STATE *PreviousWalkState; 459db2bae30SDana Myers 460db2bae30SDana Myers 461db2bae30SDana Myers ACPI_FUNCTION_TRACE (PsParseAml); 462db2bae30SDana Myers 463db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 464db2bae30SDana Myers "Entered with WalkState=%p Aml=%p size=%X\n", 465db2bae30SDana Myers WalkState, WalkState->ParserState.Aml, 466db2bae30SDana Myers WalkState->ParserState.AmlSize)); 467db2bae30SDana Myers 468aa2aa9a6SDana Myers if (!WalkState->ParserState.Aml) 469aa2aa9a6SDana Myers { 470aa2aa9a6SDana Myers return_ACPI_STATUS (AE_NULL_OBJECT); 471aa2aa9a6SDana Myers } 472db2bae30SDana Myers 473db2bae30SDana Myers /* Create and initialize a new thread state */ 474db2bae30SDana Myers 475db2bae30SDana Myers Thread = AcpiUtCreateThreadState (); 476db2bae30SDana Myers if (!Thread) 477db2bae30SDana Myers { 478aa2aa9a6SDana Myers if (WalkState->MethodDesc) 479aa2aa9a6SDana Myers { 480aa2aa9a6SDana Myers /* Executing a control method - additional cleanup */ 481aa2aa9a6SDana Myers 482aa2aa9a6SDana Myers AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); 483aa2aa9a6SDana Myers } 484aa2aa9a6SDana Myers 485db2bae30SDana Myers AcpiDsDeleteWalkState (WalkState); 486db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 487db2bae30SDana Myers } 488db2bae30SDana Myers 489db2bae30SDana Myers WalkState->Thread = Thread; 490db2bae30SDana Myers 491db2bae30SDana Myers /* 492db2bae30SDana Myers * If executing a method, the starting SyncLevel is this method's 493db2bae30SDana Myers * SyncLevel 494db2bae30SDana Myers */ 495db2bae30SDana Myers if (WalkState->MethodDesc) 496db2bae30SDana Myers { 497*385cc6b4SJerry Jelinek WalkState->Thread->CurrentSyncLevel = 498*385cc6b4SJerry Jelinek WalkState->MethodDesc->Method.SyncLevel; 499db2bae30SDana Myers } 500db2bae30SDana Myers 501db2bae30SDana Myers AcpiDsPushWalkState (WalkState, Thread); 502db2bae30SDana Myers 503db2bae30SDana Myers /* 504db2bae30SDana Myers * This global allows the AML debugger to get a handle to the currently 505db2bae30SDana Myers * executing control method. 506db2bae30SDana Myers */ 507db2bae30SDana Myers AcpiGbl_CurrentWalkList = Thread; 508db2bae30SDana Myers 509db2bae30SDana Myers /* 510db2bae30SDana Myers * Execute the walk loop as long as there is a valid Walk State. This 511db2bae30SDana Myers * handles nested control method invocations without recursion. 512db2bae30SDana Myers */ 513db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState)); 514db2bae30SDana Myers 515db2bae30SDana Myers Status = AE_OK; 516db2bae30SDana Myers while (WalkState) 517db2bae30SDana Myers { 518db2bae30SDana Myers if (ACPI_SUCCESS (Status)) 519db2bae30SDana Myers { 520db2bae30SDana Myers /* 521db2bae30SDana Myers * The ParseLoop executes AML until the method terminates 522db2bae30SDana Myers * or calls another method. 523db2bae30SDana Myers */ 524db2bae30SDana Myers Status = AcpiPsParseLoop (WalkState); 525db2bae30SDana Myers } 526db2bae30SDana Myers 527db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 528db2bae30SDana Myers "Completed one call to walk loop, %s State=%p\n", 529db2bae30SDana Myers AcpiFormatException (Status), WalkState)); 530db2bae30SDana Myers 531db2bae30SDana Myers if (Status == AE_CTRL_TRANSFER) 532db2bae30SDana Myers { 533db2bae30SDana Myers /* 534db2bae30SDana Myers * A method call was detected. 535db2bae30SDana Myers * Transfer control to the called control method 536db2bae30SDana Myers */ 537db2bae30SDana Myers Status = AcpiDsCallControlMethod (Thread, WalkState, NULL); 538db2bae30SDana Myers if (ACPI_FAILURE (Status)) 539db2bae30SDana Myers { 540db2bae30SDana Myers Status = AcpiDsMethodError (Status, WalkState); 541db2bae30SDana Myers } 542db2bae30SDana Myers 543db2bae30SDana Myers /* 544*385cc6b4SJerry Jelinek * If the transfer to the new method method call worked 545*385cc6b4SJerry Jelinek *, a new walk state was created -- get it 546db2bae30SDana Myers */ 547db2bae30SDana Myers WalkState = AcpiDsGetCurrentWalkState (Thread); 548db2bae30SDana Myers continue; 549db2bae30SDana Myers } 550db2bae30SDana Myers else if (Status == AE_CTRL_TERMINATE) 551db2bae30SDana Myers { 552db2bae30SDana Myers Status = AE_OK; 553db2bae30SDana Myers } 554db2bae30SDana Myers else if ((Status != AE_OK) && (WalkState->MethodDesc)) 555db2bae30SDana Myers { 556db2bae30SDana Myers /* Either the method parse or actual execution failed */ 557db2bae30SDana Myers 558db2bae30SDana Myers ACPI_ERROR_METHOD ("Method parse/execution failed", 559db2bae30SDana Myers WalkState->MethodNode, NULL, Status); 560db2bae30SDana Myers 561db2bae30SDana Myers /* Check for possible multi-thread reentrancy problem */ 562db2bae30SDana Myers 563db2bae30SDana Myers if ((Status == AE_ALREADY_EXISTS) && 564*385cc6b4SJerry Jelinek (!(WalkState->MethodDesc->Method.InfoFlags & 565*385cc6b4SJerry Jelinek ACPI_METHOD_SERIALIZED))) 566db2bae30SDana Myers { 567db2bae30SDana Myers /* 56826f3cdf0SGordon Ross * Method is not serialized and tried to create an object 56926f3cdf0SGordon Ross * twice. The probable cause is that the method cannot 57026f3cdf0SGordon Ross * handle reentrancy. Mark as "pending serialized" now, and 57126f3cdf0SGordon Ross * then mark "serialized" when the last thread exits. 572db2bae30SDana Myers */ 57326f3cdf0SGordon Ross WalkState->MethodDesc->Method.InfoFlags |= 57426f3cdf0SGordon Ross ACPI_METHOD_SERIALIZED_PENDING; 575db2bae30SDana Myers } 576db2bae30SDana Myers } 577db2bae30SDana Myers 578db2bae30SDana Myers /* We are done with this walk, move on to the parent if any */ 579db2bae30SDana Myers 580db2bae30SDana Myers WalkState = AcpiDsPopWalkState (Thread); 581db2bae30SDana Myers 582db2bae30SDana Myers /* Reset the current scope to the beginning of scope stack */ 583db2bae30SDana Myers 584db2bae30SDana Myers AcpiDsScopeStackClear (WalkState); 585db2bae30SDana Myers 586db2bae30SDana Myers /* 587db2bae30SDana Myers * If we just returned from the execution of a control method or if we 588db2bae30SDana Myers * encountered an error during the method parse phase, there's lots of 589db2bae30SDana Myers * cleanup to do 590db2bae30SDana Myers */ 591*385cc6b4SJerry Jelinek if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == 592*385cc6b4SJerry Jelinek ACPI_PARSE_EXECUTE) || 593db2bae30SDana Myers (ACPI_FAILURE (Status))) 594db2bae30SDana Myers { 595db2bae30SDana Myers AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); 596db2bae30SDana Myers } 597db2bae30SDana Myers 598db2bae30SDana Myers /* Delete this walk state and all linked control states */ 599db2bae30SDana Myers 600db2bae30SDana Myers AcpiPsCleanupScope (&WalkState->ParserState); 601db2bae30SDana Myers PreviousWalkState = WalkState; 602db2bae30SDana Myers 603db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 604db2bae30SDana Myers "ReturnValue=%p, ImplicitValue=%p State=%p\n", 605db2bae30SDana Myers WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState)); 606db2bae30SDana Myers 607db2bae30SDana Myers /* Check if we have restarted a preempted walk */ 608db2bae30SDana Myers 609db2bae30SDana Myers WalkState = AcpiDsGetCurrentWalkState (Thread); 610db2bae30SDana Myers if (WalkState) 611db2bae30SDana Myers { 612db2bae30SDana Myers if (ACPI_SUCCESS (Status)) 613db2bae30SDana Myers { 614db2bae30SDana Myers /* 615db2bae30SDana Myers * There is another walk state, restart it. 616db2bae30SDana Myers * If the method return value is not used by the parent, 617db2bae30SDana Myers * The object is deleted 618db2bae30SDana Myers */ 619db2bae30SDana Myers if (!PreviousWalkState->ReturnDesc) 620db2bae30SDana Myers { 621db2bae30SDana Myers /* 622db2bae30SDana Myers * In slack mode execution, if there is no return value 623db2bae30SDana Myers * we should implicitly return zero (0) as a default value. 624db2bae30SDana Myers */ 625db2bae30SDana Myers if (AcpiGbl_EnableInterpreterSlack && 626db2bae30SDana Myers !PreviousWalkState->ImplicitReturnObj) 627db2bae30SDana Myers { 628db2bae30SDana Myers PreviousWalkState->ImplicitReturnObj = 62957190917SDana Myers AcpiUtCreateIntegerObject ((UINT64) 0); 630db2bae30SDana Myers if (!PreviousWalkState->ImplicitReturnObj) 631db2bae30SDana Myers { 632db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 633db2bae30SDana Myers } 634db2bae30SDana Myers } 635db2bae30SDana Myers 636db2bae30SDana Myers /* Restart the calling control method */ 637db2bae30SDana Myers 638db2bae30SDana Myers Status = AcpiDsRestartControlMethod (WalkState, 639db2bae30SDana Myers PreviousWalkState->ImplicitReturnObj); 640db2bae30SDana Myers } 641db2bae30SDana Myers else 642db2bae30SDana Myers { 643db2bae30SDana Myers /* 644db2bae30SDana Myers * We have a valid return value, delete any implicit 645db2bae30SDana Myers * return value. 646db2bae30SDana Myers */ 647db2bae30SDana Myers AcpiDsClearImplicitReturn (PreviousWalkState); 648db2bae30SDana Myers 649db2bae30SDana Myers Status = AcpiDsRestartControlMethod (WalkState, 650db2bae30SDana Myers PreviousWalkState->ReturnDesc); 651db2bae30SDana Myers } 652db2bae30SDana Myers if (ACPI_SUCCESS (Status)) 653db2bae30SDana Myers { 654db2bae30SDana Myers WalkState->WalkType |= ACPI_WALK_METHOD_RESTART; 655db2bae30SDana Myers } 656db2bae30SDana Myers } 657db2bae30SDana Myers else 658db2bae30SDana Myers { 659aa2aa9a6SDana Myers /* On error, delete any return object or implicit return */ 660db2bae30SDana Myers 661db2bae30SDana Myers AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); 662aa2aa9a6SDana Myers AcpiDsClearImplicitReturn (PreviousWalkState); 663db2bae30SDana Myers } 664db2bae30SDana Myers } 665db2bae30SDana Myers 666db2bae30SDana Myers /* 667db2bae30SDana Myers * Just completed a 1st-level method, save the final internal return 668db2bae30SDana Myers * value (if any) 669db2bae30SDana Myers */ 670db2bae30SDana Myers else if (PreviousWalkState->CallerReturnDesc) 671db2bae30SDana Myers { 672db2bae30SDana Myers if (PreviousWalkState->ImplicitReturnObj) 673db2bae30SDana Myers { 674db2bae30SDana Myers *(PreviousWalkState->CallerReturnDesc) = 675db2bae30SDana Myers PreviousWalkState->ImplicitReturnObj; 676db2bae30SDana Myers } 677db2bae30SDana Myers else 678db2bae30SDana Myers { 679db2bae30SDana Myers /* NULL if no return value */ 680db2bae30SDana Myers 681db2bae30SDana Myers *(PreviousWalkState->CallerReturnDesc) = 682db2bae30SDana Myers PreviousWalkState->ReturnDesc; 683db2bae30SDana Myers } 684db2bae30SDana Myers } 685db2bae30SDana Myers else 686db2bae30SDana Myers { 687db2bae30SDana Myers if (PreviousWalkState->ReturnDesc) 688db2bae30SDana Myers { 689db2bae30SDana Myers /* Caller doesn't want it, must delete it */ 690db2bae30SDana Myers 691db2bae30SDana Myers AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); 692db2bae30SDana Myers } 693db2bae30SDana Myers if (PreviousWalkState->ImplicitReturnObj) 694db2bae30SDana Myers { 695db2bae30SDana Myers /* Caller doesn't want it, must delete it */ 696db2bae30SDana Myers 697db2bae30SDana Myers AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj); 698db2bae30SDana Myers } 699db2bae30SDana Myers } 700db2bae30SDana Myers 701db2bae30SDana Myers AcpiDsDeleteWalkState (PreviousWalkState); 702db2bae30SDana Myers } 703db2bae30SDana Myers 704db2bae30SDana Myers /* Normal exit */ 705db2bae30SDana Myers 706db2bae30SDana Myers AcpiExReleaseAllMutexes (Thread); 707db2bae30SDana Myers AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread)); 708db2bae30SDana Myers AcpiGbl_CurrentWalkList = PrevWalkList; 709db2bae30SDana Myers return_ACPI_STATUS (Status); 710db2bae30SDana Myers } 711