1100966Siwasaki/*******************************************************************************
2100966Siwasaki *
3100966Siwasaki * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4100966Siwasaki *                         ACPI Object evaluation interfaces
5100966Siwasaki *
6100966Siwasaki ******************************************************************************/
7100966Siwasaki
8217365Sjkim/*
9245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
10100966Siwasaki * All rights reserved.
11100966Siwasaki *
12217365Sjkim * Redistribution and use in source and binary forms, with or without
13217365Sjkim * modification, are permitted provided that the following conditions
14217365Sjkim * are met:
15217365Sjkim * 1. Redistributions of source code must retain the above copyright
16217365Sjkim *    notice, this list of conditions, and the following disclaimer,
17217365Sjkim *    without modification.
18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21217365Sjkim *    including a substantially similar Disclaimer requirement for further
22217365Sjkim *    binary redistribution.
23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24217365Sjkim *    of any contributors may be used to endorse or promote products derived
25217365Sjkim *    from this software without specific prior written permission.
26100966Siwasaki *
27217365Sjkim * Alternatively, this software may be distributed under the terms of the
28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29217365Sjkim * Software Foundation.
30100966Siwasaki *
31217365Sjkim * NO WARRANTY
32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
43217365Sjkim */
44100966Siwasaki
45100966Siwasaki
46100966Siwasaki#define __NSXFEVAL_C__
47100966Siwasaki
48193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
49193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
50193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
51193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
52100966Siwasaki
53100966Siwasaki
54100966Siwasaki#define _COMPONENT          ACPI_NAMESPACE
55100966Siwasaki        ACPI_MODULE_NAME    ("nsxfeval")
56100966Siwasaki
57193267Sjkim/* Local prototypes */
58100966Siwasaki
59193267Sjkimstatic void
60193267SjkimAcpiNsResolveReferences (
61193267Sjkim    ACPI_EVALUATE_INFO      *Info);
62193267Sjkim
63193267Sjkim
64100966Siwasaki/*******************************************************************************
65100966Siwasaki *
66100966Siwasaki * FUNCTION:    AcpiEvaluateObjectTyped
67100966Siwasaki *
68100966Siwasaki * PARAMETERS:  Handle              - Object handle (optional)
69151937Sjkim *              Pathname            - Object pathname (optional)
70151937Sjkim *              ExternalParams      - List of parameters to pass to method,
71241973Sjkim *                                    terminated by NULL. May be NULL
72100966Siwasaki *                                    if no parameters are being passed.
73151937Sjkim *              ReturnBuffer        - Where to put method's return value (if
74241973Sjkim *                                    any). If NULL, no value is returned.
75100966Siwasaki *              ReturnType          - Expected type of return object
76100966Siwasaki *
77100966Siwasaki * RETURN:      Status
78100966Siwasaki *
79100966Siwasaki * DESCRIPTION: Find and evaluate the given object, passing the given
80241973Sjkim *              parameters if necessary. One of "Handle" or "Pathname" must
81100966Siwasaki *              be valid (non-null)
82100966Siwasaki *
83100966Siwasaki ******************************************************************************/
84100966Siwasaki
85100966SiwasakiACPI_STATUS
86100966SiwasakiAcpiEvaluateObjectTyped (
87100966Siwasaki    ACPI_HANDLE             Handle,
88100966Siwasaki    ACPI_STRING             Pathname,
89100966Siwasaki    ACPI_OBJECT_LIST        *ExternalParams,
90100966Siwasaki    ACPI_BUFFER             *ReturnBuffer,
91100966Siwasaki    ACPI_OBJECT_TYPE        ReturnType)
92100966Siwasaki{
93100966Siwasaki    ACPI_STATUS             Status;
94100966Siwasaki    BOOLEAN                 MustFree = FALSE;
95100966Siwasaki
96100966Siwasaki
97167802Sjkim    ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
98100966Siwasaki
99100966Siwasaki
100100966Siwasaki    /* Return buffer must be valid */
101100966Siwasaki
102100966Siwasaki    if (!ReturnBuffer)
103100966Siwasaki    {
104100966Siwasaki        return_ACPI_STATUS (AE_BAD_PARAMETER);
105100966Siwasaki    }
106100966Siwasaki
107100966Siwasaki    if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
108100966Siwasaki    {
109100966Siwasaki        MustFree = TRUE;
110100966Siwasaki    }
111100966Siwasaki
112100966Siwasaki    /* Evaluate the object */
113100966Siwasaki
114100966Siwasaki    Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer);
115100966Siwasaki    if (ACPI_FAILURE (Status))
116100966Siwasaki    {
117100966Siwasaki        return_ACPI_STATUS (Status);
118100966Siwasaki    }
119100966Siwasaki
120100966Siwasaki    /* Type ANY means "don't care" */
121100966Siwasaki
122100966Siwasaki    if (ReturnType == ACPI_TYPE_ANY)
123100966Siwasaki    {
124100966Siwasaki        return_ACPI_STATUS (AE_OK);
125100966Siwasaki    }
126100966Siwasaki
127100966Siwasaki    if (ReturnBuffer->Length == 0)
128100966Siwasaki    {
129100966Siwasaki        /* Error because caller specifically asked for a return value */
130100966Siwasaki
131167802Sjkim        ACPI_ERROR ((AE_INFO, "No return value"));
132100966Siwasaki        return_ACPI_STATUS (AE_NULL_OBJECT);
133100966Siwasaki    }
134100966Siwasaki
135100966Siwasaki    /* Examine the object type returned from EvaluateObject */
136100966Siwasaki
137100966Siwasaki    if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
138100966Siwasaki    {
139100966Siwasaki        return_ACPI_STATUS (AE_OK);
140100966Siwasaki    }
141100966Siwasaki
142100966Siwasaki    /* Return object type does not match requested type */
143100966Siwasaki
144167802Sjkim    ACPI_ERROR ((AE_INFO,
145167802Sjkim        "Incorrect return type [%s] requested [%s]",
146100966Siwasaki        AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
147100966Siwasaki        AcpiUtGetTypeName (ReturnType)));
148100966Siwasaki
149100966Siwasaki    if (MustFree)
150100966Siwasaki    {
151100966Siwasaki        /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
152100966Siwasaki
153100966Siwasaki        AcpiOsFree (ReturnBuffer->Pointer);
154100966Siwasaki        ReturnBuffer->Pointer = NULL;
155100966Siwasaki    }
156100966Siwasaki
157100966Siwasaki    ReturnBuffer->Length = 0;
158100966Siwasaki    return_ACPI_STATUS (AE_TYPE);
159100966Siwasaki}
160100966Siwasaki
161167802SjkimACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
162100966Siwasaki
163167802Sjkim
164100966Siwasaki/*******************************************************************************
165100966Siwasaki *
166100966Siwasaki * FUNCTION:    AcpiEvaluateObject
167100966Siwasaki *
168100966Siwasaki * PARAMETERS:  Handle              - Object handle (optional)
169128212Snjl *              Pathname            - Object pathname (optional)
170128212Snjl *              ExternalParams      - List of parameters to pass to method,
171241973Sjkim *                                    terminated by NULL. May be NULL
172100966Siwasaki *                                    if no parameters are being passed.
173128212Snjl *              ReturnBuffer        - Where to put method's return value (if
174241973Sjkim *                                    any). If NULL, no value is returned.
175100966Siwasaki *
176100966Siwasaki * RETURN:      Status
177100966Siwasaki *
178100966Siwasaki * DESCRIPTION: Find and evaluate the given object, passing the given
179241973Sjkim *              parameters if necessary. One of "Handle" or "Pathname" must
180100966Siwasaki *              be valid (non-null)
181100966Siwasaki *
182100966Siwasaki ******************************************************************************/
183100966Siwasaki
184100966SiwasakiACPI_STATUS
185100966SiwasakiAcpiEvaluateObject (
186100966Siwasaki    ACPI_HANDLE             Handle,
187100966Siwasaki    ACPI_STRING             Pathname,
188100966Siwasaki    ACPI_OBJECT_LIST        *ExternalParams,
189100966Siwasaki    ACPI_BUFFER             *ReturnBuffer)
190100966Siwasaki{
191100966Siwasaki    ACPI_STATUS             Status;
192167802Sjkim    ACPI_EVALUATE_INFO      *Info;
193100966Siwasaki    ACPI_SIZE               BufferSpaceNeeded;
194100966Siwasaki    UINT32                  i;
195100966Siwasaki
196100966Siwasaki
197167802Sjkim    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
198100966Siwasaki
199100966Siwasaki
200167802Sjkim    /* Allocate and initialize the evaluation information block */
201129684Snjl
202167802Sjkim    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
203167802Sjkim    if (!Info)
204167802Sjkim    {
205167802Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
206167802Sjkim    }
207167802Sjkim
208167802Sjkim    /* Convert and validate the device handle */
209167802Sjkim
210200553Sjkim    Info->PrefixNode = AcpiNsValidateHandle (Handle);
211167802Sjkim    if (!Info->PrefixNode)
212167802Sjkim    {
213167802Sjkim        Status = AE_BAD_PARAMETER;
214167802Sjkim        goto Cleanup;
215167802Sjkim    }
216167802Sjkim
217100966Siwasaki    /*
218249663Sjkim     * Get the actual namespace node for the target object.
219249663Sjkim     * Handles these cases:
220249663Sjkim     *
221249663Sjkim     * 1) Null node, valid pathname from root (absolute path)
222249663Sjkim     * 2) Node and valid pathname (path relative to Node)
223249663Sjkim     * 3) Node, Null pathname
224100966Siwasaki     */
225249663Sjkim    if ((Pathname) &&
226249663Sjkim        (ACPI_IS_ROOT_PREFIX (Pathname[0])))
227249663Sjkim    {
228249663Sjkim        /* The path is fully qualified, just evaluate by name */
229249663Sjkim
230249663Sjkim        Info->PrefixNode = NULL;
231249663Sjkim    }
232249663Sjkim    else if (!Handle)
233249663Sjkim    {
234249663Sjkim        /*
235249663Sjkim         * A handle is optional iff a fully qualified pathname is specified.
236249663Sjkim         * Since we've already handled fully qualified names above, this is
237249663Sjkim         * an error.
238249663Sjkim         */
239249663Sjkim        if (!Pathname)
240249663Sjkim        {
241249663Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
242249663Sjkim                "Both Handle and Pathname are NULL"));
243249663Sjkim        }
244249663Sjkim        else
245249663Sjkim        {
246249663Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
247249663Sjkim                "Null Handle with relative pathname [%s]", Pathname));
248249663Sjkim        }
249249663Sjkim
250249663Sjkim        Status = AE_BAD_PARAMETER;
251249663Sjkim        goto Cleanup;
252249663Sjkim    }
253249663Sjkim
254249663Sjkim    Info->RelativePathname = Pathname;
255249663Sjkim
256249663Sjkim    /*
257249663Sjkim     * Convert all external objects passed as arguments to the
258249663Sjkim     * internal version(s).
259249663Sjkim     */
260100966Siwasaki    if (ExternalParams && ExternalParams->Count)
261100966Siwasaki    {
262249663Sjkim        Info->ParamCount = (UINT16) ExternalParams->Count;
263249663Sjkim
264249663Sjkim        /* Warn on impossible argument count */
265249663Sjkim
266249663Sjkim        if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
267249663Sjkim        {
268249663Sjkim            ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
269249663Sjkim                "Excess arguments (%u) - using only %u",
270249663Sjkim                Info->ParamCount, ACPI_METHOD_NUM_ARGS));
271249663Sjkim
272249663Sjkim            Info->ParamCount = ACPI_METHOD_NUM_ARGS;
273249663Sjkim        }
274249663Sjkim
275100966Siwasaki        /*
276100966Siwasaki         * Allocate a new parameter block for the internal objects
277100966Siwasaki         * Add 1 to count to allow for null terminated internal list
278100966Siwasaki         */
279167802Sjkim        Info->Parameters = ACPI_ALLOCATE_ZEROED (
280249663Sjkim            ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
281167802Sjkim        if (!Info->Parameters)
282100966Siwasaki        {
283167802Sjkim            Status = AE_NO_MEMORY;
284167802Sjkim            goto Cleanup;
285100966Siwasaki        }
286100966Siwasaki
287167802Sjkim        /* Convert each external object in the list to an internal object */
288167802Sjkim
289249663Sjkim        for (i = 0; i < Info->ParamCount; i++)
290100966Siwasaki        {
291167802Sjkim            Status = AcpiUtCopyEobjectToIobject (
292249663Sjkim                &ExternalParams->Pointer[i], &Info->Parameters[i]);
293100966Siwasaki            if (ACPI_FAILURE (Status))
294100966Siwasaki            {
295167802Sjkim                goto Cleanup;
296100966Siwasaki            }
297100966Siwasaki        }
298249663Sjkim
299249663Sjkim        Info->Parameters[Info->ParamCount] = NULL;
300100966Siwasaki    }
301100966Siwasaki
302249663Sjkim
303249663Sjkim#if 0
304249663Sjkim
305100966Siwasaki    /*
306249663Sjkim     * Begin incoming argument count analysis. Check for too few args
307249663Sjkim     * and too many args.
308100966Siwasaki     */
309249663Sjkim
310249663Sjkim    switch (AcpiNsGetType (Info->Node))
311100966Siwasaki    {
312249663Sjkim    case ACPI_TYPE_METHOD:
313167802Sjkim
314249663Sjkim        /* Check incoming argument count against the method definition */
315249663Sjkim
316249663Sjkim        if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
317249663Sjkim        {
318249663Sjkim            ACPI_ERROR ((AE_INFO,
319249663Sjkim                "Insufficient arguments (%u) - %u are required",
320249663Sjkim                Info->ParamCount,
321249663Sjkim                Info->ObjDesc->Method.ParamCount));
322249663Sjkim
323249663Sjkim            Status = AE_MISSING_ARGUMENTS;
324249663Sjkim            goto Cleanup;
325249663Sjkim        }
326249663Sjkim
327249663Sjkim        else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
328249663Sjkim        {
329249663Sjkim            ACPI_WARNING ((AE_INFO,
330249663Sjkim                "Excess arguments (%u) - only %u are required",
331249663Sjkim                Info->ParamCount,
332249663Sjkim                Info->ObjDesc->Method.ParamCount));
333249663Sjkim
334249663Sjkim            /* Just pass the required number of arguments */
335249663Sjkim
336249663Sjkim            Info->ParamCount = Info->ObjDesc->Method.ParamCount;
337249663Sjkim        }
338249663Sjkim
339100966Siwasaki        /*
340249663Sjkim         * Any incoming external objects to be passed as arguments to the
341249663Sjkim         * method must be converted to internal objects
342100966Siwasaki         */
343249663Sjkim        if (Info->ParamCount)
344100966Siwasaki        {
345249663Sjkim            /*
346249663Sjkim             * Allocate a new parameter block for the internal objects
347249663Sjkim             * Add 1 to count to allow for null terminated internal list
348249663Sjkim             */
349249663Sjkim            Info->Parameters = ACPI_ALLOCATE_ZEROED (
350249663Sjkim                ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
351249663Sjkim            if (!Info->Parameters)
352249663Sjkim            {
353249663Sjkim                Status = AE_NO_MEMORY;
354249663Sjkim                goto Cleanup;
355249663Sjkim            }
356249663Sjkim
357249663Sjkim            /* Convert each external object in the list to an internal object */
358249663Sjkim
359249663Sjkim            for (i = 0; i < Info->ParamCount; i++)
360249663Sjkim            {
361249663Sjkim                Status = AcpiUtCopyEobjectToIobject (
362249663Sjkim                    &ExternalParams->Pointer[i], &Info->Parameters[i]);
363249663Sjkim                if (ACPI_FAILURE (Status))
364249663Sjkim                {
365249663Sjkim                    goto Cleanup;
366249663Sjkim                }
367249663Sjkim            }
368249663Sjkim
369249663Sjkim            Info->Parameters[Info->ParamCount] = NULL;
370100966Siwasaki        }
371249663Sjkim        break;
372249663Sjkim
373249663Sjkim    default:
374249663Sjkim
375249663Sjkim        /* Warn if arguments passed to an object that is not a method */
376249663Sjkim
377249663Sjkim        if (Info->ParamCount)
378100966Siwasaki        {
379249663Sjkim            ACPI_WARNING ((AE_INFO,
380249663Sjkim                "%u arguments were passed to a non-method ACPI object",
381249663Sjkim                Info->ParamCount));
382100966Siwasaki        }
383249663Sjkim        break;
384100966Siwasaki    }
385167802Sjkim
386249663Sjkim#endif
387100966Siwasaki
388249663Sjkim
389249663Sjkim    /* Now we can evaluate the object */
390249663Sjkim
391249663Sjkim    Status = AcpiNsEvaluate (Info);
392249663Sjkim
393100966Siwasaki    /*
394100966Siwasaki     * If we are expecting a return value, and all went well above,
395100966Siwasaki     * copy the return value to an external object.
396100966Siwasaki     */
397100966Siwasaki    if (ReturnBuffer)
398100966Siwasaki    {
399167802Sjkim        if (!Info->ReturnObject)
400100966Siwasaki        {
401100966Siwasaki            ReturnBuffer->Length = 0;
402100966Siwasaki        }
403100966Siwasaki        else
404100966Siwasaki        {
405167802Sjkim            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
406167802Sjkim                ACPI_DESC_TYPE_NAMED)
407100966Siwasaki            {
408100966Siwasaki                /*
409100966Siwasaki                 * If we received a NS Node as a return object, this means that
410100966Siwasaki                 * the object we are evaluating has nothing interesting to
411100966Siwasaki                 * return (such as a mutex, etc.)  We return an error because
412100966Siwasaki                 * these types are essentially unsupported by this interface.
413100966Siwasaki                 * We don't check up front because this makes it easier to add
414100966Siwasaki                 * support for various types at a later date if necessary.
415100966Siwasaki                 */
416100966Siwasaki                Status = AE_TYPE;
417167802Sjkim                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
418100966Siwasaki                ReturnBuffer->Length = 0;
419100966Siwasaki            }
420100966Siwasaki
421100966Siwasaki            if (ACPI_SUCCESS (Status))
422100966Siwasaki            {
423193267Sjkim                /* Dereference Index and RefOf references */
424193267Sjkim
425193267Sjkim                AcpiNsResolveReferences (Info);
426193267Sjkim
427167802Sjkim                /* Get the size of the returned object */
428167802Sjkim
429167802Sjkim                Status = AcpiUtGetObjectSize (Info->ReturnObject,
430167802Sjkim                            &BufferSpaceNeeded);
431100966Siwasaki                if (ACPI_SUCCESS (Status))
432100966Siwasaki                {
433100966Siwasaki                    /* Validate/Allocate/Clear caller buffer */
434100966Siwasaki
435151937Sjkim                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
436167802Sjkim                                BufferSpaceNeeded);
437100966Siwasaki                    if (ACPI_FAILURE (Status))
438100966Siwasaki                    {
439100966Siwasaki                        /*
440167802Sjkim                         * Caller's buffer is too small or a new one can't
441167802Sjkim                         * be allocated
442100966Siwasaki                         */
443100966Siwasaki                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
444100966Siwasaki                            "Needed buffer size %X, %s\n",
445129684Snjl                            (UINT32) BufferSpaceNeeded,
446129684Snjl                            AcpiFormatException (Status)));
447100966Siwasaki                    }
448100966Siwasaki                    else
449100966Siwasaki                    {
450167802Sjkim                        /* We have enough space for the object, build it */
451167802Sjkim
452167802Sjkim                        Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
453167802Sjkim                                    ReturnBuffer);
454100966Siwasaki                    }
455100966Siwasaki                }
456100966Siwasaki            }
457100966Siwasaki        }
458100966Siwasaki    }
459100966Siwasaki
460167802Sjkim    if (Info->ReturnObject)
461100966Siwasaki    {
462129684Snjl        /*
463167802Sjkim         * Delete the internal return object. NOTE: Interpreter must be
464167802Sjkim         * locked to avoid race condition.
465100966Siwasaki         */
466167802Sjkim        AcpiExEnterInterpreter ();
467167802Sjkim
468167802Sjkim        /* Remove one reference on the return object (should delete it) */
469167802Sjkim
470167802Sjkim        AcpiUtRemoveReference (Info->ReturnObject);
471167802Sjkim        AcpiExExitInterpreter ();
472100966Siwasaki    }
473100966Siwasaki
474167802Sjkim
475167802SjkimCleanup:
476167802Sjkim
477167802Sjkim    /* Free the input parameter list (if we created one) */
478167802Sjkim
479167802Sjkim    if (Info->Parameters)
480100966Siwasaki    {
481100966Siwasaki        /* Free the allocated parameter block */
482100966Siwasaki
483167802Sjkim        AcpiUtDeleteInternalObjectList (Info->Parameters);
484100966Siwasaki    }
485100966Siwasaki
486167802Sjkim    ACPI_FREE (Info);
487100966Siwasaki    return_ACPI_STATUS (Status);
488100966Siwasaki}
489100966Siwasaki
490167802SjkimACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
491100966Siwasaki
492167802Sjkim
493100966Siwasaki/*******************************************************************************
494100966Siwasaki *
495193267Sjkim * FUNCTION:    AcpiNsResolveReferences
496193267Sjkim *
497193267Sjkim * PARAMETERS:  Info                    - Evaluation info block
498193267Sjkim *
499193267Sjkim * RETURN:      Info->ReturnObject is replaced with the dereferenced object
500193267Sjkim *
501193267Sjkim * DESCRIPTION: Dereference certain reference objects. Called before an
502193267Sjkim *              internal return object is converted to an external ACPI_OBJECT.
503193267Sjkim *
504193267Sjkim * Performs an automatic dereference of Index and RefOf reference objects.
505193267Sjkim * These reference objects are not supported by the ACPI_OBJECT, so this is a
506193267Sjkim * last resort effort to return something useful. Also, provides compatibility
507193267Sjkim * with other ACPI implementations.
508193267Sjkim *
509193267Sjkim * NOTE: does not handle references within returned package objects or nested
510193267Sjkim * references, but this support could be added later if found to be necessary.
511193267Sjkim *
512193267Sjkim ******************************************************************************/
513193267Sjkim
514193267Sjkimstatic void
515193267SjkimAcpiNsResolveReferences (
516193267Sjkim    ACPI_EVALUATE_INFO      *Info)
517193267Sjkim{
518193267Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
519193267Sjkim    ACPI_NAMESPACE_NODE     *Node;
520193267Sjkim
521193267Sjkim
522193267Sjkim    /* We are interested in reference objects only */
523193267Sjkim
524193267Sjkim    if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
525193267Sjkim    {
526193267Sjkim        return;
527193267Sjkim    }
528193267Sjkim
529193267Sjkim    /*
530193267Sjkim     * Two types of references are supported - those created by Index and
531193267Sjkim     * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
532193267Sjkim     * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
533193267Sjkim     * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
534193267Sjkim     * an ACPI_OBJECT.
535193267Sjkim     */
536193267Sjkim    switch (Info->ReturnObject->Reference.Class)
537193267Sjkim    {
538193267Sjkim    case ACPI_REFCLASS_INDEX:
539193267Sjkim
540193267Sjkim        ObjDesc = *(Info->ReturnObject->Reference.Where);
541193267Sjkim        break;
542193267Sjkim
543193267Sjkim    case ACPI_REFCLASS_REFOF:
544193267Sjkim
545193267Sjkim        Node = Info->ReturnObject->Reference.Object;
546193267Sjkim        if (Node)
547193267Sjkim        {
548193267Sjkim            ObjDesc = Node->Object;
549193267Sjkim        }
550193267Sjkim        break;
551193267Sjkim
552193267Sjkim    default:
553250838Sjkim
554193267Sjkim        return;
555193267Sjkim    }
556193267Sjkim
557193267Sjkim    /* Replace the existing reference object */
558193267Sjkim
559193267Sjkim    if (ObjDesc)
560193267Sjkim    {
561193267Sjkim        AcpiUtAddReference (ObjDesc);
562193267Sjkim        AcpiUtRemoveReference (Info->ReturnObject);
563193267Sjkim        Info->ReturnObject = ObjDesc;
564193267Sjkim    }
565193267Sjkim
566193267Sjkim    return;
567193267Sjkim}
568193267Sjkim
569193267Sjkim
570193267Sjkim/*******************************************************************************
571193267Sjkim *
572100966Siwasaki * FUNCTION:    AcpiWalkNamespace
573100966Siwasaki *
574100966Siwasaki * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
575100966Siwasaki *              StartObject         - Handle in namespace where search begins
576100966Siwasaki *              MaxDepth            - Depth to which search is to reach
577253690Sjkim *              DescendingCallback  - Called during tree descent
578199337Sjkim *                                    when an object of "Type" is found
579253690Sjkim *              AscendingCallback   - Called during tree ascent
580199337Sjkim *                                    when an object of "Type" is found
581199337Sjkim *              Context             - Passed to user function(s) above
582100966Siwasaki *              ReturnValue         - Location where return value of
583100966Siwasaki *                                    UserFunction is put if terminated early
584100966Siwasaki *
585100966Siwasaki * RETURNS      Return value from the UserFunction if terminated early.
586100966Siwasaki *              Otherwise, returns NULL.
587100966Siwasaki *
588100966Siwasaki * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
589100966Siwasaki *              starting (and ending) at the object specified by StartHandle.
590199337Sjkim *              The callback function is called whenever an object that matches
591199337Sjkim *              the type parameter is found. If the callback function returns
592100966Siwasaki *              a non-zero value, the search is terminated immediately and this
593100966Siwasaki *              value is returned to the caller.
594100966Siwasaki *
595100966Siwasaki *              The point of this procedure is to provide a generic namespace
596100966Siwasaki *              walk routine that can be called from multiple places to
597199337Sjkim *              provide multiple services; the callback function(s) can be
598199337Sjkim *              tailored to each task, whether it is a print function,
599199337Sjkim *              a compare function, etc.
600100966Siwasaki *
601100966Siwasaki ******************************************************************************/
602100966Siwasaki
603100966SiwasakiACPI_STATUS
604100966SiwasakiAcpiWalkNamespace (
605100966Siwasaki    ACPI_OBJECT_TYPE        Type,
606100966Siwasaki    ACPI_HANDLE             StartObject,
607100966Siwasaki    UINT32                  MaxDepth,
608253690Sjkim    ACPI_WALK_CALLBACK      DescendingCallback,
609253690Sjkim    ACPI_WALK_CALLBACK      AscendingCallback,
610100966Siwasaki    void                    *Context,
611100966Siwasaki    void                    **ReturnValue)
612100966Siwasaki{
613100966Siwasaki    ACPI_STATUS             Status;
614100966Siwasaki
615100966Siwasaki
616167802Sjkim    ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
617100966Siwasaki
618100966Siwasaki
619100966Siwasaki    /* Parameter validation */
620100966Siwasaki
621167802Sjkim    if ((Type > ACPI_TYPE_LOCAL_MAX) ||
622167802Sjkim        (!MaxDepth)                  ||
623253690Sjkim        (!DescendingCallback && !AscendingCallback))
624100966Siwasaki    {
625100966Siwasaki        return_ACPI_STATUS (AE_BAD_PARAMETER);
626100966Siwasaki    }
627100966Siwasaki
628100966Siwasaki    /*
629193267Sjkim     * Need to acquire the namespace reader lock to prevent interference
630193267Sjkim     * with any concurrent table unloads (which causes the deletion of
631193267Sjkim     * namespace objects). We cannot allow the deletion of a namespace node
632193267Sjkim     * while the user function is using it. The exception to this are the
633193267Sjkim     * nodes created and deleted during control method execution -- these
634193267Sjkim     * nodes are marked as temporary nodes and are ignored by the namespace
635193267Sjkim     * walk. Thus, control methods can be executed while holding the
636193267Sjkim     * namespace deletion lock (and the user function can execute control
637193267Sjkim     * methods.)
638100966Siwasaki     */
639193267Sjkim    Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
640193267Sjkim    if (ACPI_FAILURE (Status))
641193267Sjkim    {
642241973Sjkim        return_ACPI_STATUS (Status);
643193267Sjkim    }
644193267Sjkim
645193267Sjkim    /*
646193267Sjkim     * Lock the namespace around the walk. The namespace will be
647193267Sjkim     * unlocked/locked around each call to the user function - since the user
648193267Sjkim     * function must be allowed to make ACPICA calls itself (for example, it
649193267Sjkim     * will typically execute control methods during device enumeration.)
650193267Sjkim     */
651100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
652100966Siwasaki    if (ACPI_FAILURE (Status))
653100966Siwasaki    {
654193267Sjkim        goto UnlockAndExit;
655100966Siwasaki    }
656100966Siwasaki
657254745Sjkim    /* Now we can validate the starting node */
658254745Sjkim
659254745Sjkim    if (!AcpiNsValidateHandle (StartObject))
660254745Sjkim    {
661254745Sjkim        Status = AE_BAD_PARAMETER;
662254745Sjkim        goto UnlockAndExit2;
663254745Sjkim    }
664254745Sjkim
665151937Sjkim    Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
666253690Sjkim                ACPI_NS_WALK_UNLOCK, DescendingCallback,
667253690Sjkim                AscendingCallback, Context, ReturnValue);
668100966Siwasaki
669254745SjkimUnlockAndExit2:
670100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
671193267Sjkim
672193267SjkimUnlockAndExit:
673193267Sjkim    (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
674100966Siwasaki    return_ACPI_STATUS (Status);
675100966Siwasaki}
676100966Siwasaki
677167802SjkimACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
678100966Siwasaki
679167802Sjkim
680100966Siwasaki/*******************************************************************************
681100966Siwasaki *
682100966Siwasaki * FUNCTION:    AcpiNsGetDeviceCallback
683100966Siwasaki *
684100966Siwasaki * PARAMETERS:  Callback from AcpiGetDevice
685100966Siwasaki *
686100966Siwasaki * RETURN:      Status
687100966Siwasaki *
688100966Siwasaki * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
689100966Siwasaki *              present devices, or if they specified a HID, it filters based
690100966Siwasaki *              on that.
691100966Siwasaki *
692100966Siwasaki ******************************************************************************/
693100966Siwasaki
694100966Siwasakistatic ACPI_STATUS
695100966SiwasakiAcpiNsGetDeviceCallback (
696100966Siwasaki    ACPI_HANDLE             ObjHandle,
697100966Siwasaki    UINT32                  NestingLevel,
698100966Siwasaki    void                    *Context,
699100966Siwasaki    void                    **ReturnValue)
700100966Siwasaki{
701117521Snjl    ACPI_GET_DEVICES_INFO   *Info = Context;
702100966Siwasaki    ACPI_STATUS             Status;
703100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
704100966Siwasaki    UINT32                  Flags;
705241973Sjkim    ACPI_PNP_DEVICE_ID      *Hid;
706241973Sjkim    ACPI_PNP_DEVICE_ID_LIST *Cid;
707193267Sjkim    UINT32                  i;
708193267Sjkim    BOOLEAN                 Found;
709197104Sjkim    int                     NoMatch;
710100966Siwasaki
711100966Siwasaki
712100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
713100966Siwasaki    if (ACPI_FAILURE (Status))
714100966Siwasaki    {
715100966Siwasaki        return (Status);
716100966Siwasaki    }
717100966Siwasaki
718200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
719100966Siwasaki    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
720100966Siwasaki    if (ACPI_FAILURE (Status))
721100966Siwasaki    {
722100966Siwasaki        return (Status);
723100966Siwasaki    }
724100966Siwasaki
725100966Siwasaki    if (!Node)
726100966Siwasaki    {
727100966Siwasaki        return (AE_BAD_PARAMETER);
728100966Siwasaki    }
729100966Siwasaki
730202771Sjkim    /*
731202771Sjkim     * First, filter based on the device HID and CID.
732202771Sjkim     *
733202771Sjkim     * 01/2010: For this case where a specific HID is requested, we don't
734202771Sjkim     * want to run _STA until we have an actual HID match. Thus, we will
735202771Sjkim     * not unnecessarily execute _STA on devices for which the caller
736202771Sjkim     * doesn't care about. Previously, _STA was executed unconditionally
737202771Sjkim     * on all devices found here.
738202771Sjkim     *
739202771Sjkim     * A side-effect of this change is that now we will continue to search
740202771Sjkim     * for a matching HID even under device trees where the parent device
741202771Sjkim     * would have returned a _STA that indicates it is not present or
742202771Sjkim     * not functioning (thus aborting the search on that branch).
743202771Sjkim     */
744100966Siwasaki    if (Info->Hid != NULL)
745100966Siwasaki    {
746100966Siwasaki        Status = AcpiUtExecute_HID (Node, &Hid);
747100966Siwasaki        if (Status == AE_NOT_FOUND)
748100966Siwasaki        {
749100966Siwasaki            return (AE_OK);
750100966Siwasaki        }
751100966Siwasaki        else if (ACPI_FAILURE (Status))
752100966Siwasaki        {
753100966Siwasaki            return (AE_CTRL_DEPTH);
754100966Siwasaki        }
755100966Siwasaki
756197104Sjkim        NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
757197104Sjkim        ACPI_FREE (Hid);
758197104Sjkim
759197104Sjkim        if (NoMatch)
760100966Siwasaki        {
761193267Sjkim            /*
762193267Sjkim             * HID does not match, attempt match within the
763193267Sjkim             * list of Compatible IDs (CIDs)
764193267Sjkim             */
765100966Siwasaki            Status = AcpiUtExecute_CID (Node, &Cid);
766100966Siwasaki            if (Status == AE_NOT_FOUND)
767100966Siwasaki            {
768100966Siwasaki                return (AE_OK);
769100966Siwasaki            }
770100966Siwasaki            else if (ACPI_FAILURE (Status))
771100966Siwasaki            {
772100966Siwasaki                return (AE_CTRL_DEPTH);
773100966Siwasaki            }
774100966Siwasaki
775117521Snjl            /* Walk the CID list */
776100966Siwasaki
777193267Sjkim            Found = FALSE;
778117521Snjl            for (i = 0; i < Cid->Count; i++)
779100966Siwasaki            {
780197104Sjkim                if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
781117521Snjl                {
782193267Sjkim                    /* Found a matching CID */
783193267Sjkim
784193267Sjkim                    Found = TRUE;
785193267Sjkim                    break;
786117521Snjl                }
787100966Siwasaki            }
788193267Sjkim
789167802Sjkim            ACPI_FREE (Cid);
790193267Sjkim            if (!Found)
791193267Sjkim            {
792193267Sjkim                return (AE_OK);
793193267Sjkim            }
794100966Siwasaki        }
795100966Siwasaki    }
796100966Siwasaki
797202771Sjkim    /* Run _STA to determine if device is present */
798202771Sjkim
799202771Sjkim    Status = AcpiUtExecute_STA (Node, &Flags);
800202771Sjkim    if (ACPI_FAILURE (Status))
801202771Sjkim    {
802202771Sjkim        return (AE_CTRL_DEPTH);
803202771Sjkim    }
804202771Sjkim
805202771Sjkim    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
806202771Sjkim        !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
807202771Sjkim    {
808202771Sjkim        /*
809202771Sjkim         * Don't examine the children of the device only when the
810202771Sjkim         * device is neither present nor functional. See ACPI spec,
811202771Sjkim         * description of _STA for more information.
812202771Sjkim         */
813202771Sjkim        return (AE_CTRL_DEPTH);
814202771Sjkim    }
815202771Sjkim
816193267Sjkim    /* We have a valid device, invoke the user function */
817193267Sjkim
818151937Sjkim    Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
819151937Sjkim                ReturnValue);
820100966Siwasaki    return (Status);
821100966Siwasaki}
822100966Siwasaki
823100966Siwasaki
824100966Siwasaki/*******************************************************************************
825100966Siwasaki *
826100966Siwasaki * FUNCTION:    AcpiGetDevices
827100966Siwasaki *
828100966Siwasaki * PARAMETERS:  HID                 - HID to search for. Can be NULL.
829100966Siwasaki *              UserFunction        - Called when a matching object is found
830100966Siwasaki *              Context             - Passed to user function
831100966Siwasaki *              ReturnValue         - Location where return value of
832100966Siwasaki *                                    UserFunction is put if terminated early
833100966Siwasaki *
834100966Siwasaki * RETURNS      Return value from the UserFunction if terminated early.
835100966Siwasaki *              Otherwise, returns NULL.
836100966Siwasaki *
837100966Siwasaki * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
838100966Siwasaki *              starting (and ending) at the object specified by StartHandle.
839117521Snjl *              The UserFunction is called whenever an object of type
840241973Sjkim *              Device is found. If the user function returns
841100966Siwasaki *              a non-zero value, the search is terminated immediately and this
842100966Siwasaki *              value is returned to the caller.
843100966Siwasaki *
844100966Siwasaki *              This is a wrapper for WalkNamespace, but the callback performs
845193267Sjkim *              additional filtering. Please see AcpiNsGetDeviceCallback.
846100966Siwasaki *
847100966Siwasaki ******************************************************************************/
848100966Siwasaki
849100966SiwasakiACPI_STATUS
850100966SiwasakiAcpiGetDevices (
851114237Snjl    char                    *HID,
852100966Siwasaki    ACPI_WALK_CALLBACK      UserFunction,
853100966Siwasaki    void                    *Context,
854100966Siwasaki    void                    **ReturnValue)
855100966Siwasaki{
856100966Siwasaki    ACPI_STATUS             Status;
857100966Siwasaki    ACPI_GET_DEVICES_INFO   Info;
858100966Siwasaki
859100966Siwasaki
860167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetDevices);
861100966Siwasaki
862100966Siwasaki
863100966Siwasaki    /* Parameter validation */
864100966Siwasaki
865100966Siwasaki    if (!UserFunction)
866100966Siwasaki    {
867100966Siwasaki        return_ACPI_STATUS (AE_BAD_PARAMETER);
868100966Siwasaki    }
869100966Siwasaki
870100966Siwasaki    /*
871100966Siwasaki     * We're going to call their callback from OUR callback, so we need
872100966Siwasaki     * to know what it is, and their context parameter.
873100966Siwasaki     */
874167802Sjkim    Info.Hid          = HID;
875100966Siwasaki    Info.Context      = Context;
876100966Siwasaki    Info.UserFunction = UserFunction;
877100966Siwasaki
878100966Siwasaki    /*
879100966Siwasaki     * Lock the namespace around the walk.
880100966Siwasaki     * The namespace will be unlocked/locked around each call
881100966Siwasaki     * to the user function - since this function
882100966Siwasaki     * must be allowed to make Acpi calls itself.
883100966Siwasaki     */
884100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
885100966Siwasaki    if (ACPI_FAILURE (Status))
886100966Siwasaki    {
887100966Siwasaki        return_ACPI_STATUS (Status);
888100966Siwasaki    }
889100966Siwasaki
890167802Sjkim    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
891167802Sjkim                ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
892199337Sjkim                AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
893100966Siwasaki
894100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
895100966Siwasaki    return_ACPI_STATUS (Status);
896100966Siwasaki}
897100966Siwasaki
898167802SjkimACPI_EXPORT_SYMBOL (AcpiGetDevices)
899100966Siwasaki
900167802Sjkim
901100966Siwasaki/*******************************************************************************
902100966Siwasaki *
903100966Siwasaki * FUNCTION:    AcpiAttachData
904100966Siwasaki *
905114237Snjl * PARAMETERS:  ObjHandle           - Namespace node
906107325Siwasaki *              Handler             - Handler for this attachment
907107325Siwasaki *              Data                - Pointer to data to be attached
908100966Siwasaki *
909100966Siwasaki * RETURN:      Status
910100966Siwasaki *
911107325Siwasaki * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
912100966Siwasaki *
913100966Siwasaki ******************************************************************************/
914100966Siwasaki
915100966SiwasakiACPI_STATUS
916100966SiwasakiAcpiAttachData (
917100966Siwasaki    ACPI_HANDLE             ObjHandle,
918100966Siwasaki    ACPI_OBJECT_HANDLER     Handler,
919100966Siwasaki    void                    *Data)
920100966Siwasaki{
921100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
922100966Siwasaki    ACPI_STATUS             Status;
923100966Siwasaki
924100966Siwasaki
925100966Siwasaki    /* Parameter validation */
926100966Siwasaki
927100966Siwasaki    if (!ObjHandle  ||
928100966Siwasaki        !Handler    ||
929100966Siwasaki        !Data)
930100966Siwasaki    {
931100966Siwasaki        return (AE_BAD_PARAMETER);
932100966Siwasaki    }
933100966Siwasaki
934100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
935100966Siwasaki    if (ACPI_FAILURE (Status))
936100966Siwasaki    {
937100966Siwasaki        return (Status);
938100966Siwasaki    }
939100966Siwasaki
940100966Siwasaki    /* Convert and validate the handle */
941100966Siwasaki
942200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
943100966Siwasaki    if (!Node)
944100966Siwasaki    {
945100966Siwasaki        Status = AE_BAD_PARAMETER;
946100966Siwasaki        goto UnlockAndExit;
947100966Siwasaki    }
948100966Siwasaki
949100966Siwasaki    Status = AcpiNsAttachData (Node, Handler, Data);
950100966Siwasaki
951100966SiwasakiUnlockAndExit:
952100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
953100966Siwasaki    return (Status);
954100966Siwasaki}
955100966Siwasaki
956167802SjkimACPI_EXPORT_SYMBOL (AcpiAttachData)
957100966Siwasaki
958167802Sjkim
959100966Siwasaki/*******************************************************************************
960100966Siwasaki *
961100966Siwasaki * FUNCTION:    AcpiDetachData
962100966Siwasaki *
963107325Siwasaki * PARAMETERS:  ObjHandle           - Namespace node handle
964107325Siwasaki *              Handler             - Handler used in call to AcpiAttachData
965100966Siwasaki *
966100966Siwasaki * RETURN:      Status
967100966Siwasaki *
968107325Siwasaki * DESCRIPTION: Remove data that was previously attached to a node.
969100966Siwasaki *
970100966Siwasaki ******************************************************************************/
971100966Siwasaki
972100966SiwasakiACPI_STATUS
973100966SiwasakiAcpiDetachData (
974100966Siwasaki    ACPI_HANDLE             ObjHandle,
975100966Siwasaki    ACPI_OBJECT_HANDLER     Handler)
976100966Siwasaki{
977100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
978100966Siwasaki    ACPI_STATUS             Status;
979100966Siwasaki
980100966Siwasaki
981100966Siwasaki    /* Parameter validation */
982100966Siwasaki
983100966Siwasaki    if (!ObjHandle  ||
984100966Siwasaki        !Handler)
985100966Siwasaki    {
986100966Siwasaki        return (AE_BAD_PARAMETER);
987100966Siwasaki    }
988100966Siwasaki
989100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
990100966Siwasaki    if (ACPI_FAILURE (Status))
991100966Siwasaki    {
992100966Siwasaki        return (Status);
993100966Siwasaki    }
994100966Siwasaki
995100966Siwasaki    /* Convert and validate the handle */
996100966Siwasaki
997200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
998100966Siwasaki    if (!Node)
999100966Siwasaki    {
1000100966Siwasaki        Status = AE_BAD_PARAMETER;
1001100966Siwasaki        goto UnlockAndExit;
1002100966Siwasaki    }
1003100966Siwasaki
1004100966Siwasaki    Status = AcpiNsDetachData (Node, Handler);
1005100966Siwasaki
1006100966SiwasakiUnlockAndExit:
1007100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1008100966Siwasaki    return (Status);
1009100966Siwasaki}
1010100966Siwasaki
1011167802SjkimACPI_EXPORT_SYMBOL (AcpiDetachData)
1012100966Siwasaki
1013167802Sjkim
1014100966Siwasaki/*******************************************************************************
1015100966Siwasaki *
1016100966Siwasaki * FUNCTION:    AcpiGetData
1017100966Siwasaki *
1018107325Siwasaki * PARAMETERS:  ObjHandle           - Namespace node
1019107325Siwasaki *              Handler             - Handler used in call to AttachData
1020107325Siwasaki *              Data                - Where the data is returned
1021100966Siwasaki *
1022100966Siwasaki * RETURN:      Status
1023100966Siwasaki *
1024107325Siwasaki * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
1025100966Siwasaki *
1026100966Siwasaki ******************************************************************************/
1027100966Siwasaki
1028100966SiwasakiACPI_STATUS
1029100966SiwasakiAcpiGetData (
1030100966Siwasaki    ACPI_HANDLE             ObjHandle,
1031100966Siwasaki    ACPI_OBJECT_HANDLER     Handler,
1032100966Siwasaki    void                    **Data)
1033100966Siwasaki{
1034100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
1035100966Siwasaki    ACPI_STATUS             Status;
1036100966Siwasaki
1037100966Siwasaki
1038100966Siwasaki    /* Parameter validation */
1039100966Siwasaki
1040100966Siwasaki    if (!ObjHandle  ||
1041100966Siwasaki        !Handler    ||
1042100966Siwasaki        !Data)
1043100966Siwasaki    {
1044100966Siwasaki        return (AE_BAD_PARAMETER);
1045100966Siwasaki    }
1046100966Siwasaki
1047100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1048100966Siwasaki    if (ACPI_FAILURE (Status))
1049100966Siwasaki    {
1050100966Siwasaki        return (Status);
1051100966Siwasaki    }
1052100966Siwasaki
1053100966Siwasaki    /* Convert and validate the handle */
1054100966Siwasaki
1055200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
1056100966Siwasaki    if (!Node)
1057100966Siwasaki    {
1058100966Siwasaki        Status = AE_BAD_PARAMETER;
1059100966Siwasaki        goto UnlockAndExit;
1060100966Siwasaki    }
1061100966Siwasaki
1062100966Siwasaki    Status = AcpiNsGetAttachedData (Node, Handler, Data);
1063100966Siwasaki
1064100966SiwasakiUnlockAndExit:
1065100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1066100966Siwasaki    return (Status);
1067100966Siwasaki}
1068100966Siwasaki
1069167802SjkimACPI_EXPORT_SYMBOL (AcpiGetData)
1070