167754Smsmith/*******************************************************************************
267754Smsmith *
3167802Sjkim * Module Name: nseval - Object evaluation, includes control method execution
467754Smsmith *
567754Smsmith ******************************************************************************/
667754Smsmith
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46193341Sjkim#include <contrib/dev/acpica/include/acparser.h>
47193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
48193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
4967754Smsmith
5067754Smsmith
5177424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5291116Smsmith        ACPI_MODULE_NAME    ("nseval")
5367754Smsmith
54197104Sjkim/* Local prototypes */
5567754Smsmith
56197104Sjkimstatic void
57197104SjkimAcpiNsExecModuleCode (
58197104Sjkim    ACPI_OPERAND_OBJECT     *MethodObj,
59197104Sjkim    ACPI_EVALUATE_INFO      *Info);
60197104Sjkim
61197104Sjkim
6267754Smsmith/*******************************************************************************
6367754Smsmith *
64167802Sjkim * FUNCTION:    AcpiNsEvaluate
6567754Smsmith *
66306536Sjkim * PARAMETERS:  Info            - Evaluation info block, contains these fields
67306536Sjkim *                                and more:
68167802Sjkim *                  PrefixNode      - Prefix or Method/Object Node to execute
69249663Sjkim *                  RelativePath    - Name of method to execute, If NULL, the
70167802Sjkim *                                    Node is the object to execute
71151937Sjkim *                  Parameters      - List of parameters to pass to the method,
72151937Sjkim *                                    terminated by NULL. Params itself may be
7367754Smsmith *                                    NULL if no parameters are being passed.
74151937Sjkim *                  ParameterType   - Type of Parameter list
75151937Sjkim *                  ReturnObject    - Where to put method's return value (if
76151937Sjkim *                                    any). If NULL, no value is returned.
77167802Sjkim *                  Flags           - ACPI_IGNORE_RETURN_VALUE to delete return
7867754Smsmith *
7967754Smsmith * RETURN:      Status
8067754Smsmith *
81167802Sjkim * DESCRIPTION: Execute a control method or return the current value of an
82167802Sjkim *              ACPI namespace object.
8367754Smsmith *
84167802Sjkim * MUTEX:       Locks interpreter
8567754Smsmith *
8667754Smsmith ******************************************************************************/
8767754Smsmith
8867754SmsmithACPI_STATUS
89167802SjkimAcpiNsEvaluate (
90167802Sjkim    ACPI_EVALUATE_INFO      *Info)
9167754Smsmith{
9267754Smsmith    ACPI_STATUS             Status;
9367754Smsmith
9467754Smsmith
95167802Sjkim    ACPI_FUNCTION_TRACE (NsEvaluate);
9667754Smsmith
9767754Smsmith
98129684Snjl    if (!Info)
9967754Smsmith    {
10067754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
10167754Smsmith    }
10267754Smsmith
103249663Sjkim    if (!Info->Node)
10491116Smsmith    {
105249112Sjkim        /*
106249663Sjkim         * Get the actual namespace node for the target object if we
107249663Sjkim         * need to. Handles these cases:
108249112Sjkim         *
109249663Sjkim         * 1) Null node, valid pathname from root (absolute path)
110249663Sjkim         * 2) Node and valid pathname (path relative to Node)
111249663Sjkim         * 3) Node, Null pathname
112249112Sjkim         */
113249663Sjkim        Status = AcpiNsGetNode (Info->PrefixNode, Info->RelativePathname,
114249663Sjkim            ACPI_NS_NO_UPSEARCH, &Info->Node);
115249112Sjkim        if (ACPI_FAILURE (Status))
116249112Sjkim        {
117249112Sjkim            return_ACPI_STATUS (Status);
118249112Sjkim        }
11991116Smsmith    }
12067754Smsmith
12167754Smsmith    /*
122249663Sjkim     * For a method alias, we must grab the actual method node so that
123249663Sjkim     * proper scoping context will be established before execution.
124128212Snjl     */
125249663Sjkim    if (AcpiNsGetType (Info->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS)
126128212Snjl    {
127249663Sjkim        Info->Node = ACPI_CAST_PTR (
128249663Sjkim            ACPI_NAMESPACE_NODE, Info->Node->Object);
129128212Snjl    }
130128212Snjl
131249663Sjkim    /* Complete the info block initialization */
132167802Sjkim
133249663Sjkim    Info->ReturnObject = NULL;
134249663Sjkim    Info->NodeFlags = Info->Node->Flags;
135249663Sjkim    Info->ObjDesc = AcpiNsGetAttachedObject (Info->Node);
136193267Sjkim
137249663Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
138249663Sjkim        Info->RelativePathname, Info->Node,
139249663Sjkim        AcpiNsGetAttachedObject (Info->Node)));
140249663Sjkim
141249663Sjkim    /* Get info if we have a predefined name (_HID, etc.) */
142249663Sjkim
143249663Sjkim    Info->Predefined = AcpiUtMatchPredefinedMethod (Info->Node->Name.Ascii);
144249663Sjkim
145249663Sjkim    /* Get the full pathname to the object, for use in warning messages */
146249663Sjkim
147306536Sjkim    Info->FullPathname = AcpiNsGetNormalizedPathname (Info->Node, TRUE);
148249663Sjkim    if (!Info->FullPathname)
149249663Sjkim    {
150249663Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
151249663Sjkim    }
152249663Sjkim
153249663Sjkim    /* Count the number of arguments being passed in */
154249663Sjkim
155249663Sjkim    Info->ParamCount = 0;
156249663Sjkim    if (Info->Parameters)
157249663Sjkim    {
158249663Sjkim        while (Info->Parameters[Info->ParamCount])
159249663Sjkim        {
160249663Sjkim            Info->ParamCount++;
161249663Sjkim        }
162249663Sjkim
163249663Sjkim        /* Warn on impossible argument count */
164249663Sjkim
165249663Sjkim        if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
166249663Sjkim        {
167249663Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS,
168249663Sjkim                "Excess arguments (%u) - using only %u",
169249663Sjkim                Info->ParamCount, ACPI_METHOD_NUM_ARGS));
170249663Sjkim
171249663Sjkim            Info->ParamCount = ACPI_METHOD_NUM_ARGS;
172249663Sjkim        }
173249663Sjkim    }
174249663Sjkim
175128212Snjl    /*
176249663Sjkim     * For predefined names: Check that the declared argument count
177249663Sjkim     * matches the ACPI spec -- otherwise this is a BIOS error.
178249663Sjkim     */
179249663Sjkim    AcpiNsCheckAcpiCompliance (Info->FullPathname, Info->Node,
180249663Sjkim        Info->Predefined);
181249663Sjkim
182249663Sjkim    /*
183249663Sjkim     * For all names: Check that the incoming argument count for
184249663Sjkim     * this method/object matches the actual ASL/AML definition.
185249663Sjkim     */
186249663Sjkim    AcpiNsCheckArgumentCount (Info->FullPathname, Info->Node,
187249663Sjkim        Info->ParamCount, Info->Predefined);
188249663Sjkim
189249663Sjkim    /* For predefined names: Typecheck all incoming arguments */
190249663Sjkim
191249663Sjkim    AcpiNsCheckArgumentTypes (Info);
192249663Sjkim
193249663Sjkim    /*
194249663Sjkim     * Three major evaluation cases:
195167802Sjkim     *
196249663Sjkim     * 1) Object types that cannot be evaluated by definition
197249663Sjkim     * 2) The object is a control method -- execute it
198249663Sjkim     * 3) The object is not a method -- just return it's current value
19967754Smsmith     */
200249663Sjkim    switch (AcpiNsGetType (Info->Node))
20167754Smsmith    {
202249663Sjkim    case ACPI_TYPE_DEVICE:
203249663Sjkim    case ACPI_TYPE_EVENT:
204249663Sjkim    case ACPI_TYPE_MUTEX:
205249663Sjkim    case ACPI_TYPE_REGION:
206249663Sjkim    case ACPI_TYPE_THERMAL:
207249663Sjkim    case ACPI_TYPE_LOCAL_SCOPE:
20867754Smsmith        /*
209249663Sjkim         * 1) Disallow evaluation of certain object types. For these,
210249663Sjkim         *    object evaluation is undefined and not supported.
21167754Smsmith         */
212249663Sjkim        ACPI_ERROR ((AE_INFO,
213249663Sjkim            "%s: Evaluation of object type [%s] is not supported",
214249663Sjkim            Info->FullPathname,
215249663Sjkim            AcpiUtGetTypeName (Info->Node->Type)));
21667754Smsmith
217249663Sjkim        Status = AE_TYPE;
218249663Sjkim        goto Cleanup;
219249663Sjkim
220249663Sjkim    case ACPI_TYPE_METHOD:
221249663Sjkim        /*
222249663Sjkim         * 2) Object is a control method - execute it
223249663Sjkim         */
224249663Sjkim
225167802Sjkim        /* Verify that there is a method object associated with this node */
22667754Smsmith
227167802Sjkim        if (!Info->ObjDesc)
228167802Sjkim        {
229249663Sjkim            ACPI_ERROR ((AE_INFO, "%s: Method has no attached sub-object",
230249663Sjkim                Info->FullPathname));
231249663Sjkim            Status = AE_NULL_OBJECT;
232249663Sjkim            goto Cleanup;
233167802Sjkim        }
23467754Smsmith
235167802Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
236249663Sjkim            "**** Execute method [%s] at AML address %p length %X\n",
237249663Sjkim            Info->FullPathname,
238167802Sjkim            Info->ObjDesc->Method.AmlStart + 1,
239167802Sjkim            Info->ObjDesc->Method.AmlLength - 1));
24067754Smsmith
241167802Sjkim        /*
242167802Sjkim         * Any namespace deletion must acquire both the namespace and
243167802Sjkim         * interpreter locks to ensure that no thread is using the portion of
244167802Sjkim         * the namespace that is being deleted.
245167802Sjkim         *
246167802Sjkim         * Execute the method via the interpreter. The interpreter is locked
247167802Sjkim         * here before calling into the AML parser
248167802Sjkim         */
249167802Sjkim        AcpiExEnterInterpreter ();
250167802Sjkim        Status = AcpiPsExecuteMethod (Info);
251167802Sjkim        AcpiExExitInterpreter ();
252249663Sjkim        break;
253249663Sjkim
254249663Sjkim    default:
255167802Sjkim        /*
256249663Sjkim         * 3) All other non-method objects -- get the current object value
257167802Sjkim         */
25877424Smsmith
259167802Sjkim        /*
260249663Sjkim         * Some objects require additional resolution steps (e.g., the Node
261249663Sjkim         * may be a field that must be read, etc.) -- we can't just grab
262249663Sjkim         * the object out of the node.
263167802Sjkim         *
264167802Sjkim         * Use ResolveNodeToValue() to get the associated value.
265167802Sjkim         *
266167802Sjkim         * NOTE: we can get away with passing in NULL for a walk state because
267249663Sjkim         * the Node is guaranteed to not be a reference to either a method
268167802Sjkim         * local or a method argument (because this interface is never called
269167802Sjkim         * from a running method.)
270167802Sjkim         *
271167802Sjkim         * Even though we do not directly invoke the interpreter for object
272249663Sjkim         * resolution, we must lock it because we could access an OpRegion.
273249663Sjkim         * The OpRegion access code assumes that the interpreter is locked.
274167802Sjkim         */
275167802Sjkim        AcpiExEnterInterpreter ();
27667754Smsmith
277249663Sjkim        /* TBD: ResolveNodeToValue has a strange interface, fix */
27883174Smsmith
279249663Sjkim        Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->Node);
280249663Sjkim
281249663Sjkim        Status = AcpiExResolveNodeToValue (ACPI_CAST_INDIRECT_PTR (
282249663Sjkim            ACPI_NAMESPACE_NODE, &Info->ReturnObject), NULL);
283167802Sjkim        AcpiExExitInterpreter ();
28467754Smsmith
285249663Sjkim        if (ACPI_FAILURE (Status))
28677424Smsmith        {
287306536Sjkim            Info->ReturnObject = NULL;
288249663Sjkim            goto Cleanup;
289249663Sjkim        }
290167802Sjkim
291249663Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returned object %p [%s]\n",
292249663Sjkim            Info->ReturnObject,
293249663Sjkim            AcpiUtGetObjectTypeName (Info->ReturnObject)));
294249663Sjkim
295249663Sjkim        Status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */
296249663Sjkim        break;
29767754Smsmith    }
29867754Smsmith
299167802Sjkim    /*
300249663Sjkim     * For predefined names, check the return value against the ACPI
301249663Sjkim     * specification. Some incorrect return value types are repaired.
302167802Sjkim     */
303249663Sjkim    (void) AcpiNsCheckReturnValue (Info->Node, Info, Info->ParamCount,
304249663Sjkim        Status, &Info->ReturnObject);
305193267Sjkim
306193267Sjkim    /* Check if there is a return value that must be dealt with */
307193267Sjkim
308167802Sjkim    if (Status == AE_CTRL_RETURN_VALUE)
309167802Sjkim    {
310167802Sjkim        /* If caller does not want the return value, delete it */
31167754Smsmith
312167802Sjkim        if (Info->Flags & ACPI_IGNORE_RETURN_VALUE)
313167802Sjkim        {
314167802Sjkim            AcpiUtRemoveReference (Info->ReturnObject);
315167802Sjkim            Info->ReturnObject = NULL;
316167802Sjkim        }
317167802Sjkim
318167802Sjkim        /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
319167802Sjkim
320167802Sjkim        Status = AE_OK;
321167802Sjkim    }
322167802Sjkim
323167802Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
324249663Sjkim        "*** Completed evaluation of object %s ***\n",
325249663Sjkim        Info->RelativePathname));
326167802Sjkim
327249663SjkimCleanup:
328167802Sjkim    /*
329167802Sjkim     * Namespace was unlocked by the handling AcpiNs* function, so we
330249663Sjkim     * just free the pathname and return
331167802Sjkim     */
332249663Sjkim    ACPI_FREE (Info->FullPathname);
333249663Sjkim    Info->FullPathname = NULL;
33477424Smsmith    return_ACPI_STATUS (Status);
33591116Smsmith}
33677424Smsmith
337197104Sjkim
338197104Sjkim/*******************************************************************************
339197104Sjkim *
340197104Sjkim * FUNCTION:    AcpiNsExecModuleCodeList
341197104Sjkim *
342197104Sjkim * PARAMETERS:  None
343197104Sjkim *
344197104Sjkim * RETURN:      None. Exceptions during method execution are ignored, since
345197104Sjkim *              we cannot abort a table load.
346197104Sjkim *
347197104Sjkim * DESCRIPTION: Execute all elements of the global module-level code list.
348197104Sjkim *              Each element is executed as a single control method.
349197104Sjkim *
350197104Sjkim ******************************************************************************/
351197104Sjkim
352197104Sjkimvoid
353197104SjkimAcpiNsExecModuleCodeList (
354197104Sjkim    void)
355197104Sjkim{
356197104Sjkim    ACPI_OPERAND_OBJECT     *Prev;
357197104Sjkim    ACPI_OPERAND_OBJECT     *Next;
358197104Sjkim    ACPI_EVALUATE_INFO      *Info;
359197104Sjkim    UINT32                  MethodCount = 0;
360197104Sjkim
361197104Sjkim
362197104Sjkim    ACPI_FUNCTION_TRACE (NsExecModuleCodeList);
363197104Sjkim
364197104Sjkim
365197104Sjkim    /* Exit now if the list is empty */
366197104Sjkim
367197104Sjkim    Next = AcpiGbl_ModuleCodeList;
368197104Sjkim    if (!Next)
369197104Sjkim    {
370197104Sjkim        return_VOID;
371197104Sjkim    }
372197104Sjkim
373197104Sjkim    /* Allocate the evaluation information block */
374197104Sjkim
375197104Sjkim    Info = ACPI_ALLOCATE (sizeof (ACPI_EVALUATE_INFO));
376197104Sjkim    if (!Info)
377197104Sjkim    {
378197104Sjkim        return_VOID;
379197104Sjkim    }
380197104Sjkim
381197104Sjkim    /* Walk the list, executing each "method" */
382197104Sjkim
383197104Sjkim    while (Next)
384197104Sjkim    {
385197104Sjkim        Prev = Next;
386197104Sjkim        Next = Next->Method.Mutex;
387197104Sjkim
388197104Sjkim        /* Clear the link field and execute the method */
389197104Sjkim
390197104Sjkim        Prev->Method.Mutex = NULL;
391197104Sjkim        AcpiNsExecModuleCode (Prev, Info);
392197104Sjkim        MethodCount++;
393197104Sjkim
394197104Sjkim        /* Delete the (temporary) method object */
395197104Sjkim
396197104Sjkim        AcpiUtRemoveReference (Prev);
397197104Sjkim    }
398197104Sjkim
399306536Sjkim    ACPI_INFO ((
400197104Sjkim        "Executed %u blocks of module-level executable AML code",
401197104Sjkim        MethodCount));
402197104Sjkim
403197104Sjkim    ACPI_FREE (Info);
404197104Sjkim    AcpiGbl_ModuleCodeList = NULL;
405197104Sjkim    return_VOID;
406197104Sjkim}
407197104Sjkim
408197104Sjkim
409197104Sjkim/*******************************************************************************
410197104Sjkim *
411197104Sjkim * FUNCTION:    AcpiNsExecModuleCode
412197104Sjkim *
413197104Sjkim * PARAMETERS:  MethodObj           - Object container for the module-level code
414197104Sjkim *              Info                - Info block for method evaluation
415197104Sjkim *
416197104Sjkim * RETURN:      None. Exceptions during method execution are ignored, since
417197104Sjkim *              we cannot abort a table load.
418197104Sjkim *
419197104Sjkim * DESCRIPTION: Execute a control method containing a block of module-level
420197104Sjkim *              executable AML code. The control method is temporarily
421197104Sjkim *              installed to the root node, then evaluated.
422197104Sjkim *
423197104Sjkim ******************************************************************************/
424197104Sjkim
425197104Sjkimstatic void
426197104SjkimAcpiNsExecModuleCode (
427197104Sjkim    ACPI_OPERAND_OBJECT     *MethodObj,
428197104Sjkim    ACPI_EVALUATE_INFO      *Info)
429197104Sjkim{
430199337Sjkim    ACPI_OPERAND_OBJECT     *ParentObj;
431199337Sjkim    ACPI_NAMESPACE_NODE     *ParentNode;
432199337Sjkim    ACPI_OBJECT_TYPE        Type;
433197104Sjkim    ACPI_STATUS             Status;
434197104Sjkim
435197104Sjkim
436197104Sjkim    ACPI_FUNCTION_TRACE (NsExecModuleCode);
437197104Sjkim
438197104Sjkim
439199337Sjkim    /*
440199337Sjkim     * Get the parent node. We cheat by using the NextObject field
441199337Sjkim     * of the method object descriptor.
442199337Sjkim     */
443306536Sjkim    ParentNode = ACPI_CAST_PTR (
444306536Sjkim        ACPI_NAMESPACE_NODE, MethodObj->Method.NextObject);
445199337Sjkim    Type = AcpiNsGetType (ParentNode);
446199337Sjkim
447200553Sjkim    /*
448200553Sjkim     * Get the region handler and save it in the method object. We may need
449200553Sjkim     * this if an operation region declaration causes a _REG method to be run.
450200553Sjkim     *
451200553Sjkim     * We can't do this in AcpiPsLinkModuleCode because
452200553Sjkim     * AcpiGbl_RootNode->Object is NULL at PASS1.
453200553Sjkim     */
454200553Sjkim    if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object)
455200553Sjkim    {
456217365Sjkim        MethodObj->Method.Dispatch.Handler =
457200553Sjkim            ParentNode->Object->Device.Handler;
458200553Sjkim    }
459200553Sjkim
460199337Sjkim    /* Must clear NextObject (AcpiNsAttachObject needs the field) */
461199337Sjkim
462199337Sjkim    MethodObj->Method.NextObject = NULL;
463199337Sjkim
464197104Sjkim    /* Initialize the evaluation information block */
465197104Sjkim
466306536Sjkim    memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
467199337Sjkim    Info->PrefixNode = ParentNode;
468197104Sjkim
469197104Sjkim    /*
470306536Sjkim     * Get the currently attached parent object. Add a reference,
471306536Sjkim     * because the ref count will be decreased when the method object
472306536Sjkim     * is installed to the parent node.
473197104Sjkim     */
474199337Sjkim    ParentObj = AcpiNsGetAttachedObject (ParentNode);
475199337Sjkim    if (ParentObj)
476199337Sjkim    {
477199337Sjkim        AcpiUtAddReference (ParentObj);
478199337Sjkim    }
479197104Sjkim
480199337Sjkim    /* Install the method (module-level code) in the parent node */
481197104Sjkim
482306536Sjkim    Status = AcpiNsAttachObject (ParentNode, MethodObj, ACPI_TYPE_METHOD);
483197104Sjkim    if (ACPI_FAILURE (Status))
484197104Sjkim    {
485197104Sjkim        goto Exit;
486197104Sjkim    }
487197104Sjkim
488199337Sjkim    /* Execute the parent node as a control method */
489197104Sjkim
490197104Sjkim    Status = AcpiNsEvaluate (Info);
491197104Sjkim
492306536Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_INIT_NAMES,
493306536Sjkim        "Executed module-level code at %p\n",
494197104Sjkim        MethodObj->Method.AmlStart));
495197104Sjkim
496200553Sjkim    /* Delete a possible implicit return value (in slack mode) */
497200553Sjkim
498200553Sjkim    if (Info->ReturnObject)
499200553Sjkim    {
500200553Sjkim        AcpiUtRemoveReference (Info->ReturnObject);
501200553Sjkim    }
502200553Sjkim
503197104Sjkim    /* Detach the temporary method object */
504197104Sjkim
505199337Sjkim    AcpiNsDetachObject (ParentNode);
506197104Sjkim
507199337Sjkim    /* Restore the original parent object */
508197104Sjkim
509199337Sjkim    if (ParentObj)
510199337Sjkim    {
511199337Sjkim        Status = AcpiNsAttachObject (ParentNode, ParentObj, Type);
512199337Sjkim    }
513199337Sjkim    else
514199337Sjkim    {
515199337Sjkim        ParentNode->Type = (UINT8) Type;
516199337Sjkim    }
517197104Sjkim
518197104SjkimExit:
519199337Sjkim    if (ParentObj)
520199337Sjkim    {
521199337Sjkim        AcpiUtRemoveReference (ParentObj);
522199337Sjkim    }
523197104Sjkim    return_VOID;
524197104Sjkim}
525