nswalk.c revision 99679
1214640Sdim/******************************************************************************
2214640Sdim *
3214640Sdim * Module Name: nswalk - Functions for walking the ACPI namespace
4214640Sdim *              $Revision: 33 $
5214640Sdim *
6214640Sdim *****************************************************************************/
7214640Sdim
8214640Sdim/******************************************************************************
9214640Sdim *
10214640Sdim * 1. Copyright Notice
11214640Sdim *
12214640Sdim * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp.
13214640Sdim * All rights reserved.
14214640Sdim *
15214640Sdim * 2. License
16214640Sdim *
17214640Sdim * 2.1. This is your license from Intel Corp. under its intellectual property
18214640Sdim * rights.  You may have additional license terms from the party that provided
19214640Sdim * you this software, covering your right to use that party's intellectual
20214640Sdim * property rights.
21214640Sdim *
22214640Sdim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23214640Sdim * copy of the source code appearing in this file ("Covered Code") an
24214640Sdim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25214640Sdim * base code distributed originally by Intel ("Original Intel Code") to copy,
26214640Sdim * make derivatives, distribute, use and display any portion of the Covered
27214640Sdim * Code in any form, with the right to sublicense such rights; and
28214640Sdim *
29214640Sdim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30214640Sdim * license (with the right to sublicense), under only those claims of Intel
31214640Sdim * patents that are infringed by the Original Intel Code, to make, use, sell,
32214640Sdim * offer to sell, and import the Covered Code and derivative works thereof
33214640Sdim * solely to the minimum extent necessary to exercise the above copyright
34214640Sdim * license, and in no event shall the patent license extend to any additions
35214640Sdim * to or modifications of the Original Intel Code.  No other license or right
36214640Sdim * is granted directly or by implication, estoppel or otherwise;
37214640Sdim *
38214640Sdim * The above copyright and patent license is granted only if the following
39214640Sdim * conditions are met:
40214640Sdim *
41214640Sdim * 3. Conditions
42214640Sdim *
43214640Sdim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44214640Sdim * Redistribution of source code of any substantial portion of the Covered
45214640Sdim * Code or modification with rights to further distribute source must include
46214640Sdim * the above Copyright Notice, the above License, this list of Conditions,
47214640Sdim * and the following Disclaimer and Export Compliance provision.  In addition,
48214640Sdim * Licensee must cause all Covered Code to which Licensee contributes to
49214640Sdim * contain a file documenting the changes Licensee made to create that Covered
50214640Sdim * Code and the date of any change.  Licensee must include in that file the
51214640Sdim * documentation of any changes made by any predecessor Licensee.  Licensee
52214640Sdim * must include a prominent statement that the modification is derived,
53214640Sdim * directly or indirectly, from Original Intel Code.
54214640Sdim *
55214640Sdim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56214640Sdim * Redistribution of source code of any substantial portion of the Covered
57214640Sdim * Code or modification without rights to further distribute source must
58214640Sdim * include the following Disclaimer and Export Compliance provision in the
59214640Sdim * documentation and/or other materials provided with distribution.  In
60214640Sdim * addition, Licensee may not authorize further sublicense of source of any
61214640Sdim * portion of the Covered Code, and must include terms to the effect that the
62214640Sdim * license from Licensee to its licensee is limited to the intellectual
63214640Sdim * property embodied in the software Licensee provides to its licensee, and
64214640Sdim * not to intellectual property embodied in modifications its licensee may
65214640Sdim * make.
66214640Sdim *
67214640Sdim * 3.3. Redistribution of Executable. Redistribution in executable form of any
68214640Sdim * substantial portion of the Covered Code or modification must reproduce the
69214640Sdim * above Copyright Notice, and the following Disclaimer and Export Compliance
70214640Sdim * provision in the documentation and/or other materials provided with the
71214640Sdim * distribution.
72214640Sdim *
73214640Sdim * 3.4. Intel retains all right, title, and interest in and to the Original
74214640Sdim * Intel Code.
75214640Sdim *
76214640Sdim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77214640Sdim * Intel shall be used in advertising or otherwise to promote the sale, use or
78214640Sdim * other dealings in products derived from or relating to the Covered Code
79214640Sdim * without prior written authorization from Intel.
80214640Sdim *
81214640Sdim * 4. Disclaimer and Export Compliance
82214640Sdim *
83214640Sdim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84214640Sdim * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85214640Sdim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86214640Sdim * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87214640Sdim * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88214640Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89214640Sdim * PARTICULAR PURPOSE.
90214640Sdim *
91214640Sdim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92214640Sdim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93214640Sdim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94214640Sdim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95214640Sdim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96214640Sdim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97214640Sdim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98214640Sdim * LIMITED REMEDY.
99214640Sdim *
100214640Sdim * 4.3. Licensee shall not export, either directly or indirectly, any of this
101214640Sdim * software or system incorporating such software without first obtaining any
102214640Sdim * required license or other approval from the U. S. Department of Commerce or
103214640Sdim * any other agency or department of the United States Government.  In the
104214640Sdim * event Licensee exports any such software from the United States or
105214640Sdim * re-exports any such software from a foreign destination, Licensee shall
106214640Sdim * ensure that the distribution and export/re-export of the software is in
107214640Sdim * compliance with all laws, regulations, orders, or other restrictions of the
108214640Sdim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109214640Sdim * any of its subsidiaries will export/re-export any technical data, process,
110214640Sdim * software, or service, directly or indirectly, to any country for which the
111214640Sdim * United States government or any agency thereof requires an export license,
112214640Sdim * other governmental approval, or letter of assurance, without first obtaining
113214640Sdim * such license, approval or letter.
114214640Sdim *
115214640Sdim *****************************************************************************/
116214640Sdim
117214640Sdim
118214640Sdim#define __NSWALK_C__
119214640Sdim
120214640Sdim#include "acpi.h"
121214640Sdim#include "acnamesp.h"
122214640Sdim
123214640Sdim
124214640Sdim#define _COMPONENT          ACPI_NAMESPACE
125214640Sdim        ACPI_MODULE_NAME    ("nswalk")
126214640Sdim
127214640Sdim
128214640Sdim/*******************************************************************************
129214640Sdim *
130214640Sdim * FUNCTION:    AcpiNsGetNextNode
131214640Sdim *
132214640Sdim * PARAMETERS:  Type                - Type of node to be searched for
133214640Sdim *              ParentNode          - Parent node whose children we are
134235211Sgjb *                                     getting
135214640Sdim *              ChildNode           - Previous child that was found.
136214640Sdim *                                    The NEXT child will be returned
137214640Sdim *
138214640Sdim * RETURN:      ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if
139214640Sdim *                                    none is found.
140214640Sdim *
141214640Sdim * DESCRIPTION: Return the next peer node within the namespace.  If Handle
142214640Sdim *              is valid, Scope is ignored.  Otherwise, the first node
143214640Sdim *              within Scope is returned.
144214640Sdim *
145214640Sdim ******************************************************************************/
146214640Sdim
147214640SdimACPI_NAMESPACE_NODE *
148214640SdimAcpiNsGetNextNode (
149214640Sdim    ACPI_OBJECT_TYPE        Type,
150214640Sdim    ACPI_NAMESPACE_NODE     *ParentNode,
151214640Sdim    ACPI_NAMESPACE_NODE     *ChildNode)
152214640Sdim{
153214640Sdim    ACPI_NAMESPACE_NODE     *NextNode = NULL;
154214640Sdim
155214640Sdim
156214640Sdim    ACPI_FUNCTION_ENTRY ();
157214640Sdim
158214640Sdim
159214640Sdim    if (!ChildNode)
160214640Sdim    {
161214640Sdim        /* It's really the parent's _scope_ that we want */
162214640Sdim
163214640Sdim        if (ParentNode->Child)
164214640Sdim        {
165214640Sdim            NextNode = ParentNode->Child;
166214640Sdim        }
167214640Sdim    }
168214640Sdim
169214640Sdim    else
170214640Sdim    {
171214640Sdim        /* Start search at the NEXT node */
172214640Sdim
173214640Sdim        NextNode = AcpiNsGetNextValidNode (ChildNode);
174214640Sdim    }
175214640Sdim
176214640Sdim    /* If any type is OK, we are done */
177214640Sdim
178214640Sdim    if (Type == ACPI_TYPE_ANY)
179214640Sdim    {
180214640Sdim        /* NextNode is NULL if we are at the end-of-list */
181214640Sdim
182214640Sdim        return (NextNode);
183214640Sdim    }
184214640Sdim
185214640Sdim    /* Must search for the node -- but within this scope only */
186214640Sdim
187214640Sdim    while (NextNode)
188214640Sdim    {
189214640Sdim        /* If type matches, we are done */
190214640Sdim
191214640Sdim        if (NextNode->Type == Type)
192214640Sdim        {
193214640Sdim            return (NextNode);
194214640Sdim        }
195214640Sdim
196214640Sdim        /* Otherwise, move on to the next node */
197214640Sdim
198214640Sdim        NextNode = AcpiNsGetNextValidNode (NextNode);
199214640Sdim    }
200214640Sdim
201214640Sdim    /* Not found */
202214640Sdim
203214640Sdim    return (NULL);
204214640Sdim}
205214640Sdim
206214640Sdim
207214640Sdim/*******************************************************************************
208214640Sdim *
209214640Sdim * FUNCTION:    AcpiNsWalkNamespace
210214640Sdim *
211214640Sdim * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
212214640Sdim *              StartNode           - Handle in namespace where search begins
213214640Sdim *              MaxDepth            - Depth to which search is to reach
214214640Sdim *              UnlockBeforeCallback- Whether to unlock the NS before invoking
215214640Sdim *                                    the callback routine
216214640Sdim *              UserFunction        - Called when an object of "Type" is found
217214640Sdim *              Context             - Passed to user function
218214640Sdim *              ReturnValue         - from the UserFunction if terminated early.
219214640Sdim *                                    Otherwise, returns NULL.
220214640Sdim * RETURNS:     Status
221214640Sdim *
222214640Sdim * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
223214640Sdim *              starting (and ending) at the node specified by StartHandle.
224214640Sdim *              The UserFunction is called whenever a node that matches
225214640Sdim *              the type parameter is found.  If the user function returns
226214640Sdim *              a non-zero value, the search is terminated immediately and this
227214640Sdim *              value is returned to the caller.
228214640Sdim *
229214640Sdim *              The point of this procedure is to provide a generic namespace
230214640Sdim *              walk routine that can be called from multiple places to
231214640Sdim *              provide multiple services;  the User Function can be tailored
232214640Sdim *              to each task, whether it is a print function, a compare
233214640Sdim *              function, etc.
234214640Sdim *
235214640Sdim ******************************************************************************/
236214640Sdim
237214640SdimACPI_STATUS
238214640SdimAcpiNsWalkNamespace (
239214640Sdim    ACPI_OBJECT_TYPE        Type,
240214640Sdim    ACPI_HANDLE             StartNode,
241214640Sdim    UINT32                  MaxDepth,
242214640Sdim    BOOLEAN                 UnlockBeforeCallback,
243214640Sdim    ACPI_WALK_CALLBACK      UserFunction,
244214640Sdim    void                    *Context,
245214640Sdim    void                    **ReturnValue)
246214640Sdim{
247214640Sdim    ACPI_STATUS             Status;
248214640Sdim    ACPI_NAMESPACE_NODE     *ChildNode;
249214640Sdim    ACPI_NAMESPACE_NODE     *ParentNode;
250214640Sdim    ACPI_OBJECT_TYPE        ChildType;
251214640Sdim    UINT32                  Level;
252214640Sdim
253214640Sdim
254214640Sdim    ACPI_FUNCTION_TRACE ("NsWalkNamespace");
255214640Sdim
256214640Sdim
257214640Sdim    /* Special case for the namespace Root Node */
258214640Sdim
259214640Sdim    if (StartNode == ACPI_ROOT_OBJECT)
260214640Sdim    {
261214640Sdim        StartNode = AcpiGbl_RootNode;
262214640Sdim    }
263214640Sdim
264214640Sdim    /* Null child means "get first node" */
265214640Sdim
266214640Sdim    ParentNode  = StartNode;
267214640Sdim    ChildNode   = 0;
268214640Sdim    ChildType   = ACPI_TYPE_ANY;
269214640Sdim    Level       = 1;
270214640Sdim
271214640Sdim    /*
272214640Sdim     * Traverse the tree of nodes until we bubble back up to where we
273214640Sdim     * started. When Level is zero, the loop is done because we have
274214640Sdim     * bubbled up to (and passed) the original parent handle (StartEntry)
275214640Sdim     */
276214640Sdim    while (Level > 0)
277214640Sdim    {
278214640Sdim        /* Get the next node in this scope.  Null if not found */
279214640Sdim
280214640Sdim        Status = AE_OK;
281214640Sdim        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode);
282214640Sdim        if (ChildNode)
283214640Sdim        {
284214640Sdim            /*
285214640Sdim             * Found node, Get the type if we are not
286214640Sdim             * searching for ANY
287214640Sdim             */
288214640Sdim            if (Type != ACPI_TYPE_ANY)
289214640Sdim            {
290214640Sdim                ChildType = ChildNode->Type;
291214640Sdim            }
292214640Sdim
293214640Sdim            if (ChildType == Type)
294214640Sdim            {
295214640Sdim                /*
296214640Sdim                 * Found a matching node, invoke the user
297214640Sdim                 * callback function
298214640Sdim                 */
299214640Sdim                if (UnlockBeforeCallback)
300214640Sdim                {
301214640Sdim                    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
302214640Sdim                    if (ACPI_FAILURE (Status))
303226436Seadler                    {
304226436Seadler                        return_ACPI_STATUS (Status);
305214640Sdim                    }
306214640Sdim                }
307214640Sdim
308214640Sdim                Status = UserFunction (ChildNode, Level,
309214640Sdim                                        Context, ReturnValue);
310214640Sdim
311214640Sdim                if (UnlockBeforeCallback)
312214640Sdim                {
313214640Sdim                    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
314214640Sdim                    if (ACPI_FAILURE (Status))
315214640Sdim                    {
316214640Sdim                        return_ACPI_STATUS (Status);
317214640Sdim                    }
318214640Sdim                }
319214640Sdim
320214640Sdim                switch (Status)
321214640Sdim                {
322214640Sdim                case AE_OK:
323214640Sdim                case AE_CTRL_DEPTH:
324214640Sdim
325214640Sdim                    /* Just keep going */
326214640Sdim                    break;
327214640Sdim
328214640Sdim                case AE_CTRL_TERMINATE:
329214640Sdim
330214640Sdim                    /* Exit now, with OK status */
331214640Sdim
332214640Sdim                    return_ACPI_STATUS (AE_OK);
333214640Sdim
334214640Sdim                default:
335214640Sdim
336214640Sdim                    /* All others are valid exceptions */
337214640Sdim
338214640Sdim                    return_ACPI_STATUS (Status);
339214640Sdim                }
340214640Sdim            }
341214640Sdim
342214640Sdim            /*
343214640Sdim             * Depth first search:
344214640Sdim             * Attempt to go down another level in the namespace
345214640Sdim             * if we are allowed to.  Don't go any further if we
346214640Sdim             * have reached the caller specified maximum depth
347214640Sdim             * or if the user function has specified that the
348214640Sdim             * maximum depth has been reached.
349214640Sdim             */
350214640Sdim            if ((Level < MaxDepth) && (Status != AE_CTRL_DEPTH))
351214640Sdim            {
352214640Sdim                if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, 0))
353214640Sdim                {
354214640Sdim                    /*
355214640Sdim                     * There is at least one child of this
356214640Sdim                     * node, visit the onde
357214640Sdim                     */
358214640Sdim                    Level++;
359214640Sdim                    ParentNode    = ChildNode;
360214640Sdim                    ChildNode     = 0;
361214640Sdim                }
362214640Sdim            }
363214640Sdim        }
364214640Sdim        else
365214640Sdim        {
366214640Sdim            /*
367214640Sdim             * No more children of this node (AcpiNsGetNextNode
368214640Sdim             * failed), go back upwards in the namespace tree to
369214640Sdim             * the node's parent.
370214640Sdim             */
371214640Sdim            Level--;
372214640Sdim            ChildNode = ParentNode;
373214640Sdim            ParentNode = AcpiNsGetParentNode (ParentNode);
374214640Sdim        }
375214640Sdim    }
376214640Sdim
377214640Sdim    /* Complete walk, not terminated by user function */
378214640Sdim
379214640Sdim    return_ACPI_STATUS (AE_OK);
380214640Sdim}
381214640Sdim
382214640Sdim
383214640Sdim