nsxfeval.c revision 217365
1100966Siwasaki/*******************************************************************************
2100966Siwasaki *
3100966Siwasaki * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4100966Siwasaki *                         ACPI Object evaluation interfaces
5100966Siwasaki *
6100966Siwasaki ******************************************************************************/
7100966Siwasaki
8217365Sjkim/*
9217365Sjkim * Copyright (C) 2000 - 2011, 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,
71100966Siwasaki *                                    terminated by NULL.  May be NULL
72100966Siwasaki *                                    if no parameters are being passed.
73151937Sjkim *              ReturnBuffer        - Where to put method's return value (if
74100966Siwasaki *                                    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
80100966Siwasaki *              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,
171100966Siwasaki *                                    terminated by NULL.  May be NULL
172100966Siwasaki *                                    if no parameters are being passed.
173128212Snjl *              ReturnBuffer        - Where to put method's return value (if
174100966Siwasaki *                                    any).  If NULL, no value is returned.
175100966Siwasaki *
176100966Siwasaki * RETURN:      Status
177100966Siwasaki *
178100966Siwasaki * DESCRIPTION: Find and evaluate the given object, passing the given
179100966Siwasaki *              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    Info->Pathname = Pathname;
209167802Sjkim
210167802Sjkim    /* Convert and validate the device handle */
211167802Sjkim
212200553Sjkim    Info->PrefixNode = AcpiNsValidateHandle (Handle);
213167802Sjkim    if (!Info->PrefixNode)
214167802Sjkim    {
215167802Sjkim        Status = AE_BAD_PARAMETER;
216167802Sjkim        goto Cleanup;
217167802Sjkim    }
218167802Sjkim
219100966Siwasaki    /*
220167802Sjkim     * If there are parameters to be passed to a control method, the external
221167802Sjkim     * objects must all be converted to internal objects
222100966Siwasaki     */
223100966Siwasaki    if (ExternalParams && ExternalParams->Count)
224100966Siwasaki    {
225100966Siwasaki        /*
226100966Siwasaki         * Allocate a new parameter block for the internal objects
227100966Siwasaki         * Add 1 to count to allow for null terminated internal list
228100966Siwasaki         */
229167802Sjkim        Info->Parameters = ACPI_ALLOCATE_ZEROED (
230167802Sjkim            ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
231167802Sjkim        if (!Info->Parameters)
232100966Siwasaki        {
233167802Sjkim            Status = AE_NO_MEMORY;
234167802Sjkim            goto Cleanup;
235100966Siwasaki        }
236100966Siwasaki
237167802Sjkim        /* Convert each external object in the list to an internal object */
238167802Sjkim
239100966Siwasaki        for (i = 0; i < ExternalParams->Count; i++)
240100966Siwasaki        {
241167802Sjkim            Status = AcpiUtCopyEobjectToIobject (
242167802Sjkim                        &ExternalParams->Pointer[i], &Info->Parameters[i]);
243100966Siwasaki            if (ACPI_FAILURE (Status))
244100966Siwasaki            {
245167802Sjkim                goto Cleanup;
246100966Siwasaki            }
247100966Siwasaki        }
248167802Sjkim        Info->Parameters[ExternalParams->Count] = NULL;
249100966Siwasaki    }
250100966Siwasaki
251100966Siwasaki    /*
252100966Siwasaki     * Three major cases:
253100966Siwasaki     * 1) Fully qualified pathname
254100966Siwasaki     * 2) No handle, not fully qualified pathname (error)
255100966Siwasaki     * 3) Valid handle
256100966Siwasaki     */
257100966Siwasaki    if ((Pathname) &&
258100966Siwasaki        (AcpiNsValidRootPrefix (Pathname[0])))
259100966Siwasaki    {
260167802Sjkim        /* The path is fully qualified, just evaluate by name */
261167802Sjkim
262167802Sjkim        Info->PrefixNode = NULL;
263167802Sjkim        Status = AcpiNsEvaluate (Info);
264100966Siwasaki    }
265100966Siwasaki    else if (!Handle)
266100966Siwasaki    {
267100966Siwasaki        /*
268167802Sjkim         * A handle is optional iff a fully qualified pathname is specified.
269167802Sjkim         * Since we've already handled fully qualified names above, this is
270167802Sjkim         * an error
271100966Siwasaki         */
272100966Siwasaki        if (!Pathname)
273100966Siwasaki        {
274167802Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
275167802Sjkim                "Both Handle and Pathname are NULL"));
276100966Siwasaki        }
277100966Siwasaki        else
278100966Siwasaki        {
279167802Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
280167802Sjkim                "Null Handle with relative pathname [%s]", Pathname));
281100966Siwasaki        }
282100966Siwasaki
283100966Siwasaki        Status = AE_BAD_PARAMETER;
284100966Siwasaki    }
285100966Siwasaki    else
286100966Siwasaki    {
287167802Sjkim        /* We have a namespace a node and a possible relative path */
288167802Sjkim
289167802Sjkim        Status = AcpiNsEvaluate (Info);
290100966Siwasaki    }
291100966Siwasaki
292100966Siwasaki    /*
293100966Siwasaki     * If we are expecting a return value, and all went well above,
294100966Siwasaki     * copy the return value to an external object.
295100966Siwasaki     */
296100966Siwasaki    if (ReturnBuffer)
297100966Siwasaki    {
298167802Sjkim        if (!Info->ReturnObject)
299100966Siwasaki        {
300100966Siwasaki            ReturnBuffer->Length = 0;
301100966Siwasaki        }
302100966Siwasaki        else
303100966Siwasaki        {
304167802Sjkim            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
305167802Sjkim                ACPI_DESC_TYPE_NAMED)
306100966Siwasaki            {
307100966Siwasaki                /*
308100966Siwasaki                 * If we received a NS Node as a return object, this means that
309100966Siwasaki                 * the object we are evaluating has nothing interesting to
310100966Siwasaki                 * return (such as a mutex, etc.)  We return an error because
311100966Siwasaki                 * these types are essentially unsupported by this interface.
312100966Siwasaki                 * We don't check up front because this makes it easier to add
313100966Siwasaki                 * support for various types at a later date if necessary.
314100966Siwasaki                 */
315100966Siwasaki                Status = AE_TYPE;
316167802Sjkim                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
317100966Siwasaki                ReturnBuffer->Length = 0;
318100966Siwasaki            }
319100966Siwasaki
320100966Siwasaki            if (ACPI_SUCCESS (Status))
321100966Siwasaki            {
322193267Sjkim                /* Dereference Index and RefOf references */
323193267Sjkim
324193267Sjkim                AcpiNsResolveReferences (Info);
325193267Sjkim
326167802Sjkim                /* Get the size of the returned object */
327167802Sjkim
328167802Sjkim                Status = AcpiUtGetObjectSize (Info->ReturnObject,
329167802Sjkim                            &BufferSpaceNeeded);
330100966Siwasaki                if (ACPI_SUCCESS (Status))
331100966Siwasaki                {
332100966Siwasaki                    /* Validate/Allocate/Clear caller buffer */
333100966Siwasaki
334151937Sjkim                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
335167802Sjkim                                BufferSpaceNeeded);
336100966Siwasaki                    if (ACPI_FAILURE (Status))
337100966Siwasaki                    {
338100966Siwasaki                        /*
339167802Sjkim                         * Caller's buffer is too small or a new one can't
340167802Sjkim                         * be allocated
341100966Siwasaki                         */
342100966Siwasaki                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
343100966Siwasaki                            "Needed buffer size %X, %s\n",
344129684Snjl                            (UINT32) BufferSpaceNeeded,
345129684Snjl                            AcpiFormatException (Status)));
346100966Siwasaki                    }
347100966Siwasaki                    else
348100966Siwasaki                    {
349167802Sjkim                        /* We have enough space for the object, build it */
350167802Sjkim
351167802Sjkim                        Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
352167802Sjkim                                    ReturnBuffer);
353100966Siwasaki                    }
354100966Siwasaki                }
355100966Siwasaki            }
356100966Siwasaki        }
357100966Siwasaki    }
358100966Siwasaki
359167802Sjkim    if (Info->ReturnObject)
360100966Siwasaki    {
361129684Snjl        /*
362167802Sjkim         * Delete the internal return object. NOTE: Interpreter must be
363167802Sjkim         * locked to avoid race condition.
364100966Siwasaki         */
365167802Sjkim        AcpiExEnterInterpreter ();
366167802Sjkim
367167802Sjkim        /* Remove one reference on the return object (should delete it) */
368167802Sjkim
369167802Sjkim        AcpiUtRemoveReference (Info->ReturnObject);
370167802Sjkim        AcpiExExitInterpreter ();
371100966Siwasaki    }
372100966Siwasaki
373167802Sjkim
374167802SjkimCleanup:
375167802Sjkim
376167802Sjkim    /* Free the input parameter list (if we created one) */
377167802Sjkim
378167802Sjkim    if (Info->Parameters)
379100966Siwasaki    {
380100966Siwasaki        /* Free the allocated parameter block */
381100966Siwasaki
382167802Sjkim        AcpiUtDeleteInternalObjectList (Info->Parameters);
383100966Siwasaki    }
384100966Siwasaki
385167802Sjkim    ACPI_FREE (Info);
386100966Siwasaki    return_ACPI_STATUS (Status);
387100966Siwasaki}
388100966Siwasaki
389167802SjkimACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
390100966Siwasaki
391167802Sjkim
392100966Siwasaki/*******************************************************************************
393100966Siwasaki *
394193267Sjkim * FUNCTION:    AcpiNsResolveReferences
395193267Sjkim *
396193267Sjkim * PARAMETERS:  Info                    - Evaluation info block
397193267Sjkim *
398193267Sjkim * RETURN:      Info->ReturnObject is replaced with the dereferenced object
399193267Sjkim *
400193267Sjkim * DESCRIPTION: Dereference certain reference objects. Called before an
401193267Sjkim *              internal return object is converted to an external ACPI_OBJECT.
402193267Sjkim *
403193267Sjkim * Performs an automatic dereference of Index and RefOf reference objects.
404193267Sjkim * These reference objects are not supported by the ACPI_OBJECT, so this is a
405193267Sjkim * last resort effort to return something useful. Also, provides compatibility
406193267Sjkim * with other ACPI implementations.
407193267Sjkim *
408193267Sjkim * NOTE: does not handle references within returned package objects or nested
409193267Sjkim * references, but this support could be added later if found to be necessary.
410193267Sjkim *
411193267Sjkim ******************************************************************************/
412193267Sjkim
413193267Sjkimstatic void
414193267SjkimAcpiNsResolveReferences (
415193267Sjkim    ACPI_EVALUATE_INFO      *Info)
416193267Sjkim{
417193267Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
418193267Sjkim    ACPI_NAMESPACE_NODE     *Node;
419193267Sjkim
420193267Sjkim
421193267Sjkim    /* We are interested in reference objects only */
422193267Sjkim
423193267Sjkim    if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
424193267Sjkim    {
425193267Sjkim        return;
426193267Sjkim    }
427193267Sjkim
428193267Sjkim    /*
429193267Sjkim     * Two types of references are supported - those created by Index and
430193267Sjkim     * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
431193267Sjkim     * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
432193267Sjkim     * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
433193267Sjkim     * an ACPI_OBJECT.
434193267Sjkim     */
435193267Sjkim    switch (Info->ReturnObject->Reference.Class)
436193267Sjkim    {
437193267Sjkim    case ACPI_REFCLASS_INDEX:
438193267Sjkim
439193267Sjkim        ObjDesc = *(Info->ReturnObject->Reference.Where);
440193267Sjkim        break;
441193267Sjkim
442193267Sjkim    case ACPI_REFCLASS_REFOF:
443193267Sjkim
444193267Sjkim        Node = Info->ReturnObject->Reference.Object;
445193267Sjkim        if (Node)
446193267Sjkim        {
447193267Sjkim            ObjDesc = Node->Object;
448193267Sjkim        }
449193267Sjkim        break;
450193267Sjkim
451193267Sjkim    default:
452193267Sjkim        return;
453193267Sjkim    }
454193267Sjkim
455193267Sjkim    /* Replace the existing reference object */
456193267Sjkim
457193267Sjkim    if (ObjDesc)
458193267Sjkim    {
459193267Sjkim        AcpiUtAddReference (ObjDesc);
460193267Sjkim        AcpiUtRemoveReference (Info->ReturnObject);
461193267Sjkim        Info->ReturnObject = ObjDesc;
462193267Sjkim    }
463193267Sjkim
464193267Sjkim    return;
465193267Sjkim}
466193267Sjkim
467193267Sjkim
468193267Sjkim/*******************************************************************************
469193267Sjkim *
470100966Siwasaki * FUNCTION:    AcpiWalkNamespace
471100966Siwasaki *
472100966Siwasaki * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
473100966Siwasaki *              StartObject         - Handle in namespace where search begins
474100966Siwasaki *              MaxDepth            - Depth to which search is to reach
475199337Sjkim *              PreOrderVisit       - Called during tree pre-order visit
476199337Sjkim *                                    when an object of "Type" is found
477199337Sjkim *              PostOrderVisit      - Called during tree post-order visit
478199337Sjkim *                                    when an object of "Type" is found
479199337Sjkim *              Context             - Passed to user function(s) above
480100966Siwasaki *              ReturnValue         - Location where return value of
481100966Siwasaki *                                    UserFunction is put if terminated early
482100966Siwasaki *
483100966Siwasaki * RETURNS      Return value from the UserFunction if terminated early.
484100966Siwasaki *              Otherwise, returns NULL.
485100966Siwasaki *
486100966Siwasaki * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
487100966Siwasaki *              starting (and ending) at the object specified by StartHandle.
488199337Sjkim *              The callback function is called whenever an object that matches
489199337Sjkim *              the type parameter is found. If the callback function returns
490100966Siwasaki *              a non-zero value, the search is terminated immediately and this
491100966Siwasaki *              value is returned to the caller.
492100966Siwasaki *
493100966Siwasaki *              The point of this procedure is to provide a generic namespace
494100966Siwasaki *              walk routine that can be called from multiple places to
495199337Sjkim *              provide multiple services; the callback function(s) can be
496199337Sjkim *              tailored to each task, whether it is a print function,
497199337Sjkim *              a compare function, etc.
498100966Siwasaki *
499100966Siwasaki ******************************************************************************/
500100966Siwasaki
501100966SiwasakiACPI_STATUS
502100966SiwasakiAcpiWalkNamespace (
503100966Siwasaki    ACPI_OBJECT_TYPE        Type,
504100966Siwasaki    ACPI_HANDLE             StartObject,
505100966Siwasaki    UINT32                  MaxDepth,
506199337Sjkim    ACPI_WALK_CALLBACK      PreOrderVisit,
507199337Sjkim    ACPI_WALK_CALLBACK      PostOrderVisit,
508100966Siwasaki    void                    *Context,
509100966Siwasaki    void                    **ReturnValue)
510100966Siwasaki{
511100966Siwasaki    ACPI_STATUS             Status;
512100966Siwasaki
513100966Siwasaki
514167802Sjkim    ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
515100966Siwasaki
516100966Siwasaki
517100966Siwasaki    /* Parameter validation */
518100966Siwasaki
519167802Sjkim    if ((Type > ACPI_TYPE_LOCAL_MAX) ||
520167802Sjkim        (!MaxDepth)                  ||
521199337Sjkim        (!PreOrderVisit && !PostOrderVisit))
522100966Siwasaki    {
523100966Siwasaki        return_ACPI_STATUS (AE_BAD_PARAMETER);
524100966Siwasaki    }
525100966Siwasaki
526100966Siwasaki    /*
527193267Sjkim     * Need to acquire the namespace reader lock to prevent interference
528193267Sjkim     * with any concurrent table unloads (which causes the deletion of
529193267Sjkim     * namespace objects). We cannot allow the deletion of a namespace node
530193267Sjkim     * while the user function is using it. The exception to this are the
531193267Sjkim     * nodes created and deleted during control method execution -- these
532193267Sjkim     * nodes are marked as temporary nodes and are ignored by the namespace
533193267Sjkim     * walk. Thus, control methods can be executed while holding the
534193267Sjkim     * namespace deletion lock (and the user function can execute control
535193267Sjkim     * methods.)
536100966Siwasaki     */
537193267Sjkim    Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
538193267Sjkim    if (ACPI_FAILURE (Status))
539193267Sjkim    {
540193267Sjkim        return (Status);
541193267Sjkim    }
542193267Sjkim
543193267Sjkim    /*
544193267Sjkim     * Lock the namespace around the walk. The namespace will be
545193267Sjkim     * unlocked/locked around each call to the user function - since the user
546193267Sjkim     * function must be allowed to make ACPICA calls itself (for example, it
547193267Sjkim     * will typically execute control methods during device enumeration.)
548193267Sjkim     */
549100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
550100966Siwasaki    if (ACPI_FAILURE (Status))
551100966Siwasaki    {
552193267Sjkim        goto UnlockAndExit;
553100966Siwasaki    }
554100966Siwasaki
555151937Sjkim    Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
556199337Sjkim                ACPI_NS_WALK_UNLOCK, PreOrderVisit,
557199337Sjkim                PostOrderVisit, Context, ReturnValue);
558100966Siwasaki
559100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
560193267Sjkim
561193267SjkimUnlockAndExit:
562193267Sjkim    (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
563100966Siwasaki    return_ACPI_STATUS (Status);
564100966Siwasaki}
565100966Siwasaki
566167802SjkimACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
567100966Siwasaki
568167802Sjkim
569100966Siwasaki/*******************************************************************************
570100966Siwasaki *
571100966Siwasaki * FUNCTION:    AcpiNsGetDeviceCallback
572100966Siwasaki *
573100966Siwasaki * PARAMETERS:  Callback from AcpiGetDevice
574100966Siwasaki *
575100966Siwasaki * RETURN:      Status
576100966Siwasaki *
577100966Siwasaki * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
578100966Siwasaki *              present devices, or if they specified a HID, it filters based
579100966Siwasaki *              on that.
580100966Siwasaki *
581100966Siwasaki ******************************************************************************/
582100966Siwasaki
583100966Siwasakistatic ACPI_STATUS
584100966SiwasakiAcpiNsGetDeviceCallback (
585100966Siwasaki    ACPI_HANDLE             ObjHandle,
586100966Siwasaki    UINT32                  NestingLevel,
587100966Siwasaki    void                    *Context,
588100966Siwasaki    void                    **ReturnValue)
589100966Siwasaki{
590117521Snjl    ACPI_GET_DEVICES_INFO   *Info = Context;
591100966Siwasaki    ACPI_STATUS             Status;
592100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
593100966Siwasaki    UINT32                  Flags;
594197104Sjkim    ACPI_DEVICE_ID          *Hid;
595197104Sjkim    ACPI_DEVICE_ID_LIST     *Cid;
596193267Sjkim    UINT32                  i;
597193267Sjkim    BOOLEAN                 Found;
598197104Sjkim    int                     NoMatch;
599100966Siwasaki
600100966Siwasaki
601100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
602100966Siwasaki    if (ACPI_FAILURE (Status))
603100966Siwasaki    {
604100966Siwasaki        return (Status);
605100966Siwasaki    }
606100966Siwasaki
607200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
608100966Siwasaki    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
609100966Siwasaki    if (ACPI_FAILURE (Status))
610100966Siwasaki    {
611100966Siwasaki        return (Status);
612100966Siwasaki    }
613100966Siwasaki
614100966Siwasaki    if (!Node)
615100966Siwasaki    {
616100966Siwasaki        return (AE_BAD_PARAMETER);
617100966Siwasaki    }
618100966Siwasaki
619202771Sjkim    /*
620202771Sjkim     * First, filter based on the device HID and CID.
621202771Sjkim     *
622202771Sjkim     * 01/2010: For this case where a specific HID is requested, we don't
623202771Sjkim     * want to run _STA until we have an actual HID match. Thus, we will
624202771Sjkim     * not unnecessarily execute _STA on devices for which the caller
625202771Sjkim     * doesn't care about. Previously, _STA was executed unconditionally
626202771Sjkim     * on all devices found here.
627202771Sjkim     *
628202771Sjkim     * A side-effect of this change is that now we will continue to search
629202771Sjkim     * for a matching HID even under device trees where the parent device
630202771Sjkim     * would have returned a _STA that indicates it is not present or
631202771Sjkim     * not functioning (thus aborting the search on that branch).
632202771Sjkim     */
633100966Siwasaki    if (Info->Hid != NULL)
634100966Siwasaki    {
635100966Siwasaki        Status = AcpiUtExecute_HID (Node, &Hid);
636100966Siwasaki        if (Status == AE_NOT_FOUND)
637100966Siwasaki        {
638100966Siwasaki            return (AE_OK);
639100966Siwasaki        }
640100966Siwasaki        else if (ACPI_FAILURE (Status))
641100966Siwasaki        {
642100966Siwasaki            return (AE_CTRL_DEPTH);
643100966Siwasaki        }
644100966Siwasaki
645197104Sjkim        NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
646197104Sjkim        ACPI_FREE (Hid);
647197104Sjkim
648197104Sjkim        if (NoMatch)
649100966Siwasaki        {
650193267Sjkim            /*
651193267Sjkim             * HID does not match, attempt match within the
652193267Sjkim             * list of Compatible IDs (CIDs)
653193267Sjkim             */
654100966Siwasaki            Status = AcpiUtExecute_CID (Node, &Cid);
655100966Siwasaki            if (Status == AE_NOT_FOUND)
656100966Siwasaki            {
657100966Siwasaki                return (AE_OK);
658100966Siwasaki            }
659100966Siwasaki            else if (ACPI_FAILURE (Status))
660100966Siwasaki            {
661100966Siwasaki                return (AE_CTRL_DEPTH);
662100966Siwasaki            }
663100966Siwasaki
664117521Snjl            /* Walk the CID list */
665100966Siwasaki
666193267Sjkim            Found = FALSE;
667117521Snjl            for (i = 0; i < Cid->Count; i++)
668100966Siwasaki            {
669197104Sjkim                if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
670117521Snjl                {
671193267Sjkim                    /* Found a matching CID */
672193267Sjkim
673193267Sjkim                    Found = TRUE;
674193267Sjkim                    break;
675117521Snjl                }
676100966Siwasaki            }
677193267Sjkim
678167802Sjkim            ACPI_FREE (Cid);
679193267Sjkim            if (!Found)
680193267Sjkim            {
681193267Sjkim                return (AE_OK);
682193267Sjkim            }
683100966Siwasaki        }
684100966Siwasaki    }
685100966Siwasaki
686202771Sjkim    /* Run _STA to determine if device is present */
687202771Sjkim
688202771Sjkim    Status = AcpiUtExecute_STA (Node, &Flags);
689202771Sjkim    if (ACPI_FAILURE (Status))
690202771Sjkim    {
691202771Sjkim        return (AE_CTRL_DEPTH);
692202771Sjkim    }
693202771Sjkim
694202771Sjkim    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
695202771Sjkim        !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
696202771Sjkim    {
697202771Sjkim        /*
698202771Sjkim         * Don't examine the children of the device only when the
699202771Sjkim         * device is neither present nor functional. See ACPI spec,
700202771Sjkim         * description of _STA for more information.
701202771Sjkim         */
702202771Sjkim        return (AE_CTRL_DEPTH);
703202771Sjkim    }
704202771Sjkim
705193267Sjkim    /* We have a valid device, invoke the user function */
706193267Sjkim
707151937Sjkim    Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
708151937Sjkim                ReturnValue);
709100966Siwasaki    return (Status);
710100966Siwasaki}
711100966Siwasaki
712100966Siwasaki
713100966Siwasaki/*******************************************************************************
714100966Siwasaki *
715100966Siwasaki * FUNCTION:    AcpiGetDevices
716100966Siwasaki *
717100966Siwasaki * PARAMETERS:  HID                 - HID to search for. Can be NULL.
718100966Siwasaki *              UserFunction        - Called when a matching object is found
719100966Siwasaki *              Context             - Passed to user function
720100966Siwasaki *              ReturnValue         - Location where return value of
721100966Siwasaki *                                    UserFunction is put if terminated early
722100966Siwasaki *
723100966Siwasaki * RETURNS      Return value from the UserFunction if terminated early.
724100966Siwasaki *              Otherwise, returns NULL.
725100966Siwasaki *
726100966Siwasaki * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
727100966Siwasaki *              starting (and ending) at the object specified by StartHandle.
728117521Snjl *              The UserFunction is called whenever an object of type
729117521Snjl *              Device is found.  If the user function returns
730100966Siwasaki *              a non-zero value, the search is terminated immediately and this
731100966Siwasaki *              value is returned to the caller.
732100966Siwasaki *
733100966Siwasaki *              This is a wrapper for WalkNamespace, but the callback performs
734193267Sjkim *              additional filtering. Please see AcpiNsGetDeviceCallback.
735100966Siwasaki *
736100966Siwasaki ******************************************************************************/
737100966Siwasaki
738100966SiwasakiACPI_STATUS
739100966SiwasakiAcpiGetDevices (
740114237Snjl    char                    *HID,
741100966Siwasaki    ACPI_WALK_CALLBACK      UserFunction,
742100966Siwasaki    void                    *Context,
743100966Siwasaki    void                    **ReturnValue)
744100966Siwasaki{
745100966Siwasaki    ACPI_STATUS             Status;
746100966Siwasaki    ACPI_GET_DEVICES_INFO   Info;
747100966Siwasaki
748100966Siwasaki
749167802Sjkim    ACPI_FUNCTION_TRACE (AcpiGetDevices);
750100966Siwasaki
751100966Siwasaki
752100966Siwasaki    /* Parameter validation */
753100966Siwasaki
754100966Siwasaki    if (!UserFunction)
755100966Siwasaki    {
756100966Siwasaki        return_ACPI_STATUS (AE_BAD_PARAMETER);
757100966Siwasaki    }
758100966Siwasaki
759100966Siwasaki    /*
760100966Siwasaki     * We're going to call their callback from OUR callback, so we need
761100966Siwasaki     * to know what it is, and their context parameter.
762100966Siwasaki     */
763167802Sjkim    Info.Hid          = HID;
764100966Siwasaki    Info.Context      = Context;
765100966Siwasaki    Info.UserFunction = UserFunction;
766100966Siwasaki
767100966Siwasaki    /*
768100966Siwasaki     * Lock the namespace around the walk.
769100966Siwasaki     * The namespace will be unlocked/locked around each call
770100966Siwasaki     * to the user function - since this function
771100966Siwasaki     * must be allowed to make Acpi calls itself.
772100966Siwasaki     */
773100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
774100966Siwasaki    if (ACPI_FAILURE (Status))
775100966Siwasaki    {
776100966Siwasaki        return_ACPI_STATUS (Status);
777100966Siwasaki    }
778100966Siwasaki
779167802Sjkim    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
780167802Sjkim                ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
781199337Sjkim                AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
782100966Siwasaki
783100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
784100966Siwasaki    return_ACPI_STATUS (Status);
785100966Siwasaki}
786100966Siwasaki
787167802SjkimACPI_EXPORT_SYMBOL (AcpiGetDevices)
788100966Siwasaki
789167802Sjkim
790100966Siwasaki/*******************************************************************************
791100966Siwasaki *
792100966Siwasaki * FUNCTION:    AcpiAttachData
793100966Siwasaki *
794114237Snjl * PARAMETERS:  ObjHandle           - Namespace node
795107325Siwasaki *              Handler             - Handler for this attachment
796107325Siwasaki *              Data                - Pointer to data to be attached
797100966Siwasaki *
798100966Siwasaki * RETURN:      Status
799100966Siwasaki *
800107325Siwasaki * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
801100966Siwasaki *
802100966Siwasaki ******************************************************************************/
803100966Siwasaki
804100966SiwasakiACPI_STATUS
805100966SiwasakiAcpiAttachData (
806100966Siwasaki    ACPI_HANDLE             ObjHandle,
807100966Siwasaki    ACPI_OBJECT_HANDLER     Handler,
808100966Siwasaki    void                    *Data)
809100966Siwasaki{
810100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
811100966Siwasaki    ACPI_STATUS             Status;
812100966Siwasaki
813100966Siwasaki
814100966Siwasaki    /* Parameter validation */
815100966Siwasaki
816100966Siwasaki    if (!ObjHandle  ||
817100966Siwasaki        !Handler    ||
818100966Siwasaki        !Data)
819100966Siwasaki    {
820100966Siwasaki        return (AE_BAD_PARAMETER);
821100966Siwasaki    }
822100966Siwasaki
823100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
824100966Siwasaki    if (ACPI_FAILURE (Status))
825100966Siwasaki    {
826100966Siwasaki        return (Status);
827100966Siwasaki    }
828100966Siwasaki
829100966Siwasaki    /* Convert and validate the handle */
830100966Siwasaki
831200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
832100966Siwasaki    if (!Node)
833100966Siwasaki    {
834100966Siwasaki        Status = AE_BAD_PARAMETER;
835100966Siwasaki        goto UnlockAndExit;
836100966Siwasaki    }
837100966Siwasaki
838100966Siwasaki    Status = AcpiNsAttachData (Node, Handler, Data);
839100966Siwasaki
840100966SiwasakiUnlockAndExit:
841100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
842100966Siwasaki    return (Status);
843100966Siwasaki}
844100966Siwasaki
845167802SjkimACPI_EXPORT_SYMBOL (AcpiAttachData)
846100966Siwasaki
847167802Sjkim
848100966Siwasaki/*******************************************************************************
849100966Siwasaki *
850100966Siwasaki * FUNCTION:    AcpiDetachData
851100966Siwasaki *
852107325Siwasaki * PARAMETERS:  ObjHandle           - Namespace node handle
853107325Siwasaki *              Handler             - Handler used in call to AcpiAttachData
854100966Siwasaki *
855100966Siwasaki * RETURN:      Status
856100966Siwasaki *
857107325Siwasaki * DESCRIPTION: Remove data that was previously attached to a node.
858100966Siwasaki *
859100966Siwasaki ******************************************************************************/
860100966Siwasaki
861100966SiwasakiACPI_STATUS
862100966SiwasakiAcpiDetachData (
863100966Siwasaki    ACPI_HANDLE             ObjHandle,
864100966Siwasaki    ACPI_OBJECT_HANDLER     Handler)
865100966Siwasaki{
866100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
867100966Siwasaki    ACPI_STATUS             Status;
868100966Siwasaki
869100966Siwasaki
870100966Siwasaki    /* Parameter validation */
871100966Siwasaki
872100966Siwasaki    if (!ObjHandle  ||
873100966Siwasaki        !Handler)
874100966Siwasaki    {
875100966Siwasaki        return (AE_BAD_PARAMETER);
876100966Siwasaki    }
877100966Siwasaki
878100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
879100966Siwasaki    if (ACPI_FAILURE (Status))
880100966Siwasaki    {
881100966Siwasaki        return (Status);
882100966Siwasaki    }
883100966Siwasaki
884100966Siwasaki    /* Convert and validate the handle */
885100966Siwasaki
886200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
887100966Siwasaki    if (!Node)
888100966Siwasaki    {
889100966Siwasaki        Status = AE_BAD_PARAMETER;
890100966Siwasaki        goto UnlockAndExit;
891100966Siwasaki    }
892100966Siwasaki
893100966Siwasaki    Status = AcpiNsDetachData (Node, Handler);
894100966Siwasaki
895100966SiwasakiUnlockAndExit:
896100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
897100966Siwasaki    return (Status);
898100966Siwasaki}
899100966Siwasaki
900167802SjkimACPI_EXPORT_SYMBOL (AcpiDetachData)
901100966Siwasaki
902167802Sjkim
903100966Siwasaki/*******************************************************************************
904100966Siwasaki *
905100966Siwasaki * FUNCTION:    AcpiGetData
906100966Siwasaki *
907107325Siwasaki * PARAMETERS:  ObjHandle           - Namespace node
908107325Siwasaki *              Handler             - Handler used in call to AttachData
909107325Siwasaki *              Data                - Where the data is returned
910100966Siwasaki *
911100966Siwasaki * RETURN:      Status
912100966Siwasaki *
913107325Siwasaki * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
914100966Siwasaki *
915100966Siwasaki ******************************************************************************/
916100966Siwasaki
917100966SiwasakiACPI_STATUS
918100966SiwasakiAcpiGetData (
919100966Siwasaki    ACPI_HANDLE             ObjHandle,
920100966Siwasaki    ACPI_OBJECT_HANDLER     Handler,
921100966Siwasaki    void                    **Data)
922100966Siwasaki{
923100966Siwasaki    ACPI_NAMESPACE_NODE     *Node;
924100966Siwasaki    ACPI_STATUS             Status;
925100966Siwasaki
926100966Siwasaki
927100966Siwasaki    /* Parameter validation */
928100966Siwasaki
929100966Siwasaki    if (!ObjHandle  ||
930100966Siwasaki        !Handler    ||
931100966Siwasaki        !Data)
932100966Siwasaki    {
933100966Siwasaki        return (AE_BAD_PARAMETER);
934100966Siwasaki    }
935100966Siwasaki
936100966Siwasaki    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
937100966Siwasaki    if (ACPI_FAILURE (Status))
938100966Siwasaki    {
939100966Siwasaki        return (Status);
940100966Siwasaki    }
941100966Siwasaki
942100966Siwasaki    /* Convert and validate the handle */
943100966Siwasaki
944200553Sjkim    Node = AcpiNsValidateHandle (ObjHandle);
945100966Siwasaki    if (!Node)
946100966Siwasaki    {
947100966Siwasaki        Status = AE_BAD_PARAMETER;
948100966Siwasaki        goto UnlockAndExit;
949100966Siwasaki    }
950100966Siwasaki
951100966Siwasaki    Status = AcpiNsGetAttachedData (Node, Handler, Data);
952100966Siwasaki
953100966SiwasakiUnlockAndExit:
954100966Siwasaki    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
955100966Siwasaki    return (Status);
956100966Siwasaki}
957100966Siwasaki
958167802SjkimACPI_EXPORT_SYMBOL (AcpiGetData)
959100966Siwasaki
960167802Sjkim
961