nsxfeval.c revision 193341
138363Swpaul/*******************************************************************************
238363Swpaul *
338363Swpaul * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
438363Swpaul *                         ACPI Object evaluation interfaces
538363Swpaul *
638363Swpaul ******************************************************************************/
738363Swpaul
838363Swpaul/******************************************************************************
938363Swpaul *
1038363Swpaul * 1. Copyright Notice
1138363Swpaul *
1238363Swpaul * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
1338363Swpaul * All rights reserved.
1438363Swpaul *
1538363Swpaul * 2. License
1638363Swpaul *
1738363Swpaul * 2.1. This is your license from Intel Corp. under its intellectual property
1838363Swpaul * rights.  You may have additional license terms from the party that provided
1938363Swpaul * you this software, covering your right to use that party's intellectual
2038363Swpaul * property rights.
2138363Swpaul *
2238363Swpaul * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2338363Swpaul * copy of the source code appearing in this file ("Covered Code") an
2438363Swpaul * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2538363Swpaul * base code distributed originally by Intel ("Original Intel Code") to copy,
2638363Swpaul * make derivatives, distribute, use and display any portion of the Covered
2738363Swpaul * Code in any form, with the right to sublicense such rights; and
2838363Swpaul *
2938363Swpaul * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3038363Swpaul * license (with the right to sublicense), under only those claims of Intel
3138363Swpaul * patents that are infringed by the Original Intel Code, to make, use, sell,
3238526Swpaul * offer to sell, and import the Covered Code and derivative works thereof
3338363Swpaul * solely to the minimum extent necessary to exercise the above copyright
3438363Swpaul * license, and in no event shall the patent license extend to any additions
3538363Swpaul * to or modifications of the Original Intel Code.  No other license or right
3638363Swpaul * is granted directly or by implication, estoppel or otherwise;
3738363Swpaul *
3838363Swpaul * The above copyright and patent license is granted only if the following
3938363Swpaul * conditions are met:
4038363Swpaul *
4138363Swpaul * 3. Conditions
4238363Swpaul *
4338363Swpaul * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4438363Swpaul * Redistribution of source code of any substantial portion of the Covered
4538363Swpaul * Code or modification with rights to further distribute source must include
4638363Swpaul * the above Copyright Notice, the above License, this list of Conditions,
4738363Swpaul * and the following Disclaimer and Export Compliance provision.  In addition,
4838363Swpaul * Licensee must cause all Covered Code to which Licensee contributes to
4938363Swpaul * contain a file documenting the changes Licensee made to create that Covered
5038363Swpaul * Code and the date of any change.  Licensee must include in that file the
5138363Swpaul * documentation of any changes made by any predecessor Licensee.  Licensee
5238363Swpaul * must include a prominent statement that the modification is derived,
5338363Swpaul * directly or indirectly, from Original Intel Code.
5438363Swpaul *
5538363Swpaul * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5638363Swpaul * Redistribution of source code of any substantial portion of the Covered
5738363Swpaul * Code or modification without rights to further distribute source must
5838363Swpaul * include the following Disclaimer and Export Compliance provision in the
5938363Swpaul * documentation and/or other materials provided with distribution.  In
6038363Swpaul * addition, Licensee may not authorize further sublicense of source of any
6138363Swpaul * portion of the Covered Code, and must include terms to the effect that the
6238363Swpaul * license from Licensee to its licensee is limited to the intellectual
6338363Swpaul * property embodied in the software Licensee provides to its licensee, and
6438363Swpaul * not to intellectual property embodied in modifications its licensee may
6538363Swpaul * make.
6638363Swpaul *
6738363Swpaul * 3.3. Redistribution of Executable. Redistribution in executable form of any
6838363Swpaul * substantial portion of the Covered Code or modification must reproduce the
6938363Swpaul * above Copyright Notice, and the following Disclaimer and Export Compliance
7038363Swpaul * provision in the documentation and/or other materials provided with the
7138363Swpaul * distribution.
7238363Swpaul *
7338363Swpaul * 3.4. Intel retains all right, title, and interest in and to the Original
7438363Swpaul * Intel Code.
7538363Swpaul *
7638363Swpaul * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7738363Swpaul * Intel shall be used in advertising or otherwise to promote the sale, use or
7838363Swpaul * other dealings in products derived from or relating to the Covered Code
7938363Swpaul * without prior written authorization from Intel.
8038363Swpaul *
8138363Swpaul * 4. Disclaimer and Export Compliance
8238363Swpaul *
8338363Swpaul * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8438363Swpaul * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8538363Swpaul * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8638363Swpaul * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8738363Swpaul * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8838363Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8938363Swpaul * PARTICULAR PURPOSE.
9038363Swpaul *
9138363Swpaul * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9238363Swpaul * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9338363Swpaul * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9438363Swpaul * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9538363Swpaul * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9638363Swpaul * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9738363Swpaul * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9838363Swpaul * LIMITED REMEDY.
9938363Swpaul *
10038363Swpaul * 4.3. Licensee shall not export, either directly or indirectly, any of this
10138363Swpaul * software or system incorporating such software without first obtaining any
10238363Swpaul * required license or other approval from the U. S. Department of Commerce or
10338363Swpaul * any other agency or department of the United States Government.  In the
10438363Swpaul * event Licensee exports any such software from the United States or
10538363Swpaul * re-exports any such software from a foreign destination, Licensee shall
10638363Swpaul * ensure that the distribution and export/re-export of the software is in
10738363Swpaul * compliance with all laws, regulations, orders, or other restrictions of the
10838363Swpaul * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10938363Swpaul * any of its subsidiaries will export/re-export any technical data, process,
11038363Swpaul * software, or service, directly or indirectly, to any country for which the
11138363Swpaul * United States government or any agency thereof requires an export license,
11238363Swpaul * other governmental approval, or letter of assurance, without first obtaining
11338363Swpaul * such license, approval or letter.
11438363Swpaul *
11538363Swpaul *****************************************************************************/
11638363Swpaul
11738363Swpaul
11838363Swpaul#define __NSXFEVAL_C__
11938363Swpaul
12038363Swpaul#include <contrib/dev/acpica/include/acpi.h>
12138363Swpaul#include <contrib/dev/acpica/include/accommon.h>
12238363Swpaul#include <contrib/dev/acpica/include/acnamesp.h>
12338363Swpaul#include <contrib/dev/acpica/include/acinterp.h>
12438363Swpaul
12538363Swpaul
12638363Swpaul#define _COMPONENT          ACPI_NAMESPACE
12738363Swpaul        ACPI_MODULE_NAME    ("nsxfeval")
12838363Swpaul
12938363Swpaul/* Local prototypes */
13038363Swpaul
13138363Swpaulstatic void
13238363SwpaulAcpiNsResolveReferences (
13338363Swpaul    ACPI_EVALUATE_INFO      *Info);
13438363Swpaul
13538363Swpaul
13638363Swpaul/*******************************************************************************
13738363Swpaul *
13838363Swpaul * FUNCTION:    AcpiEvaluateObjectTyped
13938363Swpaul *
14038363Swpaul * PARAMETERS:  Handle              - Object handle (optional)
14138363Swpaul *              Pathname            - Object pathname (optional)
14238363Swpaul *              ExternalParams      - List of parameters to pass to method,
14338363Swpaul *                                    terminated by NULL.  May be NULL
14438363Swpaul *                                    if no parameters are being passed.
14538363Swpaul *              ReturnBuffer        - Where to put method's return value (if
14638363Swpaul *                                    any).  If NULL, no value is returned.
14738363Swpaul *              ReturnType          - Expected type of return object
14838363Swpaul *
14938363Swpaul * RETURN:      Status
15038363Swpaul *
15138363Swpaul * DESCRIPTION: Find and evaluate the given object, passing the given
15238363Swpaul *              parameters if necessary.  One of "Handle" or "Pathname" must
15338363Swpaul *              be valid (non-null)
15438363Swpaul *
15538363Swpaul ******************************************************************************/
15638363Swpaul
15738363SwpaulACPI_STATUS
15838363SwpaulAcpiEvaluateObjectTyped (
15938363Swpaul    ACPI_HANDLE             Handle,
16038363Swpaul    ACPI_STRING             Pathname,
16138363Swpaul    ACPI_OBJECT_LIST        *ExternalParams,
16238363Swpaul    ACPI_BUFFER             *ReturnBuffer,
16338363Swpaul    ACPI_OBJECT_TYPE        ReturnType)
16438363Swpaul{
16538363Swpaul    ACPI_STATUS             Status;
16638363Swpaul    BOOLEAN                 MustFree = FALSE;
16738363Swpaul
16838363Swpaul
16938363Swpaul    ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
17038363Swpaul
17138363Swpaul
17238363Swpaul    /* Return buffer must be valid */
17338363Swpaul
17438526Swpaul    if (!ReturnBuffer)
17538526Swpaul    {
17638526Swpaul        return_ACPI_STATUS (AE_BAD_PARAMETER);
17738526Swpaul    }
17838526Swpaul
17938526Swpaul    if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
18038526Swpaul    {
18138363Swpaul        MustFree = TRUE;
18238363Swpaul    }
18338363Swpaul
18438363Swpaul    /* Evaluate the object */
18538363Swpaul
18638363Swpaul    Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer);
18738363Swpaul    if (ACPI_FAILURE (Status))
18838363Swpaul    {
18938363Swpaul        return_ACPI_STATUS (Status);
19038363Swpaul    }
19138363Swpaul
19238363Swpaul    /* Type ANY means "don't care" */
19338363Swpaul
19438363Swpaul    if (ReturnType == ACPI_TYPE_ANY)
19538363Swpaul    {
19638363Swpaul        return_ACPI_STATUS (AE_OK);
19738363Swpaul    }
19838363Swpaul
19938363Swpaul    if (ReturnBuffer->Length == 0)
20038363Swpaul    {
20138363Swpaul        /* Error because caller specifically asked for a return value */
20238363Swpaul
20338363Swpaul        ACPI_ERROR ((AE_INFO, "No return value"));
20438363Swpaul        return_ACPI_STATUS (AE_NULL_OBJECT);
20538363Swpaul    }
20638363Swpaul
20738363Swpaul    /* Examine the object type returned from EvaluateObject */
20838363Swpaul
20938363Swpaul    if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
21038363Swpaul    {
21138363Swpaul        return_ACPI_STATUS (AE_OK);
21238363Swpaul    }
21338363Swpaul
21438363Swpaul    /* Return object type does not match requested type */
21538363Swpaul
21638363Swpaul    ACPI_ERROR ((AE_INFO,
21738363Swpaul        "Incorrect return type [%s] requested [%s]",
21838363Swpaul        AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
21938363Swpaul        AcpiUtGetTypeName (ReturnType)));
22038363Swpaul
22138363Swpaul    if (MustFree)
22238363Swpaul    {
22338363Swpaul        /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
22438363Swpaul
22538363Swpaul        AcpiOsFree (ReturnBuffer->Pointer);
22638363Swpaul        ReturnBuffer->Pointer = NULL;
22738363Swpaul    }
22838363Swpaul
22938363Swpaul    ReturnBuffer->Length = 0;
23038363Swpaul    return_ACPI_STATUS (AE_TYPE);
23138363Swpaul}
23238363Swpaul
23338363SwpaulACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
23438363Swpaul
23538363Swpaul
23638363Swpaul/*******************************************************************************
23738363Swpaul *
23838363Swpaul * FUNCTION:    AcpiEvaluateObject
23938363Swpaul *
24038363Swpaul * PARAMETERS:  Handle              - Object handle (optional)
24138363Swpaul *              Pathname            - Object pathname (optional)
24238363Swpaul *              ExternalParams      - List of parameters to pass to method,
24338363Swpaul *                                    terminated by NULL.  May be NULL
24438363Swpaul *                                    if no parameters are being passed.
24538363Swpaul *              ReturnBuffer        - Where to put method's return value (if
24638363Swpaul *                                    any).  If NULL, no value is returned.
24738363Swpaul *
24838363Swpaul * RETURN:      Status
24938363Swpaul *
25038363Swpaul * DESCRIPTION: Find and evaluate the given object, passing the given
25138363Swpaul *              parameters if necessary.  One of "Handle" or "Pathname" must
25238363Swpaul *              be valid (non-null)
25338363Swpaul *
25438363Swpaul ******************************************************************************/
25538363Swpaul
25638363SwpaulACPI_STATUS
25738363SwpaulAcpiEvaluateObject (
25838363Swpaul    ACPI_HANDLE             Handle,
25938363Swpaul    ACPI_STRING             Pathname,
26038363Swpaul    ACPI_OBJECT_LIST        *ExternalParams,
26138363Swpaul    ACPI_BUFFER             *ReturnBuffer)
26238363Swpaul{
26338363Swpaul    ACPI_STATUS             Status;
26438363Swpaul    ACPI_EVALUATE_INFO      *Info;
26538363Swpaul    ACPI_SIZE               BufferSpaceNeeded;
26638363Swpaul    UINT32                  i;
26738363Swpaul
26838363Swpaul
26938363Swpaul    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
27038363Swpaul
27138363Swpaul
27238363Swpaul    /* Allocate and initialize the evaluation information block */
27338363Swpaul
27438363Swpaul    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
27538363Swpaul    if (!Info)
27638363Swpaul    {
27738363Swpaul        return_ACPI_STATUS (AE_NO_MEMORY);
27838363Swpaul    }
27938363Swpaul
28038363Swpaul    Info->Pathname = Pathname;
28138363Swpaul
28238363Swpaul    /* Convert and validate the device handle */
28338363Swpaul
28438363Swpaul    Info->PrefixNode = AcpiNsMapHandleToNode (Handle);
28538363Swpaul    if (!Info->PrefixNode)
28638363Swpaul    {
28738363Swpaul        Status = AE_BAD_PARAMETER;
28838363Swpaul        goto Cleanup;
28938363Swpaul    }
29038363Swpaul
29138363Swpaul    /*
29238363Swpaul     * If there are parameters to be passed to a control method, the external
29338363Swpaul     * objects must all be converted to internal objects
29438363Swpaul     */
29538363Swpaul    if (ExternalParams && ExternalParams->Count)
29638363Swpaul    {
29738363Swpaul        /*
29838363Swpaul         * Allocate a new parameter block for the internal objects
29938363Swpaul         * Add 1 to count to allow for null terminated internal list
30038363Swpaul         */
30138363Swpaul        Info->Parameters = ACPI_ALLOCATE_ZEROED (
30238363Swpaul            ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
30338363Swpaul        if (!Info->Parameters)
30438363Swpaul        {
30538363Swpaul            Status = AE_NO_MEMORY;
30638363Swpaul            goto Cleanup;
30738363Swpaul        }
30838363Swpaul
30938363Swpaul        /* Convert each external object in the list to an internal object */
31038363Swpaul
31138363Swpaul        for (i = 0; i < ExternalParams->Count; i++)
31238363Swpaul        {
31338363Swpaul            Status = AcpiUtCopyEobjectToIobject (
31438363Swpaul                        &ExternalParams->Pointer[i], &Info->Parameters[i]);
31538363Swpaul            if (ACPI_FAILURE (Status))
31638363Swpaul            {
31738363Swpaul                goto Cleanup;
31838363Swpaul            }
31938363Swpaul        }
32038363Swpaul        Info->Parameters[ExternalParams->Count] = NULL;
32138363Swpaul    }
32238363Swpaul
32338363Swpaul    /*
32438363Swpaul     * Three major cases:
32538363Swpaul     * 1) Fully qualified pathname
32638363Swpaul     * 2) No handle, not fully qualified pathname (error)
32738363Swpaul     * 3) Valid handle
32838363Swpaul     */
32938363Swpaul    if ((Pathname) &&
33038363Swpaul        (AcpiNsValidRootPrefix (Pathname[0])))
33138363Swpaul    {
33238363Swpaul        /* The path is fully qualified, just evaluate by name */
33338363Swpaul
33438363Swpaul        Info->PrefixNode = NULL;
33538363Swpaul        Status = AcpiNsEvaluate (Info);
33638363Swpaul    }
33738363Swpaul    else if (!Handle)
33838363Swpaul    {
33938363Swpaul        /*
34038363Swpaul         * A handle is optional iff a fully qualified pathname is specified.
34138363Swpaul         * Since we've already handled fully qualified names above, this is
34238363Swpaul         * an error
34338363Swpaul         */
34438363Swpaul        if (!Pathname)
34538363Swpaul        {
34638363Swpaul            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
34738363Swpaul                "Both Handle and Pathname are NULL"));
34838363Swpaul        }
34938363Swpaul        else
35038363Swpaul        {
35138363Swpaul            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
35238363Swpaul                "Null Handle with relative pathname [%s]", Pathname));
35338363Swpaul        }
35438363Swpaul
35538363Swpaul        Status = AE_BAD_PARAMETER;
35638363Swpaul    }
35738363Swpaul    else
35838363Swpaul    {
35938363Swpaul        /* We have a namespace a node and a possible relative path */
36038363Swpaul
36138363Swpaul        Status = AcpiNsEvaluate (Info);
36238363Swpaul    }
36338363Swpaul
36438363Swpaul    /*
36538363Swpaul     * If we are expecting a return value, and all went well above,
36638363Swpaul     * copy the return value to an external object.
36738363Swpaul     */
36838363Swpaul    if (ReturnBuffer)
36938363Swpaul    {
37038363Swpaul        if (!Info->ReturnObject)
37138363Swpaul        {
37238363Swpaul            ReturnBuffer->Length = 0;
37338363Swpaul        }
37438363Swpaul        else
37538363Swpaul        {
37638363Swpaul            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
37738363Swpaul                ACPI_DESC_TYPE_NAMED)
37838363Swpaul            {
37938363Swpaul                /*
38038363Swpaul                 * If we received a NS Node as a return object, this means that
38138363Swpaul                 * the object we are evaluating has nothing interesting to
38238363Swpaul                 * return (such as a mutex, etc.)  We return an error because
38338363Swpaul                 * these types are essentially unsupported by this interface.
38438363Swpaul                 * We don't check up front because this makes it easier to add
38538363Swpaul                 * support for various types at a later date if necessary.
38638363Swpaul                 */
38738363Swpaul                Status = AE_TYPE;
38838363Swpaul                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
38938363Swpaul                ReturnBuffer->Length = 0;
39038363Swpaul            }
39138363Swpaul
39238363Swpaul            if (ACPI_SUCCESS (Status))
39338363Swpaul            {
39438363Swpaul                /* Dereference Index and RefOf references */
39538363Swpaul
39638363Swpaul                AcpiNsResolveReferences (Info);
39738363Swpaul
39838363Swpaul                /* Get the size of the returned object */
39938363Swpaul
40038363Swpaul                Status = AcpiUtGetObjectSize (Info->ReturnObject,
40138363Swpaul                            &BufferSpaceNeeded);
40238363Swpaul                if (ACPI_SUCCESS (Status))
40338363Swpaul                {
40438363Swpaul                    /* Validate/Allocate/Clear caller buffer */
40538363Swpaul
40638363Swpaul                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
40738363Swpaul                                BufferSpaceNeeded);
40838363Swpaul                    if (ACPI_FAILURE (Status))
40938363Swpaul                    {
41038363Swpaul                        /*
41138363Swpaul                         * Caller's buffer is too small or a new one can't
41238363Swpaul                         * be allocated
41338363Swpaul                         */
41438363Swpaul                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
41538363Swpaul                            "Needed buffer size %X, %s\n",
41638363Swpaul                            (UINT32) BufferSpaceNeeded,
41738363Swpaul                            AcpiFormatException (Status)));
41838363Swpaul                    }
41938363Swpaul                    else
42038363Swpaul                    {
42138363Swpaul                        /* We have enough space for the object, build it */
42238363Swpaul
42338363Swpaul                        Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
42438363Swpaul                                    ReturnBuffer);
42538363Swpaul                    }
42638363Swpaul                }
42738363Swpaul            }
42838363Swpaul        }
42938363Swpaul    }
43038363Swpaul
43138363Swpaul    if (Info->ReturnObject)
43238363Swpaul    {
43338363Swpaul        /*
43438363Swpaul         * Delete the internal return object. NOTE: Interpreter must be
43538363Swpaul         * locked to avoid race condition.
43638363Swpaul         */
43738363Swpaul        AcpiExEnterInterpreter ();
43838363Swpaul
43938469Swpaul        /* Remove one reference on the return object (should delete it) */
44038363Swpaul
44138363Swpaul        AcpiUtRemoveReference (Info->ReturnObject);
44238363Swpaul        AcpiExExitInterpreter ();
44338363Swpaul    }
44438363Swpaul
44538363Swpaul
44638363SwpaulCleanup:
44738363Swpaul
44838363Swpaul    /* Free the input parameter list (if we created one) */
44938363Swpaul
45038363Swpaul    if (Info->Parameters)
45138363Swpaul    {
45238363Swpaul        /* Free the allocated parameter block */
45338363Swpaul
45438363Swpaul        AcpiUtDeleteInternalObjectList (Info->Parameters);
45538363Swpaul    }
45638363Swpaul
45738363Swpaul    ACPI_FREE (Info);
45838363Swpaul    return_ACPI_STATUS (Status);
45938363Swpaul}
46038363Swpaul
46138363SwpaulACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
46238363Swpaul
46338363Swpaul
46438363Swpaul/*******************************************************************************
46538363Swpaul *
46638363Swpaul * FUNCTION:    AcpiNsResolveReferences
46738363Swpaul *
46838363Swpaul * PARAMETERS:  Info                    - Evaluation info block
46938363Swpaul *
47038363Swpaul * RETURN:      Info->ReturnObject is replaced with the dereferenced object
47138363Swpaul *
47238363Swpaul * DESCRIPTION: Dereference certain reference objects. Called before an
47338363Swpaul *              internal return object is converted to an external ACPI_OBJECT.
47438363Swpaul *
47538363Swpaul * Performs an automatic dereference of Index and RefOf reference objects.
47638363Swpaul * These reference objects are not supported by the ACPI_OBJECT, so this is a
47738363Swpaul * last resort effort to return something useful. Also, provides compatibility
47838363Swpaul * with other ACPI implementations.
47938363Swpaul *
48038363Swpaul * NOTE: does not handle references within returned package objects or nested
48138363Swpaul * references, but this support could be added later if found to be necessary.
48238363Swpaul *
48338363Swpaul ******************************************************************************/
48438363Swpaul
48538363Swpaulstatic void
48638363SwpaulAcpiNsResolveReferences (
48738363Swpaul    ACPI_EVALUATE_INFO      *Info)
48838363Swpaul{
48938363Swpaul    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
49038363Swpaul    ACPI_NAMESPACE_NODE     *Node;
49138363Swpaul
49238363Swpaul
49338363Swpaul    /* We are interested in reference objects only */
49438363Swpaul
49538363Swpaul    if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
49638363Swpaul    {
49738363Swpaul        return;
49838363Swpaul    }
49938363Swpaul
50038363Swpaul    /*
50138363Swpaul     * Two types of references are supported - those created by Index and
50238363Swpaul     * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
50338363Swpaul     * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
50438363Swpaul     * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
50538363Swpaul     * an ACPI_OBJECT.
50638363Swpaul     */
50738363Swpaul    switch (Info->ReturnObject->Reference.Class)
50838363Swpaul    {
50938363Swpaul    case ACPI_REFCLASS_INDEX:
51038363Swpaul
51138363Swpaul        ObjDesc = *(Info->ReturnObject->Reference.Where);
51238363Swpaul        break;
51338363Swpaul
51438363Swpaul    case ACPI_REFCLASS_REFOF:
51538363Swpaul
51638363Swpaul        Node = Info->ReturnObject->Reference.Object;
51738363Swpaul        if (Node)
51838363Swpaul        {
51938363Swpaul            ObjDesc = Node->Object;
52038363Swpaul        }
52138363Swpaul        break;
52238363Swpaul
52338363Swpaul    default:
52438363Swpaul        return;
52538363Swpaul    }
52638363Swpaul
52738363Swpaul    /* Replace the existing reference object */
52838363Swpaul
52938363Swpaul    if (ObjDesc)
53038363Swpaul    {
53138363Swpaul        AcpiUtAddReference (ObjDesc);
53238363Swpaul        AcpiUtRemoveReference (Info->ReturnObject);
53338363Swpaul        Info->ReturnObject = ObjDesc;
53438363Swpaul    }
53538363Swpaul
53638363Swpaul    return;
53738363Swpaul}
53838363Swpaul
53938363Swpaul
54038363Swpaul/*******************************************************************************
54138363Swpaul *
54238363Swpaul * FUNCTION:    AcpiWalkNamespace
54338363Swpaul *
54438363Swpaul * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
54538363Swpaul *              StartObject         - Handle in namespace where search begins
54638363Swpaul *              MaxDepth            - Depth to which search is to reach
54738363Swpaul *              UserFunction        - Called when an object of "Type" is found
54838363Swpaul *              Context             - Passed to user function
54938363Swpaul *              ReturnValue         - Location where return value of
55038363Swpaul *                                    UserFunction is put if terminated early
55138363Swpaul *
55238363Swpaul * RETURNS      Return value from the UserFunction if terminated early.
55338363Swpaul *              Otherwise, returns NULL.
55438363Swpaul *
55538363Swpaul * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
55638363Swpaul *              starting (and ending) at the object specified by StartHandle.
55738363Swpaul *              The UserFunction is called whenever an object that matches
55838363Swpaul *              the type parameter is found.  If the user function returns
55938363Swpaul *              a non-zero value, the search is terminated immediately and this
56038363Swpaul *              value is returned to the caller.
56138363Swpaul *
56238363Swpaul *              The point of this procedure is to provide a generic namespace
56338363Swpaul *              walk routine that can be called from multiple places to
56438363Swpaul *              provide multiple services;  the User Function can be tailored
56538363Swpaul *              to each task, whether it is a print function, a compare
56638363Swpaul *              function, etc.
56738363Swpaul *
56838363Swpaul ******************************************************************************/
56938363Swpaul
57038363SwpaulACPI_STATUS
57138363SwpaulAcpiWalkNamespace (
57238363Swpaul    ACPI_OBJECT_TYPE        Type,
57338363Swpaul    ACPI_HANDLE             StartObject,
57438363Swpaul    UINT32                  MaxDepth,
57538363Swpaul    ACPI_WALK_CALLBACK      UserFunction,
57638363Swpaul    void                    *Context,
57738363Swpaul    void                    **ReturnValue)
57838363Swpaul{
57938363Swpaul    ACPI_STATUS             Status;
58038363Swpaul
58138363Swpaul
58238363Swpaul    ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
58338363Swpaul
58438363Swpaul
58538363Swpaul    /* Parameter validation */
58638363Swpaul
58738363Swpaul    if ((Type > ACPI_TYPE_LOCAL_MAX) ||
58838363Swpaul        (!MaxDepth)                  ||
58938363Swpaul        (!UserFunction))
59038363Swpaul    {
59138363Swpaul        return_ACPI_STATUS (AE_BAD_PARAMETER);
59238363Swpaul    }
59338363Swpaul
59438363Swpaul    /*
59538363Swpaul     * Need to acquire the namespace reader lock to prevent interference
59638363Swpaul     * with any concurrent table unloads (which causes the deletion of
59738363Swpaul     * namespace objects). We cannot allow the deletion of a namespace node
59838363Swpaul     * while the user function is using it. The exception to this are the
59938363Swpaul     * nodes created and deleted during control method execution -- these
60038363Swpaul     * nodes are marked as temporary nodes and are ignored by the namespace
60138363Swpaul     * walk. Thus, control methods can be executed while holding the
60238363Swpaul     * namespace deletion lock (and the user function can execute control
60338363Swpaul     * methods.)
60438363Swpaul     */
60538363Swpaul    Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
60638363Swpaul    if (ACPI_FAILURE (Status))
60738363Swpaul    {
60838363Swpaul        return (Status);
60938363Swpaul    }
61038363Swpaul
61138363Swpaul    /*
61238363Swpaul     * Lock the namespace around the walk. The namespace will be
61338363Swpaul     * unlocked/locked around each call to the user function - since the user
61438363Swpaul     * function must be allowed to make ACPICA calls itself (for example, it
61538363Swpaul     * will typically execute control methods during device enumeration.)
61638363Swpaul     */
61738363Swpaul    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
61838363Swpaul    if (ACPI_FAILURE (Status))
61938363Swpaul    {
62038363Swpaul        goto UnlockAndExit;
62138363Swpaul    }
62238363Swpaul
62338363Swpaul    Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
62438363Swpaul                ACPI_NS_WALK_UNLOCK, UserFunction, Context, ReturnValue);
62538363Swpaul
62638363Swpaul    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
62738363Swpaul
62838363SwpaulUnlockAndExit:
62938363Swpaul    (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
63038363Swpaul    return_ACPI_STATUS (Status);
63138363Swpaul}
63238363Swpaul
63338363SwpaulACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
63438363Swpaul
63538363Swpaul
63638363Swpaul/*******************************************************************************
63738363Swpaul *
63838363Swpaul * FUNCTION:    AcpiNsGetDeviceCallback
63938363Swpaul *
64038363Swpaul * PARAMETERS:  Callback from AcpiGetDevice
64138363Swpaul *
64238363Swpaul * RETURN:      Status
64338363Swpaul *
64438363Swpaul * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
64538363Swpaul *              present devices, or if they specified a HID, it filters based
64638363Swpaul *              on that.
64738363Swpaul *
64838363Swpaul ******************************************************************************/
64938363Swpaul
65038363Swpaulstatic ACPI_STATUS
65138363SwpaulAcpiNsGetDeviceCallback (
65238363Swpaul    ACPI_HANDLE             ObjHandle,
65338363Swpaul    UINT32                  NestingLevel,
65438363Swpaul    void                    *Context,
65538363Swpaul    void                    **ReturnValue)
65638363Swpaul{
65738363Swpaul    ACPI_GET_DEVICES_INFO   *Info = Context;
65838363Swpaul    ACPI_STATUS             Status;
65938363Swpaul    ACPI_NAMESPACE_NODE     *Node;
66038363Swpaul    UINT32                  Flags;
66138363Swpaul    ACPI_DEVICE_ID          Hid;
66238363Swpaul    ACPI_COMPATIBLE_ID_LIST *Cid;
66338363Swpaul    UINT32                  i;
66438363Swpaul    BOOLEAN                 Found;
66538363Swpaul
66638363Swpaul
66738363Swpaul    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
66838363Swpaul    if (ACPI_FAILURE (Status))
66938363Swpaul    {
67038363Swpaul        return (Status);
67138363Swpaul    }
67238363Swpaul
67338363Swpaul    Node = AcpiNsMapHandleToNode (ObjHandle);
67438363Swpaul    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
67538363Swpaul    if (ACPI_FAILURE (Status))
67638363Swpaul    {
67738363Swpaul        return (Status);
67838363Swpaul    }
67938363Swpaul
68038363Swpaul    if (!Node)
68138363Swpaul    {
68238363Swpaul        return (AE_BAD_PARAMETER);
68338363Swpaul    }
68438363Swpaul
68538363Swpaul    /* Run _STA to determine if device is present */
68638363Swpaul
68738363Swpaul    Status = AcpiUtExecute_STA (Node, &Flags);
68838363Swpaul    if (ACPI_FAILURE (Status))
68938363Swpaul    {
69038363Swpaul        return (AE_CTRL_DEPTH);
69138363Swpaul    }
69238363Swpaul
69338363Swpaul    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
69438363Swpaul        !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
69538363Swpaul    {
69638363Swpaul        /*
69738363Swpaul         * Don't examine the children of the device only when the
69838363Swpaul         * device is neither present nor functional. See ACPI spec,
69938363Swpaul         * description of _STA for more information.
70038363Swpaul         */
70138363Swpaul        return (AE_CTRL_DEPTH);
70238363Swpaul    }
70338363Swpaul
70438363Swpaul    /* Filter based on device HID & CID */
70538363Swpaul
70638363Swpaul    if (Info->Hid != NULL)
70738363Swpaul    {
70838363Swpaul        Status = AcpiUtExecute_HID (Node, &Hid);
70938363Swpaul        if (Status == AE_NOT_FOUND)
71038363Swpaul        {
71138363Swpaul            return (AE_OK);
71238363Swpaul        }
71338363Swpaul        else if (ACPI_FAILURE (Status))
71438363Swpaul        {
71538363Swpaul            return (AE_CTRL_DEPTH);
71638363Swpaul        }
71738363Swpaul
71838363Swpaul        if (ACPI_STRNCMP (Hid.Value, Info->Hid, sizeof (Hid.Value)) != 0)
71938363Swpaul        {
72038363Swpaul            /*
72138363Swpaul             * HID does not match, attempt match within the
72238363Swpaul             * list of Compatible IDs (CIDs)
72338363Swpaul             */
72438363Swpaul            Status = AcpiUtExecute_CID (Node, &Cid);
72538363Swpaul            if (Status == AE_NOT_FOUND)
72638363Swpaul            {
72738363Swpaul                return (AE_OK);
72838363Swpaul            }
72938363Swpaul            else if (ACPI_FAILURE (Status))
73038363Swpaul            {
73138363Swpaul                return (AE_CTRL_DEPTH);
73238363Swpaul            }
73338363Swpaul
73438363Swpaul            /* Walk the CID list */
73538363Swpaul
73638363Swpaul            Found = FALSE;
73738363Swpaul            for (i = 0; i < Cid->Count; i++)
73838363Swpaul            {
73938363Swpaul                if (ACPI_STRNCMP (Cid->Id[i].Value, Info->Hid,
74038363Swpaul                        sizeof (ACPI_COMPATIBLE_ID)) == 0)
74138363Swpaul                {
74238363Swpaul                    /* Found a matching CID */
74338363Swpaul
74438363Swpaul                    Found = TRUE;
74538363Swpaul                    break;
74638363Swpaul                }
74738363Swpaul            }
74838363Swpaul
74938363Swpaul            ACPI_FREE (Cid);
75038363Swpaul            if (!Found)
75138363Swpaul            {
75238363Swpaul                return (AE_OK);
75338363Swpaul            }
75438363Swpaul        }
75538363Swpaul    }
75638363Swpaul
75738363Swpaul    /* We have a valid device, invoke the user function */
75838363Swpaul
75938363Swpaul    Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
76038363Swpaul                ReturnValue);
76138363Swpaul    return (Status);
76238363Swpaul}
76338363Swpaul
76438363Swpaul
76538363Swpaul/*******************************************************************************
76638363Swpaul *
76738363Swpaul * FUNCTION:    AcpiGetDevices
76838363Swpaul *
76938363Swpaul * PARAMETERS:  HID                 - HID to search for. Can be NULL.
77038363Swpaul *              UserFunction        - Called when a matching object is found
77138363Swpaul *              Context             - Passed to user function
77238363Swpaul *              ReturnValue         - Location where return value of
77338363Swpaul *                                    UserFunction is put if terminated early
77438363Swpaul *
77538363Swpaul * RETURNS      Return value from the UserFunction if terminated early.
77638363Swpaul *              Otherwise, returns NULL.
77738363Swpaul *
77838363Swpaul * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
77938363Swpaul *              starting (and ending) at the object specified by StartHandle.
78038363Swpaul *              The UserFunction is called whenever an object of type
78138363Swpaul *              Device is found.  If the user function returns
78238363Swpaul *              a non-zero value, the search is terminated immediately and this
78338363Swpaul *              value is returned to the caller.
78438363Swpaul *
78538363Swpaul *              This is a wrapper for WalkNamespace, but the callback performs
78638363Swpaul *              additional filtering. Please see AcpiNsGetDeviceCallback.
78738363Swpaul *
78838363Swpaul ******************************************************************************/
78938363Swpaul
79038363SwpaulACPI_STATUS
79138363SwpaulAcpiGetDevices (
79238363Swpaul    char                    *HID,
79338363Swpaul    ACPI_WALK_CALLBACK      UserFunction,
79438363Swpaul    void                    *Context,
79538363Swpaul    void                    **ReturnValue)
79638363Swpaul{
79738363Swpaul    ACPI_STATUS             Status;
79838363Swpaul    ACPI_GET_DEVICES_INFO   Info;
79938363Swpaul
80038363Swpaul
80138363Swpaul    ACPI_FUNCTION_TRACE (AcpiGetDevices);
80238363Swpaul
80338363Swpaul
80438363Swpaul    /* Parameter validation */
80538363Swpaul
80638363Swpaul    if (!UserFunction)
80738363Swpaul    {
80838363Swpaul        return_ACPI_STATUS (AE_BAD_PARAMETER);
80938363Swpaul    }
81038363Swpaul
81138363Swpaul    /*
81238363Swpaul     * We're going to call their callback from OUR callback, so we need
81338363Swpaul     * to know what it is, and their context parameter.
81438363Swpaul     */
81538363Swpaul    Info.Hid          = HID;
81638363Swpaul    Info.Context      = Context;
81738363Swpaul    Info.UserFunction = UserFunction;
81838363Swpaul
81938363Swpaul    /*
82038363Swpaul     * Lock the namespace around the walk.
82138363Swpaul     * The namespace will be unlocked/locked around each call
82238363Swpaul     * to the user function - since this function
823     * must be allowed to make Acpi calls itself.
824     */
825    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
826    if (ACPI_FAILURE (Status))
827    {
828        return_ACPI_STATUS (Status);
829    }
830
831    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
832                ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
833                AcpiNsGetDeviceCallback, &Info, ReturnValue);
834
835    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
836    return_ACPI_STATUS (Status);
837}
838
839ACPI_EXPORT_SYMBOL (AcpiGetDevices)
840
841
842/*******************************************************************************
843 *
844 * FUNCTION:    AcpiAttachData
845 *
846 * PARAMETERS:  ObjHandle           - Namespace node
847 *              Handler             - Handler for this attachment
848 *              Data                - Pointer to data to be attached
849 *
850 * RETURN:      Status
851 *
852 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
853 *
854 ******************************************************************************/
855
856ACPI_STATUS
857AcpiAttachData (
858    ACPI_HANDLE             ObjHandle,
859    ACPI_OBJECT_HANDLER     Handler,
860    void                    *Data)
861{
862    ACPI_NAMESPACE_NODE     *Node;
863    ACPI_STATUS             Status;
864
865
866    /* Parameter validation */
867
868    if (!ObjHandle  ||
869        !Handler    ||
870        !Data)
871    {
872        return (AE_BAD_PARAMETER);
873    }
874
875    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
876    if (ACPI_FAILURE (Status))
877    {
878        return (Status);
879    }
880
881    /* Convert and validate the handle */
882
883    Node = AcpiNsMapHandleToNode (ObjHandle);
884    if (!Node)
885    {
886        Status = AE_BAD_PARAMETER;
887        goto UnlockAndExit;
888    }
889
890    Status = AcpiNsAttachData (Node, Handler, Data);
891
892UnlockAndExit:
893    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
894    return (Status);
895}
896
897ACPI_EXPORT_SYMBOL (AcpiAttachData)
898
899
900/*******************************************************************************
901 *
902 * FUNCTION:    AcpiDetachData
903 *
904 * PARAMETERS:  ObjHandle           - Namespace node handle
905 *              Handler             - Handler used in call to AcpiAttachData
906 *
907 * RETURN:      Status
908 *
909 * DESCRIPTION: Remove data that was previously attached to a node.
910 *
911 ******************************************************************************/
912
913ACPI_STATUS
914AcpiDetachData (
915    ACPI_HANDLE             ObjHandle,
916    ACPI_OBJECT_HANDLER     Handler)
917{
918    ACPI_NAMESPACE_NODE     *Node;
919    ACPI_STATUS             Status;
920
921
922    /* Parameter validation */
923
924    if (!ObjHandle  ||
925        !Handler)
926    {
927        return (AE_BAD_PARAMETER);
928    }
929
930    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
931    if (ACPI_FAILURE (Status))
932    {
933        return (Status);
934    }
935
936    /* Convert and validate the handle */
937
938    Node = AcpiNsMapHandleToNode (ObjHandle);
939    if (!Node)
940    {
941        Status = AE_BAD_PARAMETER;
942        goto UnlockAndExit;
943    }
944
945    Status = AcpiNsDetachData (Node, Handler);
946
947UnlockAndExit:
948    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
949    return (Status);
950}
951
952ACPI_EXPORT_SYMBOL (AcpiDetachData)
953
954
955/*******************************************************************************
956 *
957 * FUNCTION:    AcpiGetData
958 *
959 * PARAMETERS:  ObjHandle           - Namespace node
960 *              Handler             - Handler used in call to AttachData
961 *              Data                - Where the data is returned
962 *
963 * RETURN:      Status
964 *
965 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
966 *
967 ******************************************************************************/
968
969ACPI_STATUS
970AcpiGetData (
971    ACPI_HANDLE             ObjHandle,
972    ACPI_OBJECT_HANDLER     Handler,
973    void                    **Data)
974{
975    ACPI_NAMESPACE_NODE     *Node;
976    ACPI_STATUS             Status;
977
978
979    /* Parameter validation */
980
981    if (!ObjHandle  ||
982        !Handler    ||
983        !Data)
984    {
985        return (AE_BAD_PARAMETER);
986    }
987
988    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
989    if (ACPI_FAILURE (Status))
990    {
991        return (Status);
992    }
993
994    /* Convert and validate the handle */
995
996    Node = AcpiNsMapHandleToNode (ObjHandle);
997    if (!Node)
998    {
999        Status = AE_BAD_PARAMETER;
1000        goto UnlockAndExit;
1001    }
1002
1003    Status = AcpiNsGetAttachedData (Node, Handler, Data);
1004
1005UnlockAndExit:
1006    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1007    return (Status);
1008}
1009
1010ACPI_EXPORT_SYMBOL (AcpiGetData)
1011
1012
1013