nswalk.c revision 193251
138363Swpaul/******************************************************************************
238363Swpaul *
338363Swpaul * Module Name: nswalk - Functions for walking the ACPI namespace
438363Swpaul *              $Revision: 1.46 $
538363Swpaul *
638363Swpaul *****************************************************************************/
738363Swpaul
838363Swpaul/******************************************************************************
938363Swpaul *
1038363Swpaul * 1. Copyright Notice
1138363Swpaul *
1238363Swpaul * Some or all of this work - Copyright (c) 1999 - 2007, 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,
3250477Speter * 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
3967233Simp * 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
8477548Swpaul * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85117375Swpaul * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86117375Swpaul * 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
9751441Swpaul * 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
10151441Swpaul * 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 __NSWALK_C__
11938363Swpaul
12038363Swpaul#include "acpi.h"
12138363Swpaul#include "acnamesp.h"
12238363Swpaul
12338363Swpaul
12438363Swpaul#define _COMPONENT          ACPI_NAMESPACE
12538363Swpaul        ACPI_MODULE_NAME    ("nswalk")
12638363Swpaul
12738363Swpaul
12838363Swpaul/*******************************************************************************
12938363Swpaul *
13038363Swpaul * FUNCTION:    AcpiNsGetNextNode
13138363Swpaul *
13238363Swpaul * PARAMETERS:  Type                - Type of node to be searched for
13338363Swpaul *              ParentNode          - Parent node whose children we are
13438363Swpaul *                                    getting
13538363Swpaul *              ChildNode           - Previous child that was found.
13638363Swpaul *                                    The NEXT child will be returned
13738363Swpaul *
13838363Swpaul * RETURN:      ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if
13938363Swpaul *                                    none is found.
14038363Swpaul *
14138363Swpaul * DESCRIPTION: Return the next peer node within the namespace.  If Handle
14238363Swpaul *              is valid, Scope is ignored.  Otherwise, the first node
14338363Swpaul *              within Scope is returned.
14438363Swpaul *
14538363Swpaul ******************************************************************************/
14638363Swpaul
14738363SwpaulACPI_NAMESPACE_NODE *
14838363SwpaulAcpiNsGetNextNode (
14938363Swpaul    ACPI_OBJECT_TYPE        Type,
15038363Swpaul    ACPI_NAMESPACE_NODE     *ParentNode,
15138363Swpaul    ACPI_NAMESPACE_NODE     *ChildNode)
15238363Swpaul{
15338363Swpaul    ACPI_NAMESPACE_NODE     *NextNode = NULL;
15438363Swpaul
15538363Swpaul
15638363Swpaul    ACPI_FUNCTION_ENTRY ();
15738363Swpaul
15838363Swpaul
15938363Swpaul    if (!ChildNode)
16038363Swpaul    {
16138363Swpaul        /* It's really the parent's _scope_ that we want */
16238363Swpaul
16338363Swpaul        NextNode = ParentNode->Child;
16438363Swpaul    }
16538363Swpaul
16638363Swpaul    else
16738363Swpaul    {
16838363Swpaul        /* Start search at the NEXT node */
16938363Swpaul
17038363Swpaul        NextNode = AcpiNsGetNextValidNode (ChildNode);
17138363Swpaul    }
17238363Swpaul
17338363Swpaul    /* If any type is OK, we are done */
17438363Swpaul
17538363Swpaul    if (Type == ACPI_TYPE_ANY)
17638363Swpaul    {
17738363Swpaul        /* NextNode is NULL if we are at the end-of-list */
17838526Swpaul
17938526Swpaul        return (NextNode);
18038526Swpaul    }
18188079Ssilby
18238526Swpaul    /* Must search for the node -- but within this scope only */
18338526Swpaul
18438526Swpaul    while (NextNode)
18538363Swpaul    {
18638363Swpaul        /* If type matches, we are done */
18738363Swpaul
18838363Swpaul        if (NextNode->Type == Type)
18938363Swpaul        {
19038363Swpaul            return (NextNode);
19138363Swpaul        }
19238363Swpaul
19338363Swpaul        /* Otherwise, move on to the next node */
19438363Swpaul
19538363Swpaul        NextNode = AcpiNsGetNextValidNode (NextNode);
19638363Swpaul    }
19738363Swpaul
19838363Swpaul    /* Not found */
19938363Swpaul
20038363Swpaul    return (NULL);
20138363Swpaul}
20238363Swpaul
20338363Swpaul
20438363Swpaul/*******************************************************************************
20538363Swpaul *
20638363Swpaul * FUNCTION:    AcpiNsWalkNamespace
20738363Swpaul *
20838363Swpaul * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
20938363Swpaul *              StartNode           - Handle in namespace where search begins
21038363Swpaul *              MaxDepth            - Depth to which search is to reach
21138363Swpaul *              Flags               - Whether to unlock the NS before invoking
21238363Swpaul *                                    the callback routine
21338363Swpaul *              UserFunction        - Called when an object of "Type" is found
21438363Swpaul *              Context             - Passed to user function
21538363Swpaul *              ReturnValue         - from the UserFunction if terminated early.
21638363Swpaul *                                    Otherwise, returns NULL.
21738363Swpaul * RETURNS:     Status
21838363Swpaul *
21938363Swpaul * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
22038363Swpaul *              starting (and ending) at the node specified by StartHandle.
22138363Swpaul *              The UserFunction is called whenever a node that matches
22238363Swpaul *              the type parameter is found.  If the user function returns
22338363Swpaul *              a non-zero value, the search is terminated immediately and this
22438363Swpaul *              value is returned to the caller.
22538363Swpaul *
22638363Swpaul *              The point of this procedure is to provide a generic namespace
22738363Swpaul *              walk routine that can be called from multiple places to
22838363Swpaul *              provide multiple services;  the User Function can be tailored
22938363Swpaul *              to each task, whether it is a print function, a compare
23038363Swpaul *              function, etc.
23138363Swpaul *
23238363Swpaul ******************************************************************************/
23338363Swpaul
23438363SwpaulACPI_STATUS
23538363SwpaulAcpiNsWalkNamespace (
23638363Swpaul    ACPI_OBJECT_TYPE        Type,
23738363Swpaul    ACPI_HANDLE             StartNode,
23838363Swpaul    UINT32                  MaxDepth,
23938363Swpaul    UINT32                  Flags,
24038363Swpaul    ACPI_WALK_CALLBACK      UserFunction,
24138363Swpaul    void                    *Context,
24238363Swpaul    void                    **ReturnValue)
24338363Swpaul{
24438363Swpaul    ACPI_STATUS             Status;
24538363Swpaul    ACPI_STATUS             MutexStatus;
24638363Swpaul    ACPI_NAMESPACE_NODE     *ChildNode;
24738363Swpaul    ACPI_NAMESPACE_NODE     *ParentNode;
24838363Swpaul    ACPI_OBJECT_TYPE        ChildType;
24938363Swpaul    UINT32                  Level;
25038363Swpaul
25138363Swpaul
25238363Swpaul    ACPI_FUNCTION_TRACE (NsWalkNamespace);
25367233Simp
25467233Simp
25567233Simp    /* Special case for the namespace Root Node */
25638363Swpaul
25738363Swpaul    if (StartNode == ACPI_ROOT_OBJECT)
25838363Swpaul    {
25938363Swpaul        StartNode = AcpiGbl_RootNode;
26077548Swpaul    }
26138363Swpaul
26238363Swpaul    /* Null child means "get first node" */
26338363Swpaul
26438363Swpaul    ParentNode  = StartNode;
26538363Swpaul    ChildNode   = NULL;
26638363Swpaul    ChildType   = ACPI_TYPE_ANY;
26738363Swpaul    Level       = 1;
26838363Swpaul
26938363Swpaul    /*
27038363Swpaul     * Traverse the tree of nodes until we bubble back up to where we
27138363Swpaul     * started. When Level is zero, the loop is done because we have
27238363Swpaul     * bubbled up to (and passed) the original parent handle (StartEntry)
27338363Swpaul     */
27438363Swpaul    while (Level > 0)
27538363Swpaul    {
27638363Swpaul        /* Get the next node in this scope.  Null if not found */
27738363Swpaul
27838363Swpaul        Status = AE_OK;
27938363Swpaul        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode);
28038363Swpaul        if (ChildNode)
28138363Swpaul        {
28238363Swpaul            /* Found next child, get the type if we are not searching for ANY */
28338363Swpaul
28438363Swpaul            if (Type != ACPI_TYPE_ANY)
28538363Swpaul            {
28638363Swpaul                ChildType = ChildNode->Type;
28738363Swpaul            }
28838363Swpaul
28938363Swpaul            /*
29038363Swpaul             * Ignore all temporary namespace nodes (created during control
29138363Swpaul             * method execution) unless told otherwise. These temporary nodes
29238363Swpaul             * can cause a race condition because they can be deleted during the
29338363Swpaul             * execution of the user function (if the namespace is unlocked before
29438363Swpaul             * invocation of the user function.) Only the debugger namespace dump
29538363Swpaul             * will examine the temporary nodes.
29638363Swpaul             */
29738363Swpaul            if ((ChildNode->Flags & ANOBJ_TEMPORARY) &&
29838363Swpaul                !(Flags & ACPI_NS_WALK_TEMP_NODES))
29938363Swpaul            {
30038363Swpaul                Status = AE_CTRL_DEPTH;
30138363Swpaul            }
30238363Swpaul
30338363Swpaul            /* Type must match requested type */
30438363Swpaul
30538363Swpaul            else if (ChildType == Type)
30638363Swpaul            {
30738363Swpaul                /*
30838363Swpaul                 * Found a matching node, invoke the user callback function.
30938363Swpaul                 * Unlock the namespace if flag is set.
31038363Swpaul                 */
31138363Swpaul                if (Flags & ACPI_NS_WALK_UNLOCK)
31238363Swpaul                {
31338363Swpaul                    MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
31438363Swpaul                    if (ACPI_FAILURE (MutexStatus))
31538363Swpaul                    {
31638363Swpaul                        return_ACPI_STATUS (MutexStatus);
31738363Swpaul                    }
31838363Swpaul                }
31938363Swpaul
32038363Swpaul                Status = UserFunction (ChildNode, Level, Context, ReturnValue);
32138363Swpaul
32238363Swpaul                if (Flags & ACPI_NS_WALK_UNLOCK)
32338363Swpaul                {
32438363Swpaul                    MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
32538363Swpaul                    if (ACPI_FAILURE (MutexStatus))
32638363Swpaul                    {
32738363Swpaul                        return_ACPI_STATUS (MutexStatus);
32838363Swpaul                    }
32938363Swpaul                }
33038363Swpaul
33138363Swpaul                switch (Status)
33238363Swpaul                {
33338363Swpaul                case AE_OK:
33438363Swpaul                case AE_CTRL_DEPTH:
33538363Swpaul
33638363Swpaul                    /* Just keep going */
33738363Swpaul                    break;
33838363Swpaul
33938363Swpaul                case AE_CTRL_TERMINATE:
34038363Swpaul
34138363Swpaul                    /* Exit now, with OK status */
34238363Swpaul
34338363Swpaul                    return_ACPI_STATUS (AE_OK);
34438363Swpaul
34538363Swpaul                default:
34638363Swpaul
34738363Swpaul                    /* All others are valid exceptions */
34838363Swpaul
34938363Swpaul                    return_ACPI_STATUS (Status);
35038363Swpaul                }
35138363Swpaul            }
35238363Swpaul
35338363Swpaul            /*
35438363Swpaul             * Depth first search: Attempt to go down another level in the
35538363Swpaul             * namespace if we are allowed to.  Don't go any further if we have
35638363Swpaul             * reached the caller specified maximum depth or if the user
35738363Swpaul             * function has specified that the maximum depth has been reached.
35838363Swpaul             */
35938363Swpaul            if ((Level < MaxDepth) && (Status != AE_CTRL_DEPTH))
36038363Swpaul            {
36138363Swpaul                if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, NULL))
36238363Swpaul                {
36338363Swpaul                    /* There is at least one child of this node, visit it */
36438363Swpaul
36538363Swpaul                    Level++;
36638363Swpaul                    ParentNode = ChildNode;
36738363Swpaul                    ChildNode = NULL;
36838363Swpaul                }
36938363Swpaul            }
37038363Swpaul        }
37138363Swpaul        else
37240588Swpaul        {
37338363Swpaul            /*
37438363Swpaul             * No more children of this node (AcpiNsGetNextNode failed), go
37538363Swpaul             * back upwards in the namespace tree to the node's parent.
37638363Swpaul             */
37738363Swpaul            Level--;
37838363Swpaul            ChildNode = ParentNode;
37938363Swpaul            ParentNode = AcpiNsGetParentNode (ParentNode);
38038363Swpaul        }
38138363Swpaul    }
38238363Swpaul
38338363Swpaul    /* Complete walk, not terminated by user function */
38438363Swpaul
38538363Swpaul    return_ACPI_STATUS (AE_OK);
38638363Swpaul}
38738363Swpaul
38838363Swpaul
38938363Swpaul