Path: blob/main/sys/contrib/dev/acpica/components/parser/psparse.c
48524 views
/******************************************************************************1*2* Module Name: psparse - Parser top level AML parse routines3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151/*152* Parse the AML and build an operation tree as most interpreters,153* like Perl, do. Parsing is done by hand rather than with a YACC154* generated parser to tightly constrain stack and dynamic memory155* usage. At the same time, parsing is kept flexible and the code156* fairly compact by parsing based on a list of AML opcode157* templates in AmlOpInfo[]158*/159160#include <contrib/dev/acpica/include/acpi.h>161#include <contrib/dev/acpica/include/accommon.h>162#include <contrib/dev/acpica/include/acparser.h>163#include <contrib/dev/acpica/include/acdispat.h>164#include <contrib/dev/acpica/include/amlcode.h>165#include <contrib/dev/acpica/include/acinterp.h>166#include <contrib/dev/acpica/include/acnamesp.h>167168#define _COMPONENT ACPI_PARSER169ACPI_MODULE_NAME ("psparse")170171172/*******************************************************************************173*174* FUNCTION: AcpiPsGetOpcodeSize175*176* PARAMETERS: Opcode - An AML opcode177*178* RETURN: Size of the opcode, in bytes (1 or 2)179*180* DESCRIPTION: Get the size of the current opcode.181*182******************************************************************************/183184UINT32185AcpiPsGetOpcodeSize (186UINT32 Opcode)187{188189/* Extended (2-byte) opcode if > 255 */190191if (Opcode > 0x00FF)192{193return (2);194}195196/* Otherwise, just a single byte opcode */197198return (1);199}200201202/*******************************************************************************203*204* FUNCTION: AcpiPsPeekOpcode205*206* PARAMETERS: ParserState - A parser state object207*208* RETURN: Next AML opcode209*210* DESCRIPTION: Get next AML opcode (without incrementing AML pointer)211*212******************************************************************************/213214UINT16215AcpiPsPeekOpcode (216ACPI_PARSE_STATE *ParserState)217{218UINT8 *Aml;219UINT16 Opcode;220221222Aml = ParserState->Aml;223Opcode = (UINT16) ACPI_GET8 (Aml);224225if (Opcode == AML_EXTENDED_PREFIX)226{227/* Extended opcode, get the second opcode byte */228229Aml++;230Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml));231}232233return (Opcode);234}235236237/*******************************************************************************238*239* FUNCTION: AcpiPsCompleteThisOp240*241* PARAMETERS: WalkState - Current State242* Op - Op to complete243*244* RETURN: Status245*246* DESCRIPTION: Perform any cleanup at the completion of an Op.247*248******************************************************************************/249250ACPI_STATUS251AcpiPsCompleteThisOp (252ACPI_WALK_STATE *WalkState,253ACPI_PARSE_OBJECT *Op)254{255ACPI_PARSE_OBJECT *Prev;256ACPI_PARSE_OBJECT *Next;257const ACPI_OPCODE_INFO *ParentInfo;258ACPI_PARSE_OBJECT *ReplacementOp = NULL;259ACPI_STATUS Status = AE_OK;260261262ACPI_FUNCTION_TRACE_PTR (PsCompleteThisOp, Op);263264265/* Check for null Op, can happen if AML code is corrupt */266267if (!Op)268{269return_ACPI_STATUS (AE_OK); /* OK for now */270}271272AcpiExStopTraceOpcode (Op, WalkState);273274/* Delete this op and the subtree below it if asked to */275276if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||277(WalkState->OpInfo->Class == AML_CLASS_ARGUMENT))278{279return_ACPI_STATUS (AE_OK);280}281282/* Make sure that we only delete this subtree */283284if (Op->Common.Parent)285{286Prev = Op->Common.Parent->Common.Value.Arg;287if (!Prev)288{289/* Nothing more to do */290291goto Cleanup;292}293294/*295* Check if we need to replace the operator and its subtree296* with a return value op (placeholder op)297*/298ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);299300switch (ParentInfo->Class)301{302case AML_CLASS_CONTROL:303304break;305306case AML_CLASS_CREATE:307/*308* These opcodes contain TermArg operands. The current309* op must be replaced by a placeholder return op310*/311ReplacementOp = AcpiPsAllocOp (312AML_INT_RETURN_VALUE_OP, Op->Common.Aml);313if (!ReplacementOp)314{315Status = AE_NO_MEMORY;316}317break;318319case AML_CLASS_NAMED_OBJECT:320/*321* These opcodes contain TermArg operands. The current322* op must be replaced by a placeholder return op323*/324if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) ||325(Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) ||326(Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) ||327(Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||328(Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP) ||329(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))330{331ReplacementOp = AcpiPsAllocOp (332AML_INT_RETURN_VALUE_OP, Op->Common.Aml);333if (!ReplacementOp)334{335Status = AE_NO_MEMORY;336}337}338else if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&339(WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))340{341if ((Op->Common.AmlOpcode == AML_BUFFER_OP) ||342(Op->Common.AmlOpcode == AML_PACKAGE_OP) ||343(Op->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))344{345ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode,346Op->Common.Aml);347if (!ReplacementOp)348{349Status = AE_NO_MEMORY;350}351else352{353ReplacementOp->Named.Data = Op->Named.Data;354ReplacementOp->Named.Length = Op->Named.Length;355}356}357}358break;359360default:361362ReplacementOp = AcpiPsAllocOp (363AML_INT_RETURN_VALUE_OP, Op->Common.Aml);364if (!ReplacementOp)365{366Status = AE_NO_MEMORY;367}368}369370/* We must unlink this op from the parent tree */371372if (Prev == Op)373{374/* This op is the first in the list */375376if (ReplacementOp)377{378ReplacementOp->Common.Parent = Op->Common.Parent;379ReplacementOp->Common.Value.Arg = NULL;380ReplacementOp->Common.Node = Op->Common.Node;381Op->Common.Parent->Common.Value.Arg = ReplacementOp;382ReplacementOp->Common.Next = Op->Common.Next;383}384else385{386Op->Common.Parent->Common.Value.Arg = Op->Common.Next;387}388}389390/* Search the parent list */391392else while (Prev)393{394/* Traverse all siblings in the parent's argument list */395396Next = Prev->Common.Next;397if (Next == Op)398{399if (ReplacementOp)400{401ReplacementOp->Common.Parent = Op->Common.Parent;402ReplacementOp->Common.Value.Arg = NULL;403ReplacementOp->Common.Node = Op->Common.Node;404Prev->Common.Next = ReplacementOp;405ReplacementOp->Common.Next = Op->Common.Next;406Next = NULL;407}408else409{410Prev->Common.Next = Op->Common.Next;411Next = NULL;412}413}414Prev = Next;415}416}417418419Cleanup:420421/* Now we can actually delete the subtree rooted at Op */422423AcpiPsDeleteParseTree (Op);424return_ACPI_STATUS (Status);425}426427428/*******************************************************************************429*430* FUNCTION: AcpiPsNextParseState431*432* PARAMETERS: WalkState - Current state433* Op - Current parse op434* CallbackStatus - Status from previous operation435*436* RETURN: Status437*438* DESCRIPTION: Update the parser state based upon the return exception from439* the parser callback.440*441******************************************************************************/442443ACPI_STATUS444AcpiPsNextParseState (445ACPI_WALK_STATE *WalkState,446ACPI_PARSE_OBJECT *Op,447ACPI_STATUS CallbackStatus)448{449ACPI_PARSE_STATE *ParserState = &WalkState->ParserState;450ACPI_STATUS Status = AE_CTRL_PENDING;451452453ACPI_FUNCTION_TRACE_PTR (PsNextParseState, Op);454455456switch (CallbackStatus)457{458case AE_CTRL_TERMINATE:459/*460* A control method was terminated via a RETURN statement.461* The walk of this method is complete.462*/463ParserState->Aml = ParserState->AmlEnd;464Status = AE_CTRL_TERMINATE;465break;466467case AE_CTRL_BREAK:468469ParserState->Aml = WalkState->AmlLastWhile;470WalkState->ControlState->Common.Value = FALSE;471Status = AE_CTRL_BREAK;472break;473474case AE_CTRL_CONTINUE:475476ParserState->Aml = WalkState->AmlLastWhile;477Status = AE_CTRL_CONTINUE;478break;479480case AE_CTRL_PENDING:481482ParserState->Aml = WalkState->AmlLastWhile;483break;484485#if 0486case AE_CTRL_SKIP:487488ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;489Status = AE_OK;490break;491#endif492493case AE_CTRL_TRUE:494/*495* Predicate of an IF was true, and we are at the matching ELSE.496* Just close out this package497*/498ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState);499Status = AE_CTRL_PENDING;500break;501502case AE_CTRL_FALSE:503/*504* Either an IF/WHILE Predicate was false or we encountered a BREAK505* opcode. In both cases, we do not execute the rest of the506* package; We simply close out the parent (finishing the walk of507* this branch of the tree) and continue execution at the parent508* level.509*/510ParserState->Aml = ParserState->Scope->ParseScope.PkgEnd;511512/* In the case of a BREAK, just force a predicate (if any) to FALSE */513514WalkState->ControlState->Common.Value = FALSE;515Status = AE_CTRL_END;516break;517518case AE_CTRL_TRANSFER:519520/* A method call (invocation) -- transfer control */521522Status = AE_CTRL_TRANSFER;523WalkState->PrevOp = Op;524WalkState->MethodCallOp = Op;525WalkState->MethodCallNode = (Op->Common.Value.Arg)->Common.Node;526527/* Will return value (if any) be used by the caller? */528529WalkState->ReturnUsed = AcpiDsIsResultUsed (Op, WalkState);530break;531532default:533534Status = CallbackStatus;535if (ACPI_CNTL_EXCEPTION (CallbackStatus))536{537Status = AE_OK;538}539break;540}541542return_ACPI_STATUS (Status);543}544545546/*******************************************************************************547*548* FUNCTION: AcpiPsParseAml549*550* PARAMETERS: WalkState - Current state551*552*553* RETURN: Status554*555* DESCRIPTION: Parse raw AML and return a tree of ops556*557******************************************************************************/558559ACPI_STATUS560AcpiPsParseAml (561ACPI_WALK_STATE *WalkState)562{563ACPI_STATUS Status;564ACPI_THREAD_STATE *Thread;565ACPI_THREAD_STATE *PrevWalkList = AcpiGbl_CurrentWalkList;566ACPI_WALK_STATE *PreviousWalkState;567568569ACPI_FUNCTION_TRACE (PsParseAml);570571ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,572"Entered with WalkState=%p Aml=%p size=%X\n",573WalkState, WalkState->ParserState.Aml,574WalkState->ParserState.AmlSize));575576if (!WalkState->ParserState.Aml)577{578return_ACPI_STATUS (AE_BAD_ADDRESS);579}580581/* Create and initialize a new thread state */582583Thread = AcpiUtCreateThreadState ();584if (!Thread)585{586if (WalkState->MethodDesc)587{588/* Executing a control method - additional cleanup */589590AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);591}592593AcpiDsDeleteWalkState (WalkState);594return_ACPI_STATUS (AE_NO_MEMORY);595}596597WalkState->Thread = Thread;598599/*600* If executing a method, the starting SyncLevel is this method's601* SyncLevel602*/603if (WalkState->MethodDesc)604{605WalkState->Thread->CurrentSyncLevel =606WalkState->MethodDesc->Method.SyncLevel;607}608609AcpiDsPushWalkState (WalkState, Thread);610611/*612* This global allows the AML debugger to get a handle to the currently613* executing control method.614*/615AcpiGbl_CurrentWalkList = Thread;616617/*618* Execute the walk loop as long as there is a valid Walk State. This619* handles nested control method invocations without recursion.620*/621ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState));622623Status = AE_OK;624while (WalkState)625{626if (ACPI_SUCCESS (Status))627{628/*629* The ParseLoop executes AML until the method terminates630* or calls another method.631*/632Status = AcpiPsParseLoop (WalkState);633}634635ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,636"Completed one call to walk loop, %s State=%p\n",637AcpiFormatException (Status), WalkState));638639if (WalkState->MethodPathname && WalkState->MethodIsNested)640{641/* Optional object evaluation log */642643ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, "%-26s: %*s%s\n",644" Exit nested method",645(WalkState->MethodNestingDepth + 1) * 3, " ",646&WalkState->MethodPathname[1]));647648ACPI_FREE (WalkState->MethodPathname);649WalkState->MethodIsNested = FALSE;650}651if (Status == AE_CTRL_TRANSFER)652{653/*654* A method call was detected.655* Transfer control to the called control method656*/657Status = AcpiDsCallControlMethod (Thread, WalkState, NULL);658if (ACPI_FAILURE (Status))659{660Status = AcpiDsMethodError (Status, WalkState);661}662663/*664* If the transfer to the new method method call worked,665* a new walk state was created -- get it666*/667WalkState = AcpiDsGetCurrentWalkState (Thread);668continue;669}670else if (Status == AE_CTRL_TERMINATE)671{672Status = AE_OK;673}674else if ((Status != AE_OK) && (WalkState->MethodDesc))675{676/* Either the method parse or actual execution failed */677678AcpiExExitInterpreter ();679if (Status == AE_ABORT_METHOD)680{681AcpiNsPrintNodePathname (682WalkState->MethodNode, "Aborting method");683AcpiOsPrintf ("\n");684}685else686{687ACPI_ERROR_METHOD ("Aborting method",688WalkState->MethodNode, NULL, Status);689}690AcpiExEnterInterpreter ();691692/* Check for possible multi-thread reentrancy problem */693694if ((Status == AE_ALREADY_EXISTS) &&695(!(WalkState->MethodDesc->Method.InfoFlags &696ACPI_METHOD_SERIALIZED)))697{698/*699* Method is not serialized and tried to create an object700* twice. The probable cause is that the method cannot701* handle reentrancy. Mark as "pending serialized" now, and702* then mark "serialized" when the last thread exits.703*/704WalkState->MethodDesc->Method.InfoFlags |=705ACPI_METHOD_SERIALIZED_PENDING;706}707}708709/* We are done with this walk, move on to the parent if any */710711WalkState = AcpiDsPopWalkState (Thread);712713/* Reset the current scope to the beginning of scope stack */714715AcpiDsScopeStackClear (WalkState);716717/*718* If we just returned from the execution of a control method or if we719* encountered an error during the method parse phase, there's lots of720* cleanup to do721*/722if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) ==723ACPI_PARSE_EXECUTE &&724!(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) ||725(ACPI_FAILURE (Status)))726{727AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);728}729730/* Delete this walk state and all linked control states */731732AcpiPsCleanupScope (&WalkState->ParserState);733PreviousWalkState = WalkState;734735ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,736"ReturnValue=%p, ImplicitValue=%p State=%p\n",737WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState));738739/* Check if we have restarted a preempted walk */740741WalkState = AcpiDsGetCurrentWalkState (Thread);742if (WalkState)743{744if (ACPI_SUCCESS (Status))745{746/*747* There is another walk state, restart it.748* If the method return value is not used by the parent,749* The object is deleted750*/751if (!PreviousWalkState->ReturnDesc)752{753/*754* In slack mode execution, if there is no return value755* we should implicitly return zero (0) as a default value.756*/757if (AcpiGbl_EnableInterpreterSlack &&758!PreviousWalkState->ImplicitReturnObj)759{760PreviousWalkState->ImplicitReturnObj =761AcpiUtCreateIntegerObject ((UINT64) 0);762if (!PreviousWalkState->ImplicitReturnObj)763{764return_ACPI_STATUS (AE_NO_MEMORY);765}766}767768/* Restart the calling control method */769770Status = AcpiDsRestartControlMethod (WalkState,771PreviousWalkState->ImplicitReturnObj);772}773else774{775/*776* We have a valid return value, delete any implicit777* return value.778*/779AcpiDsClearImplicitReturn (PreviousWalkState);780781Status = AcpiDsRestartControlMethod (WalkState,782PreviousWalkState->ReturnDesc);783}784if (ACPI_SUCCESS (Status))785{786WalkState->WalkType |= ACPI_WALK_METHOD_RESTART;787}788}789else790{791/* On error, delete any return object or implicit return */792793AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);794AcpiDsClearImplicitReturn (PreviousWalkState);795}796}797798/*799* Just completed a 1st-level method, save the final internal return800* value (if any)801*/802else if (PreviousWalkState->CallerReturnDesc)803{804if (PreviousWalkState->ImplicitReturnObj)805{806*(PreviousWalkState->CallerReturnDesc) =807PreviousWalkState->ImplicitReturnObj;808}809else810{811/* NULL if no return value */812813*(PreviousWalkState->CallerReturnDesc) =814PreviousWalkState->ReturnDesc;815}816}817else818{819if (PreviousWalkState->ReturnDesc)820{821/* Caller doesn't want it, must delete it */822823AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);824}825if (PreviousWalkState->ImplicitReturnObj)826{827/* Caller doesn't want it, must delete it */828829AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj);830}831}832833AcpiDsDeleteWalkState (PreviousWalkState);834}835836/* Normal exit */837838AcpiExReleaseAllMutexes (Thread);839AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread));840AcpiGbl_CurrentWalkList = PrevWalkList;841return_ACPI_STATUS (Status);842}843844845