13446Smrj /******************************************************************************* 23446Smrj * 33446Smrj * Module Name: nsaccess - Top-level functions for accessing ACPI namespace 43446Smrj * 53446Smrj ******************************************************************************/ 63446Smrj 73446Smrj /****************************************************************************** 83446Smrj * 93446Smrj * 1. Copyright Notice 103446Smrj * 11*9980SDana.Myers@Sun.COM * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 123446Smrj * All rights reserved. 133446Smrj * 143446Smrj * 2. License 153446Smrj * 163446Smrj * 2.1. This is your license from Intel Corp. under its intellectual property 173446Smrj * rights. You may have additional license terms from the party that provided 183446Smrj * you this software, covering your right to use that party's intellectual 193446Smrj * property rights. 203446Smrj * 213446Smrj * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 223446Smrj * copy of the source code appearing in this file ("Covered Code") an 233446Smrj * irrevocable, perpetual, worldwide license under Intel's copyrights in the 243446Smrj * base code distributed originally by Intel ("Original Intel Code") to copy, 253446Smrj * make derivatives, distribute, use and display any portion of the Covered 263446Smrj * Code in any form, with the right to sublicense such rights; and 273446Smrj * 283446Smrj * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 293446Smrj * license (with the right to sublicense), under only those claims of Intel 303446Smrj * patents that are infringed by the Original Intel Code, to make, use, sell, 313446Smrj * offer to sell, and import the Covered Code and derivative works thereof 323446Smrj * solely to the minimum extent necessary to exercise the above copyright 333446Smrj * license, and in no event shall the patent license extend to any additions 343446Smrj * to or modifications of the Original Intel Code. No other license or right 353446Smrj * is granted directly or by implication, estoppel or otherwise; 363446Smrj * 373446Smrj * The above copyright and patent license is granted only if the following 383446Smrj * conditions are met: 393446Smrj * 403446Smrj * 3. Conditions 413446Smrj * 423446Smrj * 3.1. Redistribution of Source with Rights to Further Distribute Source. 433446Smrj * Redistribution of source code of any substantial portion of the Covered 443446Smrj * Code or modification with rights to further distribute source must include 453446Smrj * the above Copyright Notice, the above License, this list of Conditions, 463446Smrj * and the following Disclaimer and Export Compliance provision. In addition, 473446Smrj * Licensee must cause all Covered Code to which Licensee contributes to 483446Smrj * contain a file documenting the changes Licensee made to create that Covered 493446Smrj * Code and the date of any change. Licensee must include in that file the 503446Smrj * documentation of any changes made by any predecessor Licensee. Licensee 513446Smrj * must include a prominent statement that the modification is derived, 523446Smrj * directly or indirectly, from Original Intel Code. 533446Smrj * 543446Smrj * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 553446Smrj * Redistribution of source code of any substantial portion of the Covered 563446Smrj * Code or modification without rights to further distribute source must 573446Smrj * include the following Disclaimer and Export Compliance provision in the 583446Smrj * documentation and/or other materials provided with distribution. In 593446Smrj * addition, Licensee may not authorize further sublicense of source of any 603446Smrj * portion of the Covered Code, and must include terms to the effect that the 613446Smrj * license from Licensee to its licensee is limited to the intellectual 623446Smrj * property embodied in the software Licensee provides to its licensee, and 633446Smrj * not to intellectual property embodied in modifications its licensee may 643446Smrj * make. 653446Smrj * 663446Smrj * 3.3. Redistribution of Executable. Redistribution in executable form of any 673446Smrj * substantial portion of the Covered Code or modification must reproduce the 683446Smrj * above Copyright Notice, and the following Disclaimer and Export Compliance 693446Smrj * provision in the documentation and/or other materials provided with the 703446Smrj * distribution. 713446Smrj * 723446Smrj * 3.4. Intel retains all right, title, and interest in and to the Original 733446Smrj * Intel Code. 743446Smrj * 753446Smrj * 3.5. Neither the name Intel nor any other trademark owned or controlled by 763446Smrj * Intel shall be used in advertising or otherwise to promote the sale, use or 773446Smrj * other dealings in products derived from or relating to the Covered Code 783446Smrj * without prior written authorization from Intel. 793446Smrj * 803446Smrj * 4. Disclaimer and Export Compliance 813446Smrj * 823446Smrj * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 833446Smrj * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 843446Smrj * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 853446Smrj * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 863446Smrj * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 873446Smrj * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 883446Smrj * PARTICULAR PURPOSE. 893446Smrj * 903446Smrj * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 913446Smrj * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 923446Smrj * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 933446Smrj * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 943446Smrj * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 953446Smrj * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 963446Smrj * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 973446Smrj * LIMITED REMEDY. 983446Smrj * 993446Smrj * 4.3. Licensee shall not export, either directly or indirectly, any of this 1003446Smrj * software or system incorporating such software without first obtaining any 1013446Smrj * required license or other approval from the U. S. Department of Commerce or 1023446Smrj * any other agency or department of the United States Government. In the 1033446Smrj * event Licensee exports any such software from the United States or 1043446Smrj * re-exports any such software from a foreign destination, Licensee shall 1053446Smrj * ensure that the distribution and export/re-export of the software is in 1063446Smrj * compliance with all laws, regulations, orders, or other restrictions of the 1073446Smrj * U.S. Export Administration Regulations. Licensee agrees that neither it nor 1083446Smrj * any of its subsidiaries will export/re-export any technical data, process, 1093446Smrj * software, or service, directly or indirectly, to any country for which the 1103446Smrj * United States government or any agency thereof requires an export license, 1113446Smrj * other governmental approval, or letter of assurance, without first obtaining 1123446Smrj * such license, approval or letter. 1133446Smrj * 1143446Smrj *****************************************************************************/ 1153446Smrj 1163446Smrj #define __NSACCESS_C__ 1173446Smrj 1183446Smrj #include "acpi.h" 119*9980SDana.Myers@Sun.COM #include "accommon.h" 1203446Smrj #include "amlcode.h" 1213446Smrj #include "acnamesp.h" 1223446Smrj #include "acdispat.h" 1233446Smrj 1243446Smrj 1253446Smrj #define _COMPONENT ACPI_NAMESPACE 1263446Smrj ACPI_MODULE_NAME ("nsaccess") 1273446Smrj 1283446Smrj 1293446Smrj /******************************************************************************* 1303446Smrj * 1313446Smrj * FUNCTION: AcpiNsRootInitialize 1323446Smrj * 1333446Smrj * PARAMETERS: None 1343446Smrj * 1353446Smrj * RETURN: Status 1363446Smrj * 1373446Smrj * DESCRIPTION: Allocate and initialize the default root named objects 1383446Smrj * 1393446Smrj * MUTEX: Locks namespace for entire execution 1403446Smrj * 1413446Smrj ******************************************************************************/ 1423446Smrj 1433446Smrj ACPI_STATUS 1443446Smrj AcpiNsRootInitialize ( 1453446Smrj void) 1463446Smrj { 1473446Smrj ACPI_STATUS Status; 1483446Smrj const ACPI_PREDEFINED_NAMES *InitVal = NULL; 1493446Smrj ACPI_NAMESPACE_NODE *NewNode; 1503446Smrj ACPI_OPERAND_OBJECT *ObjDesc; 1513446Smrj ACPI_STRING Val = NULL; 1523446Smrj 1533446Smrj 1543446Smrj ACPI_FUNCTION_TRACE (NsRootInitialize); 1553446Smrj 1563446Smrj 1573446Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1583446Smrj if (ACPI_FAILURE (Status)) 1593446Smrj { 1603446Smrj return_ACPI_STATUS (Status); 1613446Smrj } 1623446Smrj 1633446Smrj /* 1643446Smrj * The global root ptr is initially NULL, so a non-NULL value indicates 1653446Smrj * that AcpiNsRootInitialize() has already been called; just return. 1663446Smrj */ 1673446Smrj if (AcpiGbl_RootNode) 1683446Smrj { 1693446Smrj Status = AE_OK; 1703446Smrj goto UnlockAndExit; 1713446Smrj } 1723446Smrj 1733446Smrj /* 1743446Smrj * Tell the rest of the subsystem that the root is initialized 1753446Smrj * (This is OK because the namespace is locked) 1763446Smrj */ 1773446Smrj AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct; 1783446Smrj 1793446Smrj /* Enter the pre-defined names in the name table */ 1803446Smrj 1813446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 1823446Smrj "Entering predefined entries into namespace\n")); 1833446Smrj 1843446Smrj for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++) 1853446Smrj { 1863446Smrj /* _OSI is optional for now, will be permanent later */ 1873446Smrj 1883446Smrj if (!ACPI_STRCMP (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) 1893446Smrj { 1903446Smrj continue; 1913446Smrj } 1923446Smrj 1933446Smrj Status = AcpiNsLookup (NULL, InitVal->Name, InitVal->Type, 1943446Smrj ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, 1953446Smrj NULL, &NewNode); 1963446Smrj 1973446Smrj if (ACPI_FAILURE (Status) || (!NewNode)) /* Must be on same line for code converter */ 1983446Smrj { 1993446Smrj ACPI_EXCEPTION ((AE_INFO, Status, 2003446Smrj "Could not create predefined name %s", 2013446Smrj InitVal->Name)); 2023446Smrj } 2033446Smrj 2043446Smrj /* 205*9980SDana.Myers@Sun.COM * Name entered successfully. If entry in PreDefinedNames[] specifies 206*9980SDana.Myers@Sun.COM * an initial value, create the initial value. 2073446Smrj */ 2083446Smrj if (InitVal->Val) 2093446Smrj { 2103446Smrj Status = AcpiOsPredefinedOverride (InitVal, &Val); 2113446Smrj if (ACPI_FAILURE (Status)) 2123446Smrj { 2133446Smrj ACPI_ERROR ((AE_INFO, 2143446Smrj "Could not override predefined %s", 2153446Smrj InitVal->Name)); 2163446Smrj } 2173446Smrj 2183446Smrj if (!Val) 2193446Smrj { 2203446Smrj Val = InitVal->Val; 2213446Smrj } 2223446Smrj 2233446Smrj /* 2243446Smrj * Entry requests an initial value, allocate a 2253446Smrj * descriptor for it. 2263446Smrj */ 2273446Smrj ObjDesc = AcpiUtCreateInternalObject (InitVal->Type); 2283446Smrj if (!ObjDesc) 2293446Smrj { 2303446Smrj Status = AE_NO_MEMORY; 2313446Smrj goto UnlockAndExit; 2323446Smrj } 2333446Smrj 2343446Smrj /* 2353446Smrj * Convert value string from table entry to 2363446Smrj * internal representation. Only types actually 2373446Smrj * used for initial values are implemented here. 2383446Smrj */ 2393446Smrj switch (InitVal->Type) 2403446Smrj { 2413446Smrj case ACPI_TYPE_METHOD: 2423446Smrj ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val); 2433446Smrj ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; 2443446Smrj 2453446Smrj #if defined (ACPI_ASL_COMPILER) 2463446Smrj 2473446Smrj /* Save the parameter count for the iASL compiler */ 2483446Smrj 2493446Smrj NewNode->Value = ObjDesc->Method.ParamCount; 2503446Smrj #else 2513446Smrj /* Mark this as a very SPECIAL method */ 2523446Smrj 2533446Smrj ObjDesc->Method.MethodFlags = AML_METHOD_INTERNAL_ONLY; 2543446Smrj ObjDesc->Method.Implementation = AcpiUtOsiImplementation; 2553446Smrj #endif 2563446Smrj break; 2573446Smrj 2583446Smrj case ACPI_TYPE_INTEGER: 2593446Smrj 2603446Smrj ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val); 2613446Smrj break; 2623446Smrj 2633446Smrj 2643446Smrj case ACPI_TYPE_STRING: 2653446Smrj 266*9980SDana.Myers@Sun.COM /* Build an object around the static string */ 267*9980SDana.Myers@Sun.COM 2683446Smrj ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Val); 2693446Smrj ObjDesc->String.Pointer = Val; 2703446Smrj ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; 2713446Smrj break; 2723446Smrj 2733446Smrj 2743446Smrj case ACPI_TYPE_MUTEX: 2753446Smrj 2763446Smrj ObjDesc->Mutex.Node = NewNode; 2773446Smrj ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1); 2783446Smrj 2793446Smrj /* Create a mutex */ 2803446Smrj 2813446Smrj Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex); 2823446Smrj if (ACPI_FAILURE (Status)) 2833446Smrj { 2843446Smrj AcpiUtRemoveReference (ObjDesc); 2853446Smrj goto UnlockAndExit; 2863446Smrj } 2873446Smrj 2883446Smrj /* Special case for ACPI Global Lock */ 2893446Smrj 2903446Smrj if (ACPI_STRCMP (InitVal->Name, "_GL_") == 0) 2913446Smrj { 2927851SDana.Myers@Sun.COM AcpiGbl_GlobalLockMutex = ObjDesc; 2933446Smrj 2943446Smrj /* Create additional counting semaphore for global lock */ 2953446Smrj 2963446Smrj Status = AcpiOsCreateSemaphore ( 2977851SDana.Myers@Sun.COM 1, 0, &AcpiGbl_GlobalLockSemaphore); 2983446Smrj if (ACPI_FAILURE (Status)) 2993446Smrj { 3003446Smrj AcpiUtRemoveReference (ObjDesc); 3013446Smrj goto UnlockAndExit; 3023446Smrj } 3033446Smrj } 3043446Smrj break; 3053446Smrj 3063446Smrj 3073446Smrj default: 3083446Smrj 3093446Smrj ACPI_ERROR ((AE_INFO, "Unsupported initial type value %X", 3103446Smrj InitVal->Type)); 3113446Smrj AcpiUtRemoveReference (ObjDesc); 3123446Smrj ObjDesc = NULL; 3133446Smrj continue; 3143446Smrj } 3153446Smrj 3163446Smrj /* Store pointer to value descriptor in the Node */ 3173446Smrj 3183446Smrj Status = AcpiNsAttachObject (NewNode, ObjDesc, 319*9980SDana.Myers@Sun.COM ObjDesc->Common.Type); 3203446Smrj 3213446Smrj /* Remove local reference to the object */ 3223446Smrj 3233446Smrj AcpiUtRemoveReference (ObjDesc); 3243446Smrj } 3253446Smrj } 3263446Smrj 3273446Smrj 3283446Smrj UnlockAndExit: 3293446Smrj (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 3303446Smrj 3313446Smrj /* Save a handle to "_GPE", it is always present */ 3323446Smrj 3333446Smrj if (ACPI_SUCCESS (Status)) 3343446Smrj { 3353446Smrj Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, 3363446Smrj &AcpiGbl_FadtGpeDevice); 3373446Smrj } 3383446Smrj 3393446Smrj return_ACPI_STATUS (Status); 3403446Smrj } 3413446Smrj 3423446Smrj 3433446Smrj /******************************************************************************* 3443446Smrj * 3453446Smrj * FUNCTION: AcpiNsLookup 3463446Smrj * 3473446Smrj * PARAMETERS: ScopeInfo - Current scope info block 3483446Smrj * Pathname - Search pathname, in internal format 3493446Smrj * (as represented in the AML stream) 3503446Smrj * Type - Type associated with name 3513446Smrj * InterpreterMode - IMODE_LOAD_PASS2 => add name if not found 3523446Smrj * Flags - Flags describing the search restrictions 3533446Smrj * WalkState - Current state of the walk 3543446Smrj * ReturnNode - Where the Node is placed (if found 3553446Smrj * or created successfully) 3563446Smrj * 3573446Smrj * RETURN: Status 3583446Smrj * 3593446Smrj * DESCRIPTION: Find or enter the passed name in the name space. 3603446Smrj * Log an error if name not found in Exec mode. 3613446Smrj * 3623446Smrj * MUTEX: Assumes namespace is locked. 3633446Smrj * 3643446Smrj ******************************************************************************/ 3653446Smrj 3663446Smrj ACPI_STATUS 3673446Smrj AcpiNsLookup ( 3683446Smrj ACPI_GENERIC_STATE *ScopeInfo, 3693446Smrj char *Pathname, 3703446Smrj ACPI_OBJECT_TYPE Type, 3713446Smrj ACPI_INTERPRETER_MODE InterpreterMode, 3723446Smrj UINT32 Flags, 3733446Smrj ACPI_WALK_STATE *WalkState, 3743446Smrj ACPI_NAMESPACE_NODE **ReturnNode) 3753446Smrj { 3763446Smrj ACPI_STATUS Status; 3773446Smrj char *Path = Pathname; 3783446Smrj ACPI_NAMESPACE_NODE *PrefixNode; 3793446Smrj ACPI_NAMESPACE_NODE *CurrentNode = NULL; 3803446Smrj ACPI_NAMESPACE_NODE *ThisNode = NULL; 3813446Smrj UINT32 NumSegments; 3823446Smrj UINT32 NumCarats; 3833446Smrj ACPI_NAME SimpleName; 3843446Smrj ACPI_OBJECT_TYPE TypeToCheckFor; 3853446Smrj ACPI_OBJECT_TYPE ThisSearchType; 3863446Smrj UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT; 3873446Smrj UINT32 LocalFlags; 3883446Smrj 3893446Smrj 3903446Smrj ACPI_FUNCTION_TRACE (NsLookup); 3913446Smrj 3923446Smrj 3933446Smrj if (!ReturnNode) 3943446Smrj { 3953446Smrj return_ACPI_STATUS (AE_BAD_PARAMETER); 3963446Smrj } 3973446Smrj 3983446Smrj LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); 3993446Smrj *ReturnNode = ACPI_ENTRY_NOT_FOUND; 4003446Smrj AcpiGbl_NsLookupCount++; 4013446Smrj 4023446Smrj if (!AcpiGbl_RootNode) 4033446Smrj { 4043446Smrj return_ACPI_STATUS (AE_NO_NAMESPACE); 4053446Smrj } 4063446Smrj 407*9980SDana.Myers@Sun.COM /* Get the prefix scope. A null scope means use the root scope */ 408*9980SDana.Myers@Sun.COM 4093446Smrj if ((!ScopeInfo) || 4103446Smrj (!ScopeInfo->Scope.Node)) 4113446Smrj { 4123446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 4133446Smrj "Null scope prefix, using root node (%p)\n", 4143446Smrj AcpiGbl_RootNode)); 4153446Smrj 4163446Smrj PrefixNode = AcpiGbl_RootNode; 4173446Smrj } 4183446Smrj else 4193446Smrj { 4203446Smrj PrefixNode = ScopeInfo->Scope.Node; 4213446Smrj if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED) 4223446Smrj { 4233446Smrj ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]", 4243446Smrj PrefixNode, AcpiUtGetDescriptorName (PrefixNode))); 4253446Smrj return_ACPI_STATUS (AE_AML_INTERNAL); 4263446Smrj } 4273446Smrj 4283446Smrj if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE)) 4293446Smrj { 4303446Smrj /* 4313446Smrj * This node might not be a actual "scope" node (such as a 432*9980SDana.Myers@Sun.COM * Device/Method, etc.) It could be a Package or other object 433*9980SDana.Myers@Sun.COM * node. Backup up the tree to find the containing scope node. 4343446Smrj */ 4353446Smrj while (!AcpiNsOpensScope (PrefixNode->Type) && 4363446Smrj PrefixNode->Type != ACPI_TYPE_ANY) 4373446Smrj { 4383446Smrj PrefixNode = AcpiNsGetParentNode (PrefixNode); 4393446Smrj } 4403446Smrj } 4413446Smrj } 4423446Smrj 443*9980SDana.Myers@Sun.COM /* Save type. TBD: may be no longer necessary */ 4443446Smrj 4453446Smrj TypeToCheckFor = Type; 4463446Smrj 4473446Smrj /* 4483446Smrj * Begin examination of the actual pathname 4493446Smrj */ 4503446Smrj if (!Pathname) 4513446Smrj { 4523446Smrj /* A Null NamePath is allowed and refers to the root */ 4533446Smrj 4543446Smrj NumSegments = 0; 4553446Smrj ThisNode = AcpiGbl_RootNode; 4563446Smrj Path = ""; 4573446Smrj 4583446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 4593446Smrj "Null Pathname (Zero segments), Flags=%X\n", Flags)); 4603446Smrj } 4613446Smrj else 4623446Smrj { 4633446Smrj /* 4643446Smrj * Name pointer is valid (and must be in internal name format) 4653446Smrj * 4663446Smrj * Check for scope prefixes: 4673446Smrj * 4683446Smrj * As represented in the AML stream, a namepath consists of an 4693446Smrj * optional scope prefix followed by a name segment part. 4703446Smrj * 4713446Smrj * If present, the scope prefix is either a Root Prefix (in 4723446Smrj * which case the name is fully qualified), or one or more 4733446Smrj * Parent Prefixes (in which case the name's scope is relative 4743446Smrj * to the current scope). 4753446Smrj */ 4763446Smrj if (*Path == (UINT8) AML_ROOT_PREFIX) 4773446Smrj { 4783446Smrj /* Pathname is fully qualified, start from the root */ 4793446Smrj 4803446Smrj ThisNode = AcpiGbl_RootNode; 4813446Smrj SearchParentFlag = ACPI_NS_NO_UPSEARCH; 4823446Smrj 4833446Smrj /* Point to name segment part */ 4843446Smrj 4853446Smrj Path++; 4863446Smrj 4873446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 4883446Smrj "Path is absolute from root [%p]\n", ThisNode)); 4893446Smrj } 4903446Smrj else 4913446Smrj { 4923446Smrj /* Pathname is relative to current scope, start there */ 4933446Smrj 4943446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 4953446Smrj "Searching relative to prefix scope [%4.4s] (%p)\n", 4963446Smrj AcpiUtGetNodeName (PrefixNode), PrefixNode)); 4973446Smrj 4983446Smrj /* 4993446Smrj * Handle multiple Parent Prefixes (carat) by just getting 5003446Smrj * the parent node for each prefix instance. 5013446Smrj */ 5023446Smrj ThisNode = PrefixNode; 5033446Smrj NumCarats = 0; 5043446Smrj while (*Path == (UINT8) AML_PARENT_PREFIX) 5053446Smrj { 5063446Smrj /* Name is fully qualified, no search rules apply */ 5073446Smrj 5083446Smrj SearchParentFlag = ACPI_NS_NO_UPSEARCH; 509*9980SDana.Myers@Sun.COM 5103446Smrj /* 5113446Smrj * Point past this prefix to the name segment 5123446Smrj * part or the next Parent Prefix 5133446Smrj */ 5143446Smrj Path++; 5153446Smrj 5163446Smrj /* Backup to the parent node */ 5173446Smrj 5183446Smrj NumCarats++; 5193446Smrj ThisNode = AcpiNsGetParentNode (ThisNode); 5203446Smrj if (!ThisNode) 5213446Smrj { 5223446Smrj /* Current scope has no parent scope */ 5233446Smrj 5243446Smrj ACPI_ERROR ((AE_INFO, 525*9980SDana.Myers@Sun.COM "ACPI path has too many parent prefixes (^) " 526*9980SDana.Myers@Sun.COM "- reached beyond root node")); 5273446Smrj return_ACPI_STATUS (AE_NOT_FOUND); 5283446Smrj } 5293446Smrj } 5303446Smrj 5313446Smrj if (SearchParentFlag == ACPI_NS_NO_UPSEARCH) 5323446Smrj { 5333446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 5343446Smrj "Search scope is [%4.4s], path has %d carat(s)\n", 5353446Smrj AcpiUtGetNodeName (ThisNode), NumCarats)); 5363446Smrj } 5373446Smrj } 5383446Smrj 5393446Smrj /* 5403446Smrj * Determine the number of ACPI name segments in this pathname. 5413446Smrj * 5423446Smrj * The segment part consists of either: 5433446Smrj * - A Null name segment (0) 5443446Smrj * - A DualNamePrefix followed by two 4-byte name segments 5453446Smrj * - A MultiNamePrefix followed by a byte indicating the 5463446Smrj * number of segments and the segments themselves. 5473446Smrj * - A single 4-byte name segment 5483446Smrj * 5493446Smrj * Examine the name prefix opcode, if any, to determine the number of 5503446Smrj * segments. 5513446Smrj */ 5523446Smrj switch (*Path) 5533446Smrj { 5543446Smrj case 0: 5553446Smrj /* 5563446Smrj * Null name after a root or parent prefixes. We already 5573446Smrj * have the correct target node and there are no name segments. 5583446Smrj */ 5593446Smrj NumSegments = 0; 5603446Smrj Type = ThisNode->Type; 5613446Smrj 5623446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 5633446Smrj "Prefix-only Pathname (Zero name segments), Flags=%X\n", 5643446Smrj Flags)); 5653446Smrj break; 5663446Smrj 5673446Smrj case AML_DUAL_NAME_PREFIX: 5683446Smrj 5693446Smrj /* More than one NameSeg, search rules do not apply */ 5703446Smrj 5713446Smrj SearchParentFlag = ACPI_NS_NO_UPSEARCH; 5723446Smrj 5733446Smrj /* Two segments, point to first name segment */ 5743446Smrj 5753446Smrj NumSegments = 2; 5763446Smrj Path++; 5773446Smrj 5783446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 5793446Smrj "Dual Pathname (2 segments, Flags=%X)\n", Flags)); 5803446Smrj break; 5813446Smrj 5823446Smrj case AML_MULTI_NAME_PREFIX_OP: 5833446Smrj 5843446Smrj /* More than one NameSeg, search rules do not apply */ 5853446Smrj 5863446Smrj SearchParentFlag = ACPI_NS_NO_UPSEARCH; 5873446Smrj 5883446Smrj /* Extract segment count, point to first name segment */ 5893446Smrj 5903446Smrj Path++; 5913446Smrj NumSegments = (UINT32) (UINT8) *Path; 5923446Smrj Path++; 5933446Smrj 5943446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 5953446Smrj "Multi Pathname (%d Segments, Flags=%X)\n", 5963446Smrj NumSegments, Flags)); 5973446Smrj break; 5983446Smrj 5993446Smrj default: 6003446Smrj /* 6013446Smrj * Not a Null name, no Dual or Multi prefix, hence there is 6023446Smrj * only one name segment and Pathname is already pointing to it. 6033446Smrj */ 6043446Smrj NumSegments = 1; 6053446Smrj 6063446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 6073446Smrj "Simple Pathname (1 segment, Flags=%X)\n", Flags)); 6083446Smrj break; 6093446Smrj } 6103446Smrj 6113446Smrj ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path)); 6123446Smrj } 6133446Smrj 6143446Smrj 6153446Smrj /* 616*9980SDana.Myers@Sun.COM * Search namespace for each segment of the name. Loop through and 6173446Smrj * verify (or add to the namespace) each name segment. 6183446Smrj * 6193446Smrj * The object type is significant only at the last name 620*9980SDana.Myers@Sun.COM * segment. (We don't care about the types along the path, only 6213446Smrj * the type of the final target object.) 6223446Smrj */ 6233446Smrj ThisSearchType = ACPI_TYPE_ANY; 6243446Smrj CurrentNode = ThisNode; 6253446Smrj while (NumSegments && CurrentNode) 6263446Smrj { 6273446Smrj NumSegments--; 6283446Smrj if (!NumSegments) 6293446Smrj { 630*9980SDana.Myers@Sun.COM /* This is the last segment, enable typechecking */ 631*9980SDana.Myers@Sun.COM 6323446Smrj ThisSearchType = Type; 6333446Smrj 6343446Smrj /* 6353446Smrj * Only allow automatic parent search (search rules) if the caller 6363446Smrj * requested it AND we have a single, non-fully-qualified NameSeg 6373446Smrj */ 6383446Smrj if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) && 6393446Smrj (Flags & ACPI_NS_SEARCH_PARENT)) 6403446Smrj { 6413446Smrj LocalFlags |= ACPI_NS_SEARCH_PARENT; 6423446Smrj } 6433446Smrj 6443446Smrj /* Set error flag according to caller */ 6453446Smrj 6463446Smrj if (Flags & ACPI_NS_ERROR_IF_FOUND) 6473446Smrj { 6483446Smrj LocalFlags |= ACPI_NS_ERROR_IF_FOUND; 6493446Smrj } 6503446Smrj } 6513446Smrj 6523446Smrj /* Extract one ACPI name from the front of the pathname */ 6533446Smrj 6543446Smrj ACPI_MOVE_32_TO_32 (&SimpleName, Path); 6553446Smrj 6563446Smrj /* Try to find the single (4 character) ACPI name */ 6573446Smrj 6583446Smrj Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode, 6593446Smrj InterpreterMode, ThisSearchType, LocalFlags, &ThisNode); 6603446Smrj if (ACPI_FAILURE (Status)) 6613446Smrj { 6623446Smrj if (Status == AE_NOT_FOUND) 6633446Smrj { 6643446Smrj /* Name not found in ACPI namespace */ 6653446Smrj 6663446Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 6673446Smrj "Name [%4.4s] not found in scope [%4.4s] %p\n", 6683446Smrj (char *) &SimpleName, (char *) &CurrentNode->Name, 6693446Smrj CurrentNode)); 6703446Smrj } 6713446Smrj 6723446Smrj *ReturnNode = ThisNode; 6733446Smrj return_ACPI_STATUS (Status); 6743446Smrj } 6753446Smrj 6767851SDana.Myers@Sun.COM /* More segments to follow? */ 6777851SDana.Myers@Sun.COM 6787851SDana.Myers@Sun.COM if (NumSegments > 0) 6793446Smrj { 6807851SDana.Myers@Sun.COM /* 6817851SDana.Myers@Sun.COM * If we have an alias to an object that opens a scope (such as a 682*9980SDana.Myers@Sun.COM * device or processor), we need to dereference the alias here so 683*9980SDana.Myers@Sun.COM * that we can access any children of the original node (via the 684*9980SDana.Myers@Sun.COM * remaining segments). 6857851SDana.Myers@Sun.COM */ 6867851SDana.Myers@Sun.COM if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS) 6877851SDana.Myers@Sun.COM { 688*9980SDana.Myers@Sun.COM if (!ThisNode->Object) 689*9980SDana.Myers@Sun.COM { 690*9980SDana.Myers@Sun.COM return_ACPI_STATUS (AE_NOT_EXIST); 691*9980SDana.Myers@Sun.COM } 692*9980SDana.Myers@Sun.COM 693*9980SDana.Myers@Sun.COM if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *) 694*9980SDana.Myers@Sun.COM ThisNode->Object)->Type)) 6957851SDana.Myers@Sun.COM { 6967851SDana.Myers@Sun.COM ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object; 6977851SDana.Myers@Sun.COM } 6987851SDana.Myers@Sun.COM } 6993446Smrj } 7003446Smrj 7017851SDana.Myers@Sun.COM /* Special handling for the last segment (NumSegments == 0) */ 7027851SDana.Myers@Sun.COM 7037851SDana.Myers@Sun.COM else 7043446Smrj { 7057851SDana.Myers@Sun.COM /* 7067851SDana.Myers@Sun.COM * Sanity typecheck of the target object: 7077851SDana.Myers@Sun.COM * 7087851SDana.Myers@Sun.COM * If 1) This is the last segment (NumSegments == 0) 7097851SDana.Myers@Sun.COM * 2) And we are looking for a specific type 7107851SDana.Myers@Sun.COM * (Not checking for TYPE_ANY) 7117851SDana.Myers@Sun.COM * 3) Which is not an alias 7127851SDana.Myers@Sun.COM * 4) Which is not a local type (TYPE_SCOPE) 7137851SDana.Myers@Sun.COM * 5) And the type of target object is known (not TYPE_ANY) 7147851SDana.Myers@Sun.COM * 6) And target object does not match what we are looking for 7157851SDana.Myers@Sun.COM * 7167851SDana.Myers@Sun.COM * Then we have a type mismatch. Just warn and ignore it. 7177851SDana.Myers@Sun.COM */ 7187851SDana.Myers@Sun.COM if ((TypeToCheckFor != ACPI_TYPE_ANY) && 7197851SDana.Myers@Sun.COM (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS) && 7207851SDana.Myers@Sun.COM (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS) && 7217851SDana.Myers@Sun.COM (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE) && 7227851SDana.Myers@Sun.COM (ThisNode->Type != ACPI_TYPE_ANY) && 7237851SDana.Myers@Sun.COM (ThisNode->Type != TypeToCheckFor)) 7247851SDana.Myers@Sun.COM { 7257851SDana.Myers@Sun.COM /* Complain about a type mismatch */ 7267851SDana.Myers@Sun.COM 7277851SDana.Myers@Sun.COM ACPI_WARNING ((AE_INFO, 7287851SDana.Myers@Sun.COM "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", 7297851SDana.Myers@Sun.COM ACPI_CAST_PTR (char, &SimpleName), 7307851SDana.Myers@Sun.COM AcpiUtGetTypeName (ThisNode->Type), 7317851SDana.Myers@Sun.COM AcpiUtGetTypeName (TypeToCheckFor))); 7327851SDana.Myers@Sun.COM } 7337851SDana.Myers@Sun.COM 7347851SDana.Myers@Sun.COM /* 7357851SDana.Myers@Sun.COM * If this is the last name segment and we are not looking for a 736*9980SDana.Myers@Sun.COM * specific type, but the type of found object is known, use that 737*9980SDana.Myers@Sun.COM * type to (later) see if it opens a scope. 7387851SDana.Myers@Sun.COM */ 7397851SDana.Myers@Sun.COM if (Type == ACPI_TYPE_ANY) 7407851SDana.Myers@Sun.COM { 7417851SDana.Myers@Sun.COM Type = ThisNode->Type; 7427851SDana.Myers@Sun.COM } 7433446Smrj } 7443446Smrj 7453446Smrj /* Point to next name segment and make this node current */ 7463446Smrj 7473446Smrj Path += ACPI_NAME_SIZE; 7483446Smrj CurrentNode = ThisNode; 7493446Smrj } 7503446Smrj 751*9980SDana.Myers@Sun.COM /* Always check if we need to open a new scope */ 752*9980SDana.Myers@Sun.COM 7533446Smrj if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState)) 7543446Smrj { 7553446Smrj /* 7563446Smrj * If entry is a type which opens a scope, push the new scope on the 7573446Smrj * scope stack. 7583446Smrj */ 7593446Smrj if (AcpiNsOpensScope (Type)) 7603446Smrj { 7613446Smrj Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState); 7623446Smrj if (ACPI_FAILURE (Status)) 7633446Smrj { 7643446Smrj return_ACPI_STATUS (Status); 7653446Smrj } 7663446Smrj } 7673446Smrj } 7683446Smrj 7693446Smrj *ReturnNode = ThisNode; 7703446Smrj return_ACPI_STATUS (AE_OK); 7713446Smrj } 7723446Smrj 773