167754Smsmith/*******************************************************************************
267754Smsmith *
3167802Sjkim * Module Name: nseval - Object evaluation, includes control method execution
467754Smsmith *
567754Smsmith ******************************************************************************/
667754Smsmith
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, 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
4467754Smsmith#define __NSEVAL_C__
4567754Smsmith
46193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
47193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
48193341Sjkim#include <contrib/dev/acpica/include/acparser.h>
49193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
50193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
5167754Smsmith
5267754Smsmith
5377424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5491116Smsmith        ACPI_MODULE_NAME    ("nseval")
5567754Smsmith
56197104Sjkim/* Local prototypes */
5767754Smsmith
58197104Sjkimstatic void
59197104SjkimAcpiNsExecModuleCode (
60197104Sjkim    ACPI_OPERAND_OBJECT     *MethodObj,
61197104Sjkim    ACPI_EVALUATE_INFO      *Info);
62197104Sjkim
63197104Sjkim
6467754Smsmith/*******************************************************************************
6567754Smsmith *
66167802Sjkim * FUNCTION:    AcpiNsEvaluate
6767754Smsmith *
68167802Sjkim * PARAMETERS:  Info            - Evaluation info block, contains:
69167802Sjkim *                  PrefixNode      - Prefix or Method/Object Node to execute
70249663Sjkim *                  RelativePath    - Name of method to execute, If NULL, the
71167802Sjkim *                                    Node is the object to execute
72151937Sjkim *                  Parameters      - List of parameters to pass to the method,
73151937Sjkim *                                    terminated by NULL. Params itself may be
7467754Smsmith *                                    NULL if no parameters are being passed.
75151937Sjkim *                  ReturnObject    - Where to put method's return value (if
76151937Sjkim *                                    any). If NULL, no value is returned.
77151937Sjkim *                  ParameterType   - Type of Parameter list
78151937Sjkim *                  ReturnObject    - Where to put method's return value (if
79151937Sjkim *                                    any). If NULL, no value is returned.
80167802Sjkim *                  Flags           - ACPI_IGNORE_RETURN_VALUE to delete return
8167754Smsmith *
8267754Smsmith * RETURN:      Status
8367754Smsmith *
84167802Sjkim * DESCRIPTION: Execute a control method or return the current value of an
85167802Sjkim *              ACPI namespace object.
8667754Smsmith *
87167802Sjkim * MUTEX:       Locks interpreter
8867754Smsmith *
8967754Smsmith ******************************************************************************/
9067754Smsmith
9167754SmsmithACPI_STATUS
92167802SjkimAcpiNsEvaluate (
93167802Sjkim    ACPI_EVALUATE_INFO      *Info)
9467754Smsmith{
9567754Smsmith    ACPI_STATUS             Status;
9667754Smsmith
9767754Smsmith
98167802Sjkim    ACPI_FUNCTION_TRACE (NsEvaluate);
9967754Smsmith
10067754Smsmith
101129684Snjl    if (!Info)
10267754Smsmith    {
10367754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
10467754Smsmith    }
10567754Smsmith
106249663Sjkim    if (!Info->Node)
10791116Smsmith    {
108249112Sjkim        /*
109249663Sjkim         * Get the actual namespace node for the target object if we
110249663Sjkim         * need to. Handles these cases:
111249112Sjkim         *
112249663Sjkim         * 1) Null node, valid pathname from root (absolute path)
113249663Sjkim         * 2) Node and valid pathname (path relative to Node)
114249663Sjkim         * 3) Node, Null pathname
115249112Sjkim         */
116249663Sjkim        Status = AcpiNsGetNode (Info->PrefixNode, Info->RelativePathname,
117249663Sjkim            ACPI_NS_NO_UPSEARCH, &Info->Node);
118249112Sjkim        if (ACPI_FAILURE (Status))
119249112Sjkim        {
120249112Sjkim            return_ACPI_STATUS (Status);
121249112Sjkim        }
12291116Smsmith    }
12367754Smsmith
12467754Smsmith    /*
125249663Sjkim     * For a method alias, we must grab the actual method node so that
126249663Sjkim     * proper scoping context will be established before execution.
127128212Snjl     */
128249663Sjkim    if (AcpiNsGetType (Info->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS)
129128212Snjl    {
130249663Sjkim        Info->Node = ACPI_CAST_PTR (
131249663Sjkim            ACPI_NAMESPACE_NODE, Info->Node->Object);
132128212Snjl    }
133128212Snjl
134249663Sjkim    /* Complete the info block initialization */
135167802Sjkim
136249663Sjkim    Info->ReturnObject = NULL;
137249663Sjkim    Info->NodeFlags = Info->Node->Flags;
138249663Sjkim    Info->ObjDesc = AcpiNsGetAttachedObject (Info->Node);
139193267Sjkim
140249663Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
141249663Sjkim        Info->RelativePathname, Info->Node,
142249663Sjkim        AcpiNsGetAttachedObject (Info->Node)));
143249663Sjkim
144249663Sjkim    /* Get info if we have a predefined name (_HID, etc.) */
145249663Sjkim
146249663Sjkim    Info->Predefined = AcpiUtMatchPredefinedMethod (Info->Node->Name.Ascii);
147249663Sjkim
148249663Sjkim    /* Get the full pathname to the object, for use in warning messages */
149249663Sjkim
150249663Sjkim    Info->FullPathname = AcpiNsGetExternalPathname (Info->Node);
151249663Sjkim    if (!Info->FullPathname)
152249663Sjkim    {
153249663Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
154249663Sjkim    }
155249663Sjkim
156249663Sjkim    /* Count the number of arguments being passed in */
157249663Sjkim
158249663Sjkim    Info->ParamCount = 0;
159249663Sjkim    if (Info->Parameters)
160249663Sjkim    {
161249663Sjkim        while (Info->Parameters[Info->ParamCount])
162249663Sjkim        {
163249663Sjkim            Info->ParamCount++;
164249663Sjkim        }
165249663Sjkim
166249663Sjkim        /* Warn on impossible argument count */
167249663Sjkim
168249663Sjkim        if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
169249663Sjkim        {
170249663Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS,
171249663Sjkim                "Excess arguments (%u) - using only %u",
172249663Sjkim                Info->ParamCount, ACPI_METHOD_NUM_ARGS));
173249663Sjkim
174249663Sjkim            Info->ParamCount = ACPI_METHOD_NUM_ARGS;
175249663Sjkim        }
176249663Sjkim    }
177249663Sjkim
178128212Snjl    /*
179249663Sjkim     * For predefined names: Check that the declared argument count
180249663Sjkim     * matches the ACPI spec -- otherwise this is a BIOS error.
181249663Sjkim     */
182249663Sjkim    AcpiNsCheckAcpiCompliance (Info->FullPathname, Info->Node,
183249663Sjkim        Info->Predefined);
184249663Sjkim
185249663Sjkim    /*
186249663Sjkim     * For all names: Check that the incoming argument count for
187249663Sjkim     * this method/object matches the actual ASL/AML definition.
188249663Sjkim     */
189249663Sjkim    AcpiNsCheckArgumentCount (Info->FullPathname, Info->Node,
190249663Sjkim        Info->ParamCount, Info->Predefined);
191249663Sjkim
192249663Sjkim    /* For predefined names: Typecheck all incoming arguments */
193249663Sjkim
194249663Sjkim    AcpiNsCheckArgumentTypes (Info);
195249663Sjkim
196249663Sjkim    /*
197249663Sjkim     * Three major evaluation cases:
198167802Sjkim     *
199249663Sjkim     * 1) Object types that cannot be evaluated by definition
200249663Sjkim     * 2) The object is a control method -- execute it
201249663Sjkim     * 3) The object is not a method -- just return it's current value
20267754Smsmith     */
203249663Sjkim    switch (AcpiNsGetType (Info->Node))
20467754Smsmith    {
205249663Sjkim    case ACPI_TYPE_DEVICE:
206249663Sjkim    case ACPI_TYPE_EVENT:
207249663Sjkim    case ACPI_TYPE_MUTEX:
208249663Sjkim    case ACPI_TYPE_REGION:
209249663Sjkim    case ACPI_TYPE_THERMAL:
210249663Sjkim    case ACPI_TYPE_LOCAL_SCOPE:
21167754Smsmith        /*
212249663Sjkim         * 1) Disallow evaluation of certain object types. For these,
213249663Sjkim         *    object evaluation is undefined and not supported.
21467754Smsmith         */
215249663Sjkim        ACPI_ERROR ((AE_INFO,
216249663Sjkim            "%s: Evaluation of object type [%s] is not supported",
217249663Sjkim            Info->FullPathname,
218249663Sjkim            AcpiUtGetTypeName (Info->Node->Type)));
21967754Smsmith
220249663Sjkim        Status = AE_TYPE;
221249663Sjkim        goto Cleanup;
222249663Sjkim
223249663Sjkim    case ACPI_TYPE_METHOD:
224249663Sjkim        /*
225249663Sjkim         * 2) Object is a control method - execute it
226249663Sjkim         */
227249663Sjkim
228167802Sjkim        /* Verify that there is a method object associated with this node */
22967754Smsmith
230167802Sjkim        if (!Info->ObjDesc)
231167802Sjkim        {
232249663Sjkim            ACPI_ERROR ((AE_INFO, "%s: Method has no attached sub-object",
233249663Sjkim                Info->FullPathname));
234249663Sjkim            Status = AE_NULL_OBJECT;
235249663Sjkim            goto Cleanup;
236167802Sjkim        }
23767754Smsmith
238167802Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
239249663Sjkim            "**** Execute method [%s] at AML address %p length %X\n",
240249663Sjkim            Info->FullPathname,
241167802Sjkim            Info->ObjDesc->Method.AmlStart + 1,
242167802Sjkim            Info->ObjDesc->Method.AmlLength - 1));
24367754Smsmith
244167802Sjkim        /*
245167802Sjkim         * Any namespace deletion must acquire both the namespace and
246167802Sjkim         * interpreter locks to ensure that no thread is using the portion of
247167802Sjkim         * the namespace that is being deleted.
248167802Sjkim         *
249167802Sjkim         * Execute the method via the interpreter. The interpreter is locked
250167802Sjkim         * here before calling into the AML parser
251167802Sjkim         */
252167802Sjkim        AcpiExEnterInterpreter ();
253167802Sjkim        Status = AcpiPsExecuteMethod (Info);
254167802Sjkim        AcpiExExitInterpreter ();
255249663Sjkim        break;
256249663Sjkim
257249663Sjkim    default:
258167802Sjkim        /*
259249663Sjkim         * 3) All other non-method objects -- get the current object value
260167802Sjkim         */
26177424Smsmith
262167802Sjkim        /*
263249663Sjkim         * Some objects require additional resolution steps (e.g., the Node
264249663Sjkim         * may be a field that must be read, etc.) -- we can't just grab
265249663Sjkim         * the object out of the node.
266167802Sjkim         *
267167802Sjkim         * Use ResolveNodeToValue() to get the associated value.
268167802Sjkim         *
269167802Sjkim         * NOTE: we can get away with passing in NULL for a walk state because
270249663Sjkim         * the Node is guaranteed to not be a reference to either a method
271167802Sjkim         * local or a method argument (because this interface is never called
272167802Sjkim         * from a running method.)
273167802Sjkim         *
274167802Sjkim         * Even though we do not directly invoke the interpreter for object
275249663Sjkim         * resolution, we must lock it because we could access an OpRegion.
276249663Sjkim         * The OpRegion access code assumes that the interpreter is locked.
277167802Sjkim         */
278167802Sjkim        AcpiExEnterInterpreter ();
27967754Smsmith
280249663Sjkim        /* TBD: ResolveNodeToValue has a strange interface, fix */
28183174Smsmith
282249663Sjkim        Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->Node);
283249663Sjkim
284249663Sjkim        Status = AcpiExResolveNodeToValue (ACPI_CAST_INDIRECT_PTR (
285249663Sjkim            ACPI_NAMESPACE_NODE, &Info->ReturnObject), NULL);
286167802Sjkim        AcpiExExitInterpreter ();
28767754Smsmith
288249663Sjkim        if (ACPI_FAILURE (Status))
28977424Smsmith        {
290249663Sjkim            goto Cleanup;
291249663Sjkim        }
292167802Sjkim
293249663Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returned object %p [%s]\n",
294249663Sjkim            Info->ReturnObject,
295249663Sjkim            AcpiUtGetObjectTypeName (Info->ReturnObject)));
296249663Sjkim
297249663Sjkim        Status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */
298249663Sjkim        break;
29967754Smsmith    }
30067754Smsmith
301167802Sjkim    /*
302249663Sjkim     * For predefined names, check the return value against the ACPI
303249663Sjkim     * specification. Some incorrect return value types are repaired.
304167802Sjkim     */
305249663Sjkim    (void) AcpiNsCheckReturnValue (Info->Node, Info, Info->ParamCount,
306249663Sjkim        Status, &Info->ReturnObject);
307193267Sjkim
308193267Sjkim    /* Check if there is a return value that must be dealt with */
309193267Sjkim
310167802Sjkim    if (Status == AE_CTRL_RETURN_VALUE)
311167802Sjkim    {
312167802Sjkim        /* If caller does not want the return value, delete it */
31367754Smsmith
314167802Sjkim        if (Info->Flags & ACPI_IGNORE_RETURN_VALUE)
315167802Sjkim        {
316167802Sjkim            AcpiUtRemoveReference (Info->ReturnObject);
317167802Sjkim            Info->ReturnObject = NULL;
318167802Sjkim        }
319167802Sjkim
320167802Sjkim        /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
321167802Sjkim
322167802Sjkim        Status = AE_OK;
323167802Sjkim    }
324167802Sjkim
325167802Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
326249663Sjkim        "*** Completed evaluation of object %s ***\n",
327249663Sjkim        Info->RelativePathname));
328167802Sjkim
329249663SjkimCleanup:
330167802Sjkim    /*
331167802Sjkim     * Namespace was unlocked by the handling AcpiNs* function, so we
332249663Sjkim     * just free the pathname and return
333167802Sjkim     */
334249663Sjkim    ACPI_FREE (Info->FullPathname);
335249663Sjkim    Info->FullPathname = NULL;
33677424Smsmith    return_ACPI_STATUS (Status);
33791116Smsmith}
33877424Smsmith
339197104Sjkim
340197104Sjkim/*******************************************************************************
341197104Sjkim *
342197104Sjkim * FUNCTION:    AcpiNsExecModuleCodeList
343197104Sjkim *
344197104Sjkim * PARAMETERS:  None
345197104Sjkim *
346197104Sjkim * RETURN:      None. Exceptions during method execution are ignored, since
347197104Sjkim *              we cannot abort a table load.
348197104Sjkim *
349197104Sjkim * DESCRIPTION: Execute all elements of the global module-level code list.
350197104Sjkim *              Each element is executed as a single control method.
351197104Sjkim *
352197104Sjkim ******************************************************************************/
353197104Sjkim
354197104Sjkimvoid
355197104SjkimAcpiNsExecModuleCodeList (
356197104Sjkim    void)
357197104Sjkim{
358197104Sjkim    ACPI_OPERAND_OBJECT     *Prev;
359197104Sjkim    ACPI_OPERAND_OBJECT     *Next;
360197104Sjkim    ACPI_EVALUATE_INFO      *Info;
361197104Sjkim    UINT32                  MethodCount = 0;
362197104Sjkim
363197104Sjkim
364197104Sjkim    ACPI_FUNCTION_TRACE (NsExecModuleCodeList);
365197104Sjkim
366197104Sjkim
367197104Sjkim    /* Exit now if the list is empty */
368197104Sjkim
369197104Sjkim    Next = AcpiGbl_ModuleCodeList;
370197104Sjkim    if (!Next)
371197104Sjkim    {
372197104Sjkim        return_VOID;
373197104Sjkim    }
374197104Sjkim
375197104Sjkim    /* Allocate the evaluation information block */
376197104Sjkim
377197104Sjkim    Info = ACPI_ALLOCATE (sizeof (ACPI_EVALUATE_INFO));
378197104Sjkim    if (!Info)
379197104Sjkim    {
380197104Sjkim        return_VOID;
381197104Sjkim    }
382197104Sjkim
383197104Sjkim    /* Walk the list, executing each "method" */
384197104Sjkim
385197104Sjkim    while (Next)
386197104Sjkim    {
387197104Sjkim        Prev = Next;
388197104Sjkim        Next = Next->Method.Mutex;
389197104Sjkim
390197104Sjkim        /* Clear the link field and execute the method */
391197104Sjkim
392197104Sjkim        Prev->Method.Mutex = NULL;
393197104Sjkim        AcpiNsExecModuleCode (Prev, Info);
394197104Sjkim        MethodCount++;
395197104Sjkim
396197104Sjkim        /* Delete the (temporary) method object */
397197104Sjkim
398197104Sjkim        AcpiUtRemoveReference (Prev);
399197104Sjkim    }
400197104Sjkim
401197104Sjkim    ACPI_INFO ((AE_INFO,
402197104Sjkim        "Executed %u blocks of module-level executable AML code",
403197104Sjkim        MethodCount));
404197104Sjkim
405197104Sjkim    ACPI_FREE (Info);
406197104Sjkim    AcpiGbl_ModuleCodeList = NULL;
407197104Sjkim    return_VOID;
408197104Sjkim}
409197104Sjkim
410197104Sjkim
411197104Sjkim/*******************************************************************************
412197104Sjkim *
413197104Sjkim * FUNCTION:    AcpiNsExecModuleCode
414197104Sjkim *
415197104Sjkim * PARAMETERS:  MethodObj           - Object container for the module-level code
416197104Sjkim *              Info                - Info block for method evaluation
417197104Sjkim *
418197104Sjkim * RETURN:      None. Exceptions during method execution are ignored, since
419197104Sjkim *              we cannot abort a table load.
420197104Sjkim *
421197104Sjkim * DESCRIPTION: Execute a control method containing a block of module-level
422197104Sjkim *              executable AML code. The control method is temporarily
423197104Sjkim *              installed to the root node, then evaluated.
424197104Sjkim *
425197104Sjkim ******************************************************************************/
426197104Sjkim
427197104Sjkimstatic void
428197104SjkimAcpiNsExecModuleCode (
429197104Sjkim    ACPI_OPERAND_OBJECT     *MethodObj,
430197104Sjkim    ACPI_EVALUATE_INFO      *Info)
431197104Sjkim{
432199337Sjkim    ACPI_OPERAND_OBJECT     *ParentObj;
433199337Sjkim    ACPI_NAMESPACE_NODE     *ParentNode;
434199337Sjkim    ACPI_OBJECT_TYPE        Type;
435197104Sjkim    ACPI_STATUS             Status;
436197104Sjkim
437197104Sjkim
438197104Sjkim    ACPI_FUNCTION_TRACE (NsExecModuleCode);
439197104Sjkim
440197104Sjkim
441199337Sjkim    /*
442199337Sjkim     * Get the parent node. We cheat by using the NextObject field
443199337Sjkim     * of the method object descriptor.
444199337Sjkim     */
445199337Sjkim    ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
446199337Sjkim                    MethodObj->Method.NextObject);
447199337Sjkim    Type = AcpiNsGetType (ParentNode);
448199337Sjkim
449200553Sjkim    /*
450200553Sjkim     * Get the region handler and save it in the method object. We may need
451200553Sjkim     * this if an operation region declaration causes a _REG method to be run.
452200553Sjkim     *
453200553Sjkim     * We can't do this in AcpiPsLinkModuleCode because
454200553Sjkim     * AcpiGbl_RootNode->Object is NULL at PASS1.
455200553Sjkim     */
456200553Sjkim    if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object)
457200553Sjkim    {
458217365Sjkim        MethodObj->Method.Dispatch.Handler =
459200553Sjkim            ParentNode->Object->Device.Handler;
460200553Sjkim    }
461200553Sjkim
462199337Sjkim    /* Must clear NextObject (AcpiNsAttachObject needs the field) */
463199337Sjkim
464199337Sjkim    MethodObj->Method.NextObject = NULL;
465199337Sjkim
466197104Sjkim    /* Initialize the evaluation information block */
467197104Sjkim
468197104Sjkim    ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO));
469199337Sjkim    Info->PrefixNode = ParentNode;
470197104Sjkim
471197104Sjkim    /*
472199337Sjkim     * Get the currently attached parent object. Add a reference, because the
473197104Sjkim     * ref count will be decreased when the method object is installed to
474199337Sjkim     * the parent node.
475197104Sjkim     */
476199337Sjkim    ParentObj = AcpiNsGetAttachedObject (ParentNode);
477199337Sjkim    if (ParentObj)
478199337Sjkim    {
479199337Sjkim        AcpiUtAddReference (ParentObj);
480199337Sjkim    }
481197104Sjkim
482199337Sjkim    /* Install the method (module-level code) in the parent node */
483197104Sjkim
484199337Sjkim    Status = AcpiNsAttachObject (ParentNode, MethodObj,
485197104Sjkim                ACPI_TYPE_METHOD);
486197104Sjkim    if (ACPI_FAILURE (Status))
487197104Sjkim    {
488197104Sjkim        goto Exit;
489197104Sjkim    }
490197104Sjkim
491199337Sjkim    /* Execute the parent node as a control method */
492197104Sjkim
493197104Sjkim    Status = AcpiNsEvaluate (Info);
494197104Sjkim
495197104Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n",
496197104Sjkim        MethodObj->Method.AmlStart));
497197104Sjkim
498200553Sjkim    /* Delete a possible implicit return value (in slack mode) */
499200553Sjkim
500200553Sjkim    if (Info->ReturnObject)
501200553Sjkim    {
502200553Sjkim        AcpiUtRemoveReference (Info->ReturnObject);
503200553Sjkim    }
504200553Sjkim
505197104Sjkim    /* Detach the temporary method object */
506197104Sjkim
507199337Sjkim    AcpiNsDetachObject (ParentNode);
508197104Sjkim
509199337Sjkim    /* Restore the original parent object */
510197104Sjkim
511199337Sjkim    if (ParentObj)
512199337Sjkim    {
513199337Sjkim        Status = AcpiNsAttachObject (ParentNode, ParentObj, Type);
514199337Sjkim    }
515199337Sjkim    else
516199337Sjkim    {
517199337Sjkim        ParentNode->Type = (UINT8) Type;
518199337Sjkim    }
519197104Sjkim
520197104SjkimExit:
521199337Sjkim    if (ParentObj)
522199337Sjkim    {
523199337Sjkim        AcpiUtRemoveReference (ParentObj);
524199337Sjkim    }
525197104Sjkim    return_VOID;
526197104Sjkim}
527