1ae115bc7Smrj /****************************************************************************** 2ae115bc7Smrj * 3ae115bc7Smrj * Module Name: nswalk - Functions for walking the ACPI namespace 4ae115bc7Smrj * 5ae115bc7Smrj *****************************************************************************/ 6ae115bc7Smrj 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9ae115bc7Smrj * All rights reserved. 10ae115bc7Smrj * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25ae115bc7Smrj * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29ae115bc7Smrj * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43ae115bc7Smrj 44ae115bc7Smrj #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46ae115bc7Smrj #include "acnamesp.h" 47ae115bc7Smrj 48ae115bc7Smrj 49ae115bc7Smrj #define _COMPONENT ACPI_NAMESPACE 50ae115bc7Smrj ACPI_MODULE_NAME ("nswalk") 51ae115bc7Smrj 52ae115bc7Smrj 53ae115bc7Smrj /******************************************************************************* 54ae115bc7Smrj * 55ae115bc7Smrj * FUNCTION: AcpiNsGetNextNode 56ae115bc7Smrj * 57aa2aa9a6SDana Myers * PARAMETERS: ParentNode - Parent node whose children we are 58aa2aa9a6SDana Myers * getting 59aa2aa9a6SDana Myers * ChildNode - Previous child that was found. 60aa2aa9a6SDana Myers * The NEXT child will be returned 61aa2aa9a6SDana Myers * 62aa2aa9a6SDana Myers * RETURN: ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if 63aa2aa9a6SDana Myers * none is found. 64aa2aa9a6SDana Myers * 65aa2aa9a6SDana Myers * DESCRIPTION: Return the next peer node within the namespace. If Handle 66aa2aa9a6SDana Myers * is valid, Scope is ignored. Otherwise, the first node 67aa2aa9a6SDana Myers * within Scope is returned. 68aa2aa9a6SDana Myers * 69aa2aa9a6SDana Myers ******************************************************************************/ 70aa2aa9a6SDana Myers 71aa2aa9a6SDana Myers ACPI_NAMESPACE_NODE * 72aa2aa9a6SDana Myers AcpiNsGetNextNode ( 73aa2aa9a6SDana Myers ACPI_NAMESPACE_NODE *ParentNode, 74aa2aa9a6SDana Myers ACPI_NAMESPACE_NODE *ChildNode) 75aa2aa9a6SDana Myers { 76aa2aa9a6SDana Myers ACPI_FUNCTION_ENTRY (); 77aa2aa9a6SDana Myers 78aa2aa9a6SDana Myers 79aa2aa9a6SDana Myers if (!ChildNode) 80aa2aa9a6SDana Myers { 81aa2aa9a6SDana Myers /* It's really the parent's _scope_ that we want */ 82aa2aa9a6SDana Myers 83aa2aa9a6SDana Myers return (ParentNode->Child); 84aa2aa9a6SDana Myers } 85aa2aa9a6SDana Myers 86aa2aa9a6SDana Myers /* Otherwise just return the next peer */ 87aa2aa9a6SDana Myers 88aa2aa9a6SDana Myers return (ChildNode->Peer); 89aa2aa9a6SDana Myers } 90aa2aa9a6SDana Myers 91aa2aa9a6SDana Myers 92aa2aa9a6SDana Myers /******************************************************************************* 93aa2aa9a6SDana Myers * 94aa2aa9a6SDana Myers * FUNCTION: AcpiNsGetNextNodeTyped 95aa2aa9a6SDana Myers * 96ae115bc7Smrj * PARAMETERS: Type - Type of node to be searched for 97ae115bc7Smrj * ParentNode - Parent node whose children we are 98ae115bc7Smrj * getting 99ae115bc7Smrj * ChildNode - Previous child that was found. 100ae115bc7Smrj * The NEXT child will be returned 101ae115bc7Smrj * 102ae115bc7Smrj * RETURN: ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if 103ae115bc7Smrj * none is found. 104ae115bc7Smrj * 105ae115bc7Smrj * DESCRIPTION: Return the next peer node within the namespace. If Handle 106ae115bc7Smrj * is valid, Scope is ignored. Otherwise, the first node 107ae115bc7Smrj * within Scope is returned. 108ae115bc7Smrj * 109ae115bc7Smrj ******************************************************************************/ 110ae115bc7Smrj 111ae115bc7Smrj ACPI_NAMESPACE_NODE * 112aa2aa9a6SDana Myers AcpiNsGetNextNodeTyped ( 113ae115bc7Smrj ACPI_OBJECT_TYPE Type, 114ae115bc7Smrj ACPI_NAMESPACE_NODE *ParentNode, 115ae115bc7Smrj ACPI_NAMESPACE_NODE *ChildNode) 116ae115bc7Smrj { 117ae115bc7Smrj ACPI_NAMESPACE_NODE *NextNode = NULL; 118ae115bc7Smrj 119ae115bc7Smrj 120ae115bc7Smrj ACPI_FUNCTION_ENTRY (); 121ae115bc7Smrj 122ae115bc7Smrj 123aa2aa9a6SDana Myers NextNode = AcpiNsGetNextNode (ParentNode, ChildNode); 124ae115bc7Smrj 125ae115bc7Smrj /* If any type is OK, we are done */ 126ae115bc7Smrj 127ae115bc7Smrj if (Type == ACPI_TYPE_ANY) 128ae115bc7Smrj { 129ae115bc7Smrj /* NextNode is NULL if we are at the end-of-list */ 130ae115bc7Smrj 131ae115bc7Smrj return (NextNode); 132ae115bc7Smrj } 133ae115bc7Smrj 134ae115bc7Smrj /* Must search for the node -- but within this scope only */ 135ae115bc7Smrj 136ae115bc7Smrj while (NextNode) 137ae115bc7Smrj { 138ae115bc7Smrj /* If type matches, we are done */ 139ae115bc7Smrj 140ae115bc7Smrj if (NextNode->Type == Type) 141ae115bc7Smrj { 142ae115bc7Smrj return (NextNode); 143ae115bc7Smrj } 144ae115bc7Smrj 14526f3cdf0SGordon Ross /* Otherwise, move on to the next peer node */ 146ae115bc7Smrj 14726f3cdf0SGordon Ross NextNode = NextNode->Peer; 148ae115bc7Smrj } 149ae115bc7Smrj 150ae115bc7Smrj /* Not found */ 151ae115bc7Smrj 152ae115bc7Smrj return (NULL); 153ae115bc7Smrj } 154ae115bc7Smrj 155ae115bc7Smrj 156ae115bc7Smrj /******************************************************************************* 157ae115bc7Smrj * 158ae115bc7Smrj * FUNCTION: AcpiNsWalkNamespace 159ae115bc7Smrj * 160ae115bc7Smrj * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for 161ae115bc7Smrj * StartNode - Handle in namespace where search begins 162ae115bc7Smrj * MaxDepth - Depth to which search is to reach 163db2bae30SDana Myers * Flags - Whether to unlock the NS before invoking 164ae115bc7Smrj * the callback routine 165*385cc6b4SJerry Jelinek * DescendingCallback - Called during tree descent 16657190917SDana Myers * when an object of "Type" is found 167*385cc6b4SJerry Jelinek * AscendingCallback - Called during tree ascent 16857190917SDana Myers * when an object of "Type" is found 16957190917SDana Myers * Context - Passed to user function(s) above 17057190917SDana Myers * ReturnValue - from the UserFunction if terminated 17157190917SDana Myers * early. Otherwise, returns NULL. 172ae115bc7Smrj * RETURNS: Status 173ae115bc7Smrj * 174ae115bc7Smrj * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 175ae115bc7Smrj * starting (and ending) at the node specified by StartHandle. 17657190917SDana Myers * The callback function is called whenever a node that matches 17757190917SDana Myers * the type parameter is found. If the callback function returns 178aa2aa9a6SDana Myers * a non-zero value, the search is terminated immediately and 179aa2aa9a6SDana Myers * this value is returned to the caller. 180ae115bc7Smrj * 181ae115bc7Smrj * The point of this procedure is to provide a generic namespace 182ae115bc7Smrj * walk routine that can be called from multiple places to 18357190917SDana Myers * provide multiple services; the callback function(s) can be 18457190917SDana Myers * tailored to each task, whether it is a print function, 18557190917SDana Myers * a compare function, etc. 186ae115bc7Smrj * 187ae115bc7Smrj ******************************************************************************/ 188ae115bc7Smrj 189ae115bc7Smrj ACPI_STATUS 190ae115bc7Smrj AcpiNsWalkNamespace ( 191ae115bc7Smrj ACPI_OBJECT_TYPE Type, 192ae115bc7Smrj ACPI_HANDLE StartNode, 193ae115bc7Smrj UINT32 MaxDepth, 194db2bae30SDana Myers UINT32 Flags, 195*385cc6b4SJerry Jelinek ACPI_WALK_CALLBACK DescendingCallback, 196*385cc6b4SJerry Jelinek ACPI_WALK_CALLBACK AscendingCallback, 197ae115bc7Smrj void *Context, 198ae115bc7Smrj void **ReturnValue) 199ae115bc7Smrj { 200ae115bc7Smrj ACPI_STATUS Status; 201ae115bc7Smrj ACPI_STATUS MutexStatus; 202ae115bc7Smrj ACPI_NAMESPACE_NODE *ChildNode; 203ae115bc7Smrj ACPI_NAMESPACE_NODE *ParentNode; 204ae115bc7Smrj ACPI_OBJECT_TYPE ChildType; 205ae115bc7Smrj UINT32 Level; 20657190917SDana Myers BOOLEAN NodePreviouslyVisited = FALSE; 207ae115bc7Smrj 208ae115bc7Smrj 209ae115bc7Smrj ACPI_FUNCTION_TRACE (NsWalkNamespace); 210ae115bc7Smrj 211ae115bc7Smrj 212ae115bc7Smrj /* Special case for the namespace Root Node */ 213ae115bc7Smrj 214ae115bc7Smrj if (StartNode == ACPI_ROOT_OBJECT) 215ae115bc7Smrj { 216ae115bc7Smrj StartNode = AcpiGbl_RootNode; 217ae115bc7Smrj } 218ae115bc7Smrj 219ae115bc7Smrj /* Null child means "get first node" */ 220ae115bc7Smrj 221ae115bc7Smrj ParentNode = StartNode; 22257190917SDana Myers ChildNode = AcpiNsGetNextNode (ParentNode, NULL); 223ae115bc7Smrj ChildType = ACPI_TYPE_ANY; 224ae115bc7Smrj Level = 1; 225ae115bc7Smrj 226ae115bc7Smrj /* 227ae115bc7Smrj * Traverse the tree of nodes until we bubble back up to where we 228ae115bc7Smrj * started. When Level is zero, the loop is done because we have 229ae115bc7Smrj * bubbled up to (and passed) the original parent handle (StartEntry) 230ae115bc7Smrj */ 23157190917SDana Myers while (Level > 0 && ChildNode) 232ae115bc7Smrj { 233ae115bc7Smrj Status = AE_OK; 23457190917SDana Myers 235db2bae30SDana Myers /* Found next child, get the type if we are not searching for ANY */ 236db2bae30SDana Myers 237ae115bc7Smrj if (Type != ACPI_TYPE_ANY) 238ae115bc7Smrj { 239ae115bc7Smrj ChildType = ChildNode->Type; 240ae115bc7Smrj } 241ae115bc7Smrj 242db2bae30SDana Myers /* 243db2bae30SDana Myers * Ignore all temporary namespace nodes (created during control 244db2bae30SDana Myers * method execution) unless told otherwise. These temporary nodes 245aa2aa9a6SDana Myers * can cause a race condition because they can be deleted during 246aa2aa9a6SDana Myers * the execution of the user function (if the namespace is 247aa2aa9a6SDana Myers * unlocked before invocation of the user function.) Only the 248aa2aa9a6SDana Myers * debugger namespace dump will examine the temporary nodes. 249db2bae30SDana Myers */ 250db2bae30SDana Myers if ((ChildNode->Flags & ANOBJ_TEMPORARY) && 251db2bae30SDana Myers !(Flags & ACPI_NS_WALK_TEMP_NODES)) 252db2bae30SDana Myers { 253db2bae30SDana Myers Status = AE_CTRL_DEPTH; 254db2bae30SDana Myers } 255db2bae30SDana Myers 256db2bae30SDana Myers /* Type must match requested type */ 257db2bae30SDana Myers 258db2bae30SDana Myers else if (ChildType == Type) 259ae115bc7Smrj { 260ae115bc7Smrj /* 261db2bae30SDana Myers * Found a matching node, invoke the user callback function. 262db2bae30SDana Myers * Unlock the namespace if flag is set. 263ae115bc7Smrj */ 264db2bae30SDana Myers if (Flags & ACPI_NS_WALK_UNLOCK) 265ae115bc7Smrj { 266ae115bc7Smrj MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 267ae115bc7Smrj if (ACPI_FAILURE (MutexStatus)) 268ae115bc7Smrj { 269ae115bc7Smrj return_ACPI_STATUS (MutexStatus); 270ae115bc7Smrj } 271ae115bc7Smrj } 272ae115bc7Smrj 27357190917SDana Myers /* 274*385cc6b4SJerry Jelinek * Invoke the user function, either descending, ascending, 27557190917SDana Myers * or both. 27657190917SDana Myers */ 27757190917SDana Myers if (!NodePreviouslyVisited) 27857190917SDana Myers { 279*385cc6b4SJerry Jelinek if (DescendingCallback) 28057190917SDana Myers { 281*385cc6b4SJerry Jelinek Status = DescendingCallback (ChildNode, Level, 28257190917SDana Myers Context, ReturnValue); 28357190917SDana Myers } 28457190917SDana Myers } 28557190917SDana Myers else 28657190917SDana Myers { 287*385cc6b4SJerry Jelinek if (AscendingCallback) 28857190917SDana Myers { 289*385cc6b4SJerry Jelinek Status = AscendingCallback (ChildNode, Level, 29057190917SDana Myers Context, ReturnValue); 29157190917SDana Myers } 29257190917SDana Myers } 293ae115bc7Smrj 294db2bae30SDana Myers if (Flags & ACPI_NS_WALK_UNLOCK) 295ae115bc7Smrj { 296ae115bc7Smrj MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 297ae115bc7Smrj if (ACPI_FAILURE (MutexStatus)) 298ae115bc7Smrj { 299ae115bc7Smrj return_ACPI_STATUS (MutexStatus); 300ae115bc7Smrj } 301ae115bc7Smrj } 302ae115bc7Smrj 303ae115bc7Smrj switch (Status) 304ae115bc7Smrj { 305ae115bc7Smrj case AE_OK: 306ae115bc7Smrj case AE_CTRL_DEPTH: 307ae115bc7Smrj 308ae115bc7Smrj /* Just keep going */ 309ae115bc7Smrj break; 310ae115bc7Smrj 311ae115bc7Smrj case AE_CTRL_TERMINATE: 312ae115bc7Smrj 313ae115bc7Smrj /* Exit now, with OK status */ 314ae115bc7Smrj 315ae115bc7Smrj return_ACPI_STATUS (AE_OK); 316ae115bc7Smrj 317ae115bc7Smrj default: 318ae115bc7Smrj 319ae115bc7Smrj /* All others are valid exceptions */ 320ae115bc7Smrj 321ae115bc7Smrj return_ACPI_STATUS (Status); 322ae115bc7Smrj } 323ae115bc7Smrj } 324ae115bc7Smrj 325ae115bc7Smrj /* 326db2bae30SDana Myers * Depth first search: Attempt to go down another level in the 327db2bae30SDana Myers * namespace if we are allowed to. Don't go any further if we have 328db2bae30SDana Myers * reached the caller specified maximum depth or if the user 329db2bae30SDana Myers * function has specified that the maximum depth has been reached. 330ae115bc7Smrj */ 33157190917SDana Myers if (!NodePreviouslyVisited && 33257190917SDana Myers (Level < MaxDepth) && 33357190917SDana Myers (Status != AE_CTRL_DEPTH)) 334ae115bc7Smrj { 335aa2aa9a6SDana Myers if (ChildNode->Child) 336ae115bc7Smrj { 337db2bae30SDana Myers /* There is at least one child of this node, visit it */ 338db2bae30SDana Myers 339ae115bc7Smrj Level++; 340ae115bc7Smrj ParentNode = ChildNode; 34157190917SDana Myers ChildNode = AcpiNsGetNextNode (ParentNode, NULL); 34257190917SDana Myers continue; 343ae115bc7Smrj } 344ae115bc7Smrj } 34557190917SDana Myers 34657190917SDana Myers /* No more children, re-visit this node */ 34757190917SDana Myers 34857190917SDana Myers if (!NodePreviouslyVisited) 34957190917SDana Myers { 35057190917SDana Myers NodePreviouslyVisited = TRUE; 35157190917SDana Myers continue; 352ae115bc7Smrj } 35357190917SDana Myers 35457190917SDana Myers /* No more children, visit peers */ 35557190917SDana Myers 35657190917SDana Myers ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); 35757190917SDana Myers if (ChildNode) 35857190917SDana Myers { 35957190917SDana Myers NodePreviouslyVisited = FALSE; 36057190917SDana Myers } 36157190917SDana Myers 36257190917SDana Myers /* No peers, re-visit parent */ 36357190917SDana Myers 364ae115bc7Smrj else 365ae115bc7Smrj { 366ae115bc7Smrj /* 367db2bae30SDana Myers * No more children of this node (AcpiNsGetNextNode failed), go 368db2bae30SDana Myers * back upwards in the namespace tree to the node's parent. 369ae115bc7Smrj */ 370ae115bc7Smrj Level--; 371ae115bc7Smrj ChildNode = ParentNode; 37226f3cdf0SGordon Ross ParentNode = ParentNode->Parent; 37357190917SDana Myers 37457190917SDana Myers NodePreviouslyVisited = TRUE; 375ae115bc7Smrj } 376ae115bc7Smrj } 377ae115bc7Smrj 378ae115bc7Smrj /* Complete walk, not terminated by user function */ 379ae115bc7Smrj 380ae115bc7Smrj return_ACPI_STATUS (AE_OK); 381ae115bc7Smrj } 382