nswalk.c revision 117521
1139776Simp/******************************************************************************
2130678Sphk *
364880Sphk * Module Name: nswalk - Functions for walking the ACPI namespace
464880Sphk *              $Revision: 35 $
564880Sphk *
664880Sphk *****************************************************************************/
764880Sphk
864880Sphk/******************************************************************************
964880Sphk *
1064880Sphk * 1. Copyright Notice
1164880Sphk *
1264880Sphk * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
1364880Sphk * All rights reserved.
1464880Sphk *
1564880Sphk * 2. License
1664880Sphk *
1764880Sphk * 2.1. This is your license from Intel Corp. under its intellectual property
1864880Sphk * rights.  You may have additional license terms from the party that provided
1964880Sphk * you this software, covering your right to use that party's intellectual
2064880Sphk * property rights.
2164880Sphk *
2264880Sphk * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2364880Sphk * copy of the source code appearing in this file ("Covered Code") an
2464880Sphk * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2564880Sphk * base code distributed originally by Intel ("Original Intel Code") to copy,
2664880Sphk * make derivatives, distribute, use and display any portion of the Covered
2764880Sphk * Code in any form, with the right to sublicense such rights; and
2864880Sphk *
2964880Sphk * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3064880Sphk * license (with the right to sublicense), under only those claims of Intel
3164880Sphk * patents that are infringed by the Original Intel Code, to make, use, sell,
3264880Sphk * offer to sell, and import the Covered Code and derivative works thereof
3376166Smarkm * solely to the minimum extent necessary to exercise the above copyright
3464880Sphk * license, and in no event shall the patent license extend to any additions
3576166Smarkm * to or modifications of the Original Intel Code.  No other license or right
36150342Sphk * is granted directly or by implication, estoppel or otherwise;
3776166Smarkm *
3864880Sphk * The above copyright and patent license is granted only if the following
3976166Smarkm * conditions are met:
40150342Sphk *
4165515Sphk * 3. Conditions
4276166Smarkm *
4364880Sphk * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44150342Sphk * Redistribution of source code of any substantial portion of the Covered
4565515Sphk * Code or modification with rights to further distribute source must include
4664880Sphk * the above Copyright Notice, the above License, this list of Conditions,
47149144Sphk * and the following Disclaimer and Export Compliance provision.  In addition,
4864880Sphk * Licensee must cause all Covered Code to which Licensee contributes to
49163606Srwatson * contain a file documenting the changes Licensee made to create that Covered
50163606Srwatson * Code and the date of any change.  Licensee must include in that file the
51150342Sphk * documentation of any changes made by any predecessor Licensee.  Licensee
52150342Sphk * must include a prominent statement that the modification is derived,
53150342Sphk * directly or indirectly, from Original Intel Code.
54150342Sphk *
55163481Skib * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5665515Sphk * Redistribution of source code of any substantial portion of the Covered
57150342Sphk * Code or modification without rights to further distribute source must
5869767Sphk * include the following Disclaimer and Export Compliance provision in the
59150342Sphk * documentation and/or other materials provided with distribution.  In
60150342Sphk * addition, Licensee may not authorize further sublicense of source of any
61150342Sphk * portion of the Covered Code, and must include terms to the effect that the
62150342Sphk * license from Licensee to its licensee is limited to the intellectual
63150342Sphk * property embodied in the software Licensee provides to its licensee, and
64141633Sphk * not to intellectual property embodied in modifications its licensee may
65150342Sphk * make.
66150342Sphk *
6765515Sphk * 3.3. Redistribution of Executable. Redistribution in executable form of any
6865515Sphk * substantial portion of the Covered Code or modification must reproduce the
6965515Sphk * above Copyright Notice, and the following Disclaimer and Export Compliance
70150147Sphk * provision in the documentation and/or other materials provided with the
71150147Sphk * distribution.
72150342Sphk *
73150147Sphk * 3.4. Intel retains all right, title, and interest in and to the Original
74149146Sphk * Intel Code.
75203292Sed *
76203292Sed * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77149146Sphk * Intel shall be used in advertising or otherwise to promote the sale, use or
78149146Sphk * other dealings in products derived from or relating to the Covered Code
79149146Sphk * without prior written authorization from Intel.
80149146Sphk *
81149146Sphk * 4. Disclaimer and Export Compliance
82149146Sphk *
83150342Sphk * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84203292Sed * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85149146Sphk * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86149146Sphk * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87149146Sphk * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88149146Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89149146Sphk * PARTICULAR PURPOSE.
90203292Sed *
91203292Sed * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92150342Sphk * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93150342Sphk * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94203292Sed * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95203292Sed * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96203292Sed * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97150342Sphk * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98203292Sed * LIMITED REMEDY.
99150342Sphk *
100203292Sed * 4.3. Licensee shall not export, either directly or indirectly, any of this
101203292Sed * software or system incorporating such software without first obtaining any
102203292Sed * required license or other approval from the U. S. Department of Commerce or
103203292Sed * any other agency or department of the United States Government.  In the
104149146Sphk * event Licensee exports any such software from the United States or
105149146Sphk * re-exports any such software from a foreign destination, Licensee shall
106149146Sphk * ensure that the distribution and export/re-export of the software is in
107187864Sed * compliance with all laws, regulations, orders, or other restrictions of the
108187864Sed * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109187864Sed * any of its subsidiaries will export/re-export any technical data, process,
110149146Sphk * software, or service, directly or indirectly, to any country for which the
111149146Sphk * United States government or any agency thereof requires an export license,
112273736Shselasky * other governmental approval, or letter of assurance, without first obtaining
113149146Sphk * such license, approval or letter.
114150342Sphk *
115273736Shselasky *****************************************************************************/
11665515Sphk
117150342Sphk
118207729Skib#define __NSWALK_C__
11965515Sphk
120150342Sphk#include "acpi.h"
121150342Sphk#include "acnamesp.h"
122183230Sed
12365515Sphk
124243039Skib#define _COMPONENT          ACPI_NAMESPACE
125207729Skib        ACPI_MODULE_NAME    ("nswalk")
126207729Skib
127207729Skib
12865515Sphk/*******************************************************************************
129150342Sphk *
130150342Sphk * FUNCTION:    AcpiNsGetNextNode
131150342Sphk *
132207729Skib * PARAMETERS:  Type                - Type of node to be searched for
13365515Sphk *              ParentNode          - Parent node whose children we are
134150342Sphk *                                     getting
13565515Sphk *              ChildNode           - Previous child that was found.
136150342Sphk *                                    The NEXT child will be returned
137183230Sed *
138183230Sed * RETURN:      ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if
139207729Skib *                                    none is found.
140183230Sed *
141150342Sphk * DESCRIPTION: Return the next peer node within the namespace.  If Handle
14265515Sphk *              is valid, Scope is ignored.  Otherwise, the first node
14365515Sphk *              within Scope is returned.
144213221Sjh *
145213221Sjh ******************************************************************************/
146213221Sjh
147213221SjhACPI_NAMESPACE_NODE *
148213221SjhAcpiNsGetNextNode (
149213221Sjh    ACPI_OBJECT_TYPE        Type,
150213221Sjh    ACPI_NAMESPACE_NODE     *ParentNode,
151213221Sjh    ACPI_NAMESPACE_NODE     *ChildNode)
152213221Sjh{
153213221Sjh    ACPI_NAMESPACE_NODE     *NextNode = NULL;
154213221Sjh
155213221Sjh
156213221Sjh    ACPI_FUNCTION_ENTRY ();
157213221Sjh
158213221Sjh
159213221Sjh    if (!ChildNode)
160213221Sjh    {
161213221Sjh        /* It's really the parent's _scope_ that we want */
162213221Sjh
163213221Sjh        if (ParentNode->Child)
164213221Sjh        {
165150342Sphk            NextNode = ParentNode->Child;
166150342Sphk        }
16765515Sphk    }
168150342Sphk
16965515Sphk    else
170179828Skib    {
171150342Sphk        /* Start search at the NEXT node */
172150342Sphk
173226041Skib        NextNode = AcpiNsGetNextValidNode (ChildNode);
174150342Sphk    }
175150342Sphk
176150342Sphk    /* If any type is OK, we are done */
17765515Sphk
17865515Sphk    if (Type == ACPI_TYPE_ANY)
179150342Sphk    {
180211226Sjh        /* NextNode is NULL if we are at the end-of-list */
18165132Sphk
18265132Sphk        return (NextNode);
18365132Sphk    }
18465132Sphk
18565132Sphk    /* Must search for the node -- but within this scope only */
18665132Sphk
187211226Sjh    while (NextNode)
188211226Sjh    {
189277746Skib        /* If type matches, we are done */
190277746Skib
191277746Skib        if (NextNode->Type == Type)
192277746Skib        {
193277746Skib            return (NextNode);
194277746Skib        }
195277746Skib
196277746Skib        /* Otherwise, move on to the next node */
197277746Skib
198277746Skib        NextNode = AcpiNsGetNextValidNode (NextNode);
19965132Sphk    }
20065132Sphk
20165132Sphk    /* Not found */
20265132Sphk
203212826Sjh    return (NULL);
204212826Sjh}
20565132Sphk
20665132Sphk
20765132Sphk/*******************************************************************************
20865132Sphk *
20964880Sphk * FUNCTION:    AcpiNsWalkNamespace
21064880Sphk *
21164880Sphk * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
21264880Sphk *              StartNode           - Handle in namespace where search begins
21364880Sphk *              MaxDepth            - Depth to which search is to reach
21464880Sphk *              UnlockBeforeCallback- Whether to unlock the NS before invoking
21564880Sphk *                                    the callback routine
216150342Sphk *              UserFunction        - Called when an object of "Type" is found
217150342Sphk *              Context             - Passed to user function
21864880Sphk *              ReturnValue         - from the UserFunction if terminated early.
21964880Sphk *                                    Otherwise, returns NULL.
22064880Sphk * RETURNS:     Status
22171822Sphk *
22271822Sphk * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
22385979Sphk *              starting (and ending) at the node specified by StartHandle.
22465051Sphk *              The UserFunction is called whenever a node that matches
22565051Sphk *              the type parameter is found.  If the user function returns
226162398Skib *              a non-zero value, the search is terminated immediately and this
227101069Srwatson *              value is returned to the caller.
228172930Srwatson *
229101069Srwatson *              The point of this procedure is to provide a generic namespace
23064880Sphk *              walk routine that can be called from multiple places to
23164880Sphk *              provide multiple services;  the User Function can be tailored
23264880Sphk *              to each task, whether it is a print function, a compare
23365051Sphk *              function, etc.
234208951Sjh *
235208951Sjh ******************************************************************************/
236208951Sjh
237208951SjhACPI_STATUS
238208951SjhAcpiNsWalkNamespace (
239208951Sjh    ACPI_OBJECT_TYPE        Type,
240208951Sjh    ACPI_HANDLE             StartNode,
241208951Sjh    UINT32                  MaxDepth,
242208951Sjh    BOOLEAN                 UnlockBeforeCallback,
243208951Sjh    ACPI_WALK_CALLBACK      UserFunction,
244208951Sjh    void                    *Context,
245208951Sjh    void                    **ReturnValue)
246208951Sjh{
247208951Sjh    ACPI_STATUS             Status;
248208951Sjh    ACPI_STATUS             MutexStatus;
249208951Sjh    ACPI_NAMESPACE_NODE     *ChildNode;
250208951Sjh    ACPI_NAMESPACE_NODE     *ParentNode;
251208951Sjh    ACPI_OBJECT_TYPE        ChildType;
252208951Sjh    UINT32                  Level;
253208951Sjh
254150342Sphk
25564880Sphk    ACPI_FUNCTION_TRACE ("NsWalkNamespace");
25665051Sphk
25764880Sphk
25864880Sphk    /* Special case for the namespace Root Node */
259150342Sphk
26065051Sphk    if (StartNode == ACPI_ROOT_OBJECT)
26165051Sphk    {
26265051Sphk        StartNode = AcpiGbl_RootNode;
26385979Sphk    }
26465051Sphk
26565051Sphk    /* Null child means "get first node" */
266150342Sphk
267150342Sphk    ParentNode  = StartNode;
268150342Sphk    ChildNode   = 0;
269150342Sphk    ChildType   = ACPI_TYPE_ANY;
27065051Sphk    Level       = 1;
271211226Sjh
272211226Sjh    /*
273211226Sjh     * Traverse the tree of nodes until we bubble back up to where we
274211226Sjh     * started. When Level is zero, the loop is done because we have
275211226Sjh     * bubbled up to (and passed) the original parent handle (StartEntry)
276211226Sjh     */
27764880Sphk    while (Level > 0)
27864880Sphk    {
27965051Sphk        /* Get the next node in this scope.  Null if not found */
28065051Sphk
281150342Sphk        Status = AE_OK;
28265051Sphk        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode);
283211226Sjh        if (ChildNode)
28465051Sphk        {
28565051Sphk            /*
286150342Sphk             * Found node, Get the type if we are not
287150342Sphk             * searching for ANY
288150342Sphk             */
28965051Sphk            if (Type != ACPI_TYPE_ANY)
290150342Sphk            {
29165051Sphk                ChildType = ChildNode->Type;
292216461Sjh            }
293150342Sphk
294150342Sphk            if (ChildType == Type)
295216461Sjh            {
296150342Sphk                /*
29765051Sphk                 * Found a matching node, invoke the user
298150342Sphk                 * callback function
299172930Srwatson                 */
300150342Sphk                if (UnlockBeforeCallback)
30164880Sphk                {
30264880Sphk                    MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
30364880Sphk                    if (ACPI_FAILURE (MutexStatus))
304150342Sphk                    {
305162398Skib                        return_ACPI_STATUS (MutexStatus);
306162398Skib                    }
307162398Skib                }
308162398Skib
309162398Skib                Status = UserFunction (ChildNode, Level,
310163481Skib                                        Context, ReturnValue);
311212660Sjh
312212660Sjh                if (UnlockBeforeCallback)
313212660Sjh                {
314212660Sjh                    MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
315212660Sjh                    if (ACPI_FAILURE (MutexStatus))
316212660Sjh                    {
317212660Sjh                        return_ACPI_STATUS (MutexStatus);
318212660Sjh                    }
319212660Sjh                }
320212660Sjh
321212660Sjh                switch (Status)
322212660Sjh                {
323212660Sjh                case AE_OK:
324212660Sjh                case AE_CTRL_DEPTH:
325212660Sjh
326212660Sjh                    /* Just keep going */
327212660Sjh                    break;
328212660Sjh
329212660Sjh                case AE_CTRL_TERMINATE:
330212660Sjh
331212660Sjh                    /* Exit now, with OK status */
332212660Sjh
333212660Sjh                    return_ACPI_STATUS (AE_OK);
334212660Sjh
335212660Sjh                default:
336212660Sjh
337212660Sjh                    /* All others are valid exceptions */
338212826Sjh
339212826Sjh                    return_ACPI_STATUS (Status);
340212660Sjh                }
341212660Sjh            }
342212660Sjh
343212660Sjh            /*
344212660Sjh             * Depth first search:
345212660Sjh             * Attempt to go down another level in the namespace
346212660Sjh             * if we are allowed to.  Don't go any further if we
347212660Sjh             * have reached the caller specified maximum depth
348212660Sjh             * or if the user function has specified that the
349212660Sjh             * maximum depth has been reached.
350212660Sjh             */
351212660Sjh            if ((Level < MaxDepth) && (Status != AE_CTRL_DEPTH))
352212660Sjh            {
353212660Sjh                if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, 0))
354212660Sjh                {
355163481Skib                    /*
356163481Skib                     * There is at least one child of this
357163481Skib                     * node, visit the onde
358162398Skib                     */
359212660Sjh                    Level++;
36064880Sphk                    ParentNode    = ChildNode;
361212660Sjh                    ChildNode     = 0;
362163481Skib                }
36364880Sphk            }
364162398Skib        }
365162398Skib        else
366162398Skib        {
367212660Sjh            /*
368212660Sjh             * No more children of this node (AcpiNsGetNextNode
369212660Sjh             * failed), go back upwards in the namespace tree to
370212660Sjh             * the node's parent.
371212660Sjh             */
372213215Sjh            Level--;
373213215Sjh            ChildNode = ParentNode;
374213215Sjh            ParentNode = AcpiNsGetParentNode (ParentNode);
375213215Sjh        }
376212660Sjh    }
377212660Sjh
378212660Sjh    /* Complete walk, not terminated by user function */
379163481Skib
380163481Skib    return_ACPI_STATUS (AE_OK);
381163481Skib}
382163481Skib
383163481Skib
384163481Skib