xref: /titanic_41/usr/src/uts/intel/io/acpica/namespace/nsaccess.c (revision de5d74c22760a6d2cefd94d0e7f0fd87214fb71f)
1ae115bc7Smrj /*******************************************************************************
2ae115bc7Smrj  *
3ae115bc7Smrj  * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
4ae115bc7Smrj  *
5ae115bc7Smrj  ******************************************************************************/
6ae115bc7Smrj 
726f3cdf0SGordon Ross /*
8*de5d74c2SJerry 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 "amlcode.h"
47ae115bc7Smrj #include "acnamesp.h"
48ae115bc7Smrj #include "acdispat.h"
49ae115bc7Smrj 
50ae115bc7Smrj 
51ae115bc7Smrj #define _COMPONENT          ACPI_NAMESPACE
52ae115bc7Smrj         ACPI_MODULE_NAME    ("nsaccess")
53ae115bc7Smrj 
54ae115bc7Smrj 
55ae115bc7Smrj /*******************************************************************************
56ae115bc7Smrj  *
57ae115bc7Smrj  * FUNCTION:    AcpiNsRootInitialize
58ae115bc7Smrj  *
59ae115bc7Smrj  * PARAMETERS:  None
60ae115bc7Smrj  *
61ae115bc7Smrj  * RETURN:      Status
62ae115bc7Smrj  *
63ae115bc7Smrj  * DESCRIPTION: Allocate and initialize the default root named objects
64ae115bc7Smrj  *
65ae115bc7Smrj  * MUTEX:       Locks namespace for entire execution
66ae115bc7Smrj  *
67ae115bc7Smrj  ******************************************************************************/
68ae115bc7Smrj 
69ae115bc7Smrj ACPI_STATUS
AcpiNsRootInitialize(void)70ae115bc7Smrj AcpiNsRootInitialize (
71ae115bc7Smrj     void)
72ae115bc7Smrj {
73ae115bc7Smrj     ACPI_STATUS                 Status;
74ae115bc7Smrj     const ACPI_PREDEFINED_NAMES *InitVal = NULL;
75ae115bc7Smrj     ACPI_NAMESPACE_NODE         *NewNode;
76ae115bc7Smrj     ACPI_OPERAND_OBJECT         *ObjDesc;
77ae115bc7Smrj     ACPI_STRING                 Val = NULL;
78ae115bc7Smrj 
79ae115bc7Smrj 
80ae115bc7Smrj     ACPI_FUNCTION_TRACE (NsRootInitialize);
81ae115bc7Smrj 
82ae115bc7Smrj 
83ae115bc7Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
84ae115bc7Smrj     if (ACPI_FAILURE (Status))
85ae115bc7Smrj     {
86ae115bc7Smrj         return_ACPI_STATUS (Status);
87ae115bc7Smrj     }
88ae115bc7Smrj 
89ae115bc7Smrj     /*
90ae115bc7Smrj      * The global root ptr is initially NULL, so a non-NULL value indicates
91ae115bc7Smrj      * that AcpiNsRootInitialize() has already been called; just return.
92ae115bc7Smrj      */
93ae115bc7Smrj     if (AcpiGbl_RootNode)
94ae115bc7Smrj     {
95ae115bc7Smrj         Status = AE_OK;
96ae115bc7Smrj         goto UnlockAndExit;
97ae115bc7Smrj     }
98ae115bc7Smrj 
99ae115bc7Smrj     /*
100ae115bc7Smrj      * Tell the rest of the subsystem that the root is initialized
101ae115bc7Smrj      * (This is OK because the namespace is locked)
102ae115bc7Smrj      */
103ae115bc7Smrj     AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct;
104ae115bc7Smrj 
105ae115bc7Smrj     /* Enter the pre-defined names in the name table */
106ae115bc7Smrj 
107ae115bc7Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
108ae115bc7Smrj         "Entering predefined entries into namespace\n"));
109ae115bc7Smrj 
110ae115bc7Smrj     for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++)
111ae115bc7Smrj     {
112ae115bc7Smrj         /* _OSI is optional for now, will be permanent later */
113ae115bc7Smrj 
114*de5d74c2SJerry Jelinek         if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod)
115ae115bc7Smrj         {
116ae115bc7Smrj             continue;
117ae115bc7Smrj         }
118ae115bc7Smrj 
119*de5d74c2SJerry Jelinek         Status = AcpiNsLookup (NULL, ACPI_CAST_PTR (char, InitVal->Name),
120*de5d74c2SJerry Jelinek             InitVal->Type, ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
121ae115bc7Smrj             NULL, &NewNode);
122*de5d74c2SJerry Jelinek         if (ACPI_FAILURE (Status))
123ae115bc7Smrj         {
124ae115bc7Smrj             ACPI_EXCEPTION ((AE_INFO, Status,
125ae115bc7Smrj                 "Could not create predefined name %s",
126ae115bc7Smrj                 InitVal->Name));
127*de5d74c2SJerry Jelinek             continue;
128ae115bc7Smrj         }
129ae115bc7Smrj 
130ae115bc7Smrj         /*
131aa2aa9a6SDana Myers          * Name entered successfully. If entry in PreDefinedNames[] specifies
132aa2aa9a6SDana Myers          * an initial value, create the initial value.
133ae115bc7Smrj          */
134ae115bc7Smrj         if (InitVal->Val)
135ae115bc7Smrj         {
136ae115bc7Smrj             Status = AcpiOsPredefinedOverride (InitVal, &Val);
137ae115bc7Smrj             if (ACPI_FAILURE (Status))
138ae115bc7Smrj             {
139ae115bc7Smrj                 ACPI_ERROR ((AE_INFO,
140ae115bc7Smrj                     "Could not override predefined %s",
141ae115bc7Smrj                     InitVal->Name));
142ae115bc7Smrj             }
143ae115bc7Smrj 
144ae115bc7Smrj             if (!Val)
145ae115bc7Smrj             {
146ae115bc7Smrj                 Val = InitVal->Val;
147ae115bc7Smrj             }
148ae115bc7Smrj 
149ae115bc7Smrj             /*
150ae115bc7Smrj              * Entry requests an initial value, allocate a
151ae115bc7Smrj              * descriptor for it.
152ae115bc7Smrj              */
153ae115bc7Smrj             ObjDesc = AcpiUtCreateInternalObject (InitVal->Type);
154ae115bc7Smrj             if (!ObjDesc)
155ae115bc7Smrj             {
156ae115bc7Smrj                 Status = AE_NO_MEMORY;
157ae115bc7Smrj                 goto UnlockAndExit;
158ae115bc7Smrj             }
159ae115bc7Smrj 
160ae115bc7Smrj             /*
161ae115bc7Smrj              * Convert value string from table entry to
162ae115bc7Smrj              * internal representation. Only types actually
163ae115bc7Smrj              * used for initial values are implemented here.
164ae115bc7Smrj              */
165ae115bc7Smrj             switch (InitVal->Type)
166ae115bc7Smrj             {
167ae115bc7Smrj             case ACPI_TYPE_METHOD:
168*de5d74c2SJerry Jelinek 
169ae115bc7Smrj                 ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val);
170ae115bc7Smrj                 ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
171ae115bc7Smrj 
172ae115bc7Smrj #if defined (ACPI_ASL_COMPILER)
173ae115bc7Smrj 
174ae115bc7Smrj                 /* Save the parameter count for the iASL compiler */
175ae115bc7Smrj 
176ae115bc7Smrj                 NewNode->Value = ObjDesc->Method.ParamCount;
177ae115bc7Smrj #else
178ae115bc7Smrj                 /* Mark this as a very SPECIAL method */
179ae115bc7Smrj 
18026f3cdf0SGordon Ross                 ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY;
18126f3cdf0SGordon Ross                 ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation;
182ae115bc7Smrj #endif
183ae115bc7Smrj                 break;
184ae115bc7Smrj 
185ae115bc7Smrj             case ACPI_TYPE_INTEGER:
186ae115bc7Smrj 
187ae115bc7Smrj                 ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val);
188ae115bc7Smrj                 break;
189ae115bc7Smrj 
190ae115bc7Smrj             case ACPI_TYPE_STRING:
191ae115bc7Smrj 
192aa2aa9a6SDana Myers                 /* Build an object around the static string */
193aa2aa9a6SDana Myers 
194*de5d74c2SJerry Jelinek                 ObjDesc->String.Length = (UINT32) strlen (Val);
195ae115bc7Smrj                 ObjDesc->String.Pointer = Val;
196ae115bc7Smrj                 ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
197ae115bc7Smrj                 break;
198ae115bc7Smrj 
199ae115bc7Smrj             case ACPI_TYPE_MUTEX:
200ae115bc7Smrj 
201ae115bc7Smrj                 ObjDesc->Mutex.Node = NewNode;
202ae115bc7Smrj                 ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1);
203ae115bc7Smrj 
204ae115bc7Smrj                 /* Create a mutex */
205ae115bc7Smrj 
206ae115bc7Smrj                 Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex);
207ae115bc7Smrj                 if (ACPI_FAILURE (Status))
208ae115bc7Smrj                 {
209ae115bc7Smrj                     AcpiUtRemoveReference (ObjDesc);
210ae115bc7Smrj                     goto UnlockAndExit;
211ae115bc7Smrj                 }
212ae115bc7Smrj 
213ae115bc7Smrj                 /* Special case for ACPI Global Lock */
214ae115bc7Smrj 
215*de5d74c2SJerry Jelinek                 if (strcmp (InitVal->Name, "_GL_") == 0)
216ae115bc7Smrj                 {
217db2bae30SDana Myers                     AcpiGbl_GlobalLockMutex = ObjDesc;
218ae115bc7Smrj 
219ae115bc7Smrj                     /* Create additional counting semaphore for global lock */
220ae115bc7Smrj 
221ae115bc7Smrj                     Status = AcpiOsCreateSemaphore (
222db2bae30SDana Myers                         1, 0, &AcpiGbl_GlobalLockSemaphore);
223ae115bc7Smrj                     if (ACPI_FAILURE (Status))
224ae115bc7Smrj                     {
225ae115bc7Smrj                         AcpiUtRemoveReference (ObjDesc);
226ae115bc7Smrj                         goto UnlockAndExit;
227ae115bc7Smrj                     }
228ae115bc7Smrj                 }
229ae115bc7Smrj                 break;
230ae115bc7Smrj 
231ae115bc7Smrj             default:
232ae115bc7Smrj 
23326f3cdf0SGordon Ross                 ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X",
234ae115bc7Smrj                     InitVal->Type));
235ae115bc7Smrj                 AcpiUtRemoveReference (ObjDesc);
236ae115bc7Smrj                 ObjDesc = NULL;
237ae115bc7Smrj                 continue;
238ae115bc7Smrj             }
239ae115bc7Smrj 
240ae115bc7Smrj             /* Store pointer to value descriptor in the Node */
241ae115bc7Smrj 
242ae115bc7Smrj             Status = AcpiNsAttachObject (NewNode, ObjDesc,
243aa2aa9a6SDana Myers                 ObjDesc->Common.Type);
244ae115bc7Smrj 
245ae115bc7Smrj             /* Remove local reference to the object */
246ae115bc7Smrj 
247ae115bc7Smrj             AcpiUtRemoveReference (ObjDesc);
248ae115bc7Smrj         }
249ae115bc7Smrj     }
250ae115bc7Smrj 
251ae115bc7Smrj 
252ae115bc7Smrj UnlockAndExit:
253ae115bc7Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
254ae115bc7Smrj 
255ae115bc7Smrj     /* Save a handle to "_GPE", it is always present */
256ae115bc7Smrj 
257ae115bc7Smrj     if (ACPI_SUCCESS (Status))
258ae115bc7Smrj     {
259ae115bc7Smrj         Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
260ae115bc7Smrj             &AcpiGbl_FadtGpeDevice);
261ae115bc7Smrj     }
262ae115bc7Smrj 
263ae115bc7Smrj     return_ACPI_STATUS (Status);
264ae115bc7Smrj }
265ae115bc7Smrj 
266ae115bc7Smrj 
267ae115bc7Smrj /*******************************************************************************
268ae115bc7Smrj  *
269ae115bc7Smrj  * FUNCTION:    AcpiNsLookup
270ae115bc7Smrj  *
271ae115bc7Smrj  * PARAMETERS:  ScopeInfo       - Current scope info block
272ae115bc7Smrj  *              Pathname        - Search pathname, in internal format
273ae115bc7Smrj  *                                (as represented in the AML stream)
274ae115bc7Smrj  *              Type            - Type associated with name
275ae115bc7Smrj  *              InterpreterMode - IMODE_LOAD_PASS2 => add name if not found
276ae115bc7Smrj  *              Flags           - Flags describing the search restrictions
277ae115bc7Smrj  *              WalkState       - Current state of the walk
278ae115bc7Smrj  *              ReturnNode      - Where the Node is placed (if found
279ae115bc7Smrj  *                                or created successfully)
280ae115bc7Smrj  *
281ae115bc7Smrj  * RETURN:      Status
282ae115bc7Smrj  *
283ae115bc7Smrj  * DESCRIPTION: Find or enter the passed name in the name space.
284ae115bc7Smrj  *              Log an error if name not found in Exec mode.
285ae115bc7Smrj  *
286ae115bc7Smrj  * MUTEX:       Assumes namespace is locked.
287ae115bc7Smrj  *
288ae115bc7Smrj  ******************************************************************************/
289ae115bc7Smrj 
290ae115bc7Smrj ACPI_STATUS
AcpiNsLookup(ACPI_GENERIC_STATE * ScopeInfo,char * Pathname,ACPI_OBJECT_TYPE Type,ACPI_INTERPRETER_MODE InterpreterMode,UINT32 Flags,ACPI_WALK_STATE * WalkState,ACPI_NAMESPACE_NODE ** ReturnNode)291ae115bc7Smrj AcpiNsLookup (
292ae115bc7Smrj     ACPI_GENERIC_STATE      *ScopeInfo,
293ae115bc7Smrj     char                    *Pathname,
294ae115bc7Smrj     ACPI_OBJECT_TYPE        Type,
295ae115bc7Smrj     ACPI_INTERPRETER_MODE   InterpreterMode,
296ae115bc7Smrj     UINT32                  Flags,
297ae115bc7Smrj     ACPI_WALK_STATE         *WalkState,
298ae115bc7Smrj     ACPI_NAMESPACE_NODE     **ReturnNode)
299ae115bc7Smrj {
300ae115bc7Smrj     ACPI_STATUS             Status;
301ae115bc7Smrj     char                    *Path = Pathname;
302ae115bc7Smrj     ACPI_NAMESPACE_NODE     *PrefixNode;
303ae115bc7Smrj     ACPI_NAMESPACE_NODE     *CurrentNode = NULL;
304ae115bc7Smrj     ACPI_NAMESPACE_NODE     *ThisNode = NULL;
305ae115bc7Smrj     UINT32                  NumSegments;
306ae115bc7Smrj     UINT32                  NumCarats;
307ae115bc7Smrj     ACPI_NAME               SimpleName;
308ae115bc7Smrj     ACPI_OBJECT_TYPE        TypeToCheckFor;
309ae115bc7Smrj     ACPI_OBJECT_TYPE        ThisSearchType;
310ae115bc7Smrj     UINT32                  SearchParentFlag = ACPI_NS_SEARCH_PARENT;
311ae115bc7Smrj     UINT32                  LocalFlags;
312ae115bc7Smrj 
313ae115bc7Smrj 
314ae115bc7Smrj     ACPI_FUNCTION_TRACE (NsLookup);
315ae115bc7Smrj 
316ae115bc7Smrj 
317ae115bc7Smrj     if (!ReturnNode)
318ae115bc7Smrj     {
319ae115bc7Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
320ae115bc7Smrj     }
321ae115bc7Smrj 
322*de5d74c2SJerry Jelinek     LocalFlags = Flags &
323*de5d74c2SJerry Jelinek         ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND |
324*de5d74c2SJerry Jelinek           ACPI_NS_SEARCH_PARENT);
325ae115bc7Smrj     *ReturnNode = ACPI_ENTRY_NOT_FOUND;
326ae115bc7Smrj     AcpiGbl_NsLookupCount++;
327ae115bc7Smrj 
328ae115bc7Smrj     if (!AcpiGbl_RootNode)
329ae115bc7Smrj     {
330ae115bc7Smrj         return_ACPI_STATUS (AE_NO_NAMESPACE);
331ae115bc7Smrj     }
332ae115bc7Smrj 
333aa2aa9a6SDana Myers     /* Get the prefix scope. A null scope means use the root scope */
334aa2aa9a6SDana Myers 
335ae115bc7Smrj     if ((!ScopeInfo) ||
336ae115bc7Smrj         (!ScopeInfo->Scope.Node))
337ae115bc7Smrj     {
338ae115bc7Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
339ae115bc7Smrj             "Null scope prefix, using root node (%p)\n",
340ae115bc7Smrj             AcpiGbl_RootNode));
341ae115bc7Smrj 
342ae115bc7Smrj         PrefixNode = AcpiGbl_RootNode;
343ae115bc7Smrj     }
344ae115bc7Smrj     else
345ae115bc7Smrj     {
346ae115bc7Smrj         PrefixNode = ScopeInfo->Scope.Node;
347ae115bc7Smrj         if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED)
348ae115bc7Smrj         {
349ae115bc7Smrj             ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]",
350ae115bc7Smrj                 PrefixNode, AcpiUtGetDescriptorName (PrefixNode)));
351ae115bc7Smrj             return_ACPI_STATUS (AE_AML_INTERNAL);
352ae115bc7Smrj         }
353ae115bc7Smrj 
354ae115bc7Smrj         if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE))
355ae115bc7Smrj         {
356ae115bc7Smrj             /*
357ae115bc7Smrj              * This node might not be a actual "scope" node (such as a
358aa2aa9a6SDana Myers              * Device/Method, etc.)  It could be a Package or other object
359aa2aa9a6SDana Myers              * node. Backup up the tree to find the containing scope node.
360ae115bc7Smrj              */
361ae115bc7Smrj             while (!AcpiNsOpensScope (PrefixNode->Type) &&
362ae115bc7Smrj                     PrefixNode->Type != ACPI_TYPE_ANY)
363ae115bc7Smrj             {
36426f3cdf0SGordon Ross                 PrefixNode = PrefixNode->Parent;
365ae115bc7Smrj             }
366ae115bc7Smrj         }
367ae115bc7Smrj     }
368ae115bc7Smrj 
369aa2aa9a6SDana Myers     /* Save type. TBD: may be no longer necessary */
370ae115bc7Smrj 
371ae115bc7Smrj     TypeToCheckFor = Type;
372ae115bc7Smrj 
373ae115bc7Smrj     /*
374ae115bc7Smrj      * Begin examination of the actual pathname
375ae115bc7Smrj      */
376ae115bc7Smrj     if (!Pathname)
377ae115bc7Smrj     {
378ae115bc7Smrj         /* A Null NamePath is allowed and refers to the root */
379ae115bc7Smrj 
380ae115bc7Smrj         NumSegments = 0;
381ae115bc7Smrj         ThisNode = AcpiGbl_RootNode;
382ae115bc7Smrj         Path = "";
383ae115bc7Smrj 
384ae115bc7Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
385ae115bc7Smrj             "Null Pathname (Zero segments), Flags=%X\n", Flags));
386ae115bc7Smrj     }
387ae115bc7Smrj     else
388ae115bc7Smrj     {
389ae115bc7Smrj         /*
390ae115bc7Smrj          * Name pointer is valid (and must be in internal name format)
391ae115bc7Smrj          *
392ae115bc7Smrj          * Check for scope prefixes:
393ae115bc7Smrj          *
394ae115bc7Smrj          * As represented in the AML stream, a namepath consists of an
395ae115bc7Smrj          * optional scope prefix followed by a name segment part.
396ae115bc7Smrj          *
397ae115bc7Smrj          * If present, the scope prefix is either a Root Prefix (in
398ae115bc7Smrj          * which case the name is fully qualified), or one or more
399ae115bc7Smrj          * Parent Prefixes (in which case the name's scope is relative
400ae115bc7Smrj          * to the current scope).
401ae115bc7Smrj          */
402ae115bc7Smrj         if (*Path == (UINT8) AML_ROOT_PREFIX)
403ae115bc7Smrj         {
404ae115bc7Smrj             /* Pathname is fully qualified, start from the root */
405ae115bc7Smrj 
406ae115bc7Smrj             ThisNode = AcpiGbl_RootNode;
407ae115bc7Smrj             SearchParentFlag = ACPI_NS_NO_UPSEARCH;
408ae115bc7Smrj 
409ae115bc7Smrj             /* Point to name segment part */
410ae115bc7Smrj 
411ae115bc7Smrj             Path++;
412ae115bc7Smrj 
413ae115bc7Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
414ae115bc7Smrj                 "Path is absolute from root [%p]\n", ThisNode));
415ae115bc7Smrj         }
416ae115bc7Smrj         else
417ae115bc7Smrj         {
418ae115bc7Smrj             /* Pathname is relative to current scope, start there */
419ae115bc7Smrj 
420ae115bc7Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
421ae115bc7Smrj                 "Searching relative to prefix scope [%4.4s] (%p)\n",
422ae115bc7Smrj                 AcpiUtGetNodeName (PrefixNode), PrefixNode));
423ae115bc7Smrj 
424ae115bc7Smrj             /*
425ae115bc7Smrj              * Handle multiple Parent Prefixes (carat) by just getting
426ae115bc7Smrj              * the parent node for each prefix instance.
427ae115bc7Smrj              */
428ae115bc7Smrj             ThisNode = PrefixNode;
429ae115bc7Smrj             NumCarats = 0;
430ae115bc7Smrj             while (*Path == (UINT8) AML_PARENT_PREFIX)
431ae115bc7Smrj             {
432ae115bc7Smrj                 /* Name is fully qualified, no search rules apply */
433ae115bc7Smrj 
434ae115bc7Smrj                 SearchParentFlag = ACPI_NS_NO_UPSEARCH;
435aa2aa9a6SDana Myers 
436ae115bc7Smrj                 /*
437ae115bc7Smrj                  * Point past this prefix to the name segment
438ae115bc7Smrj                  * part or the next Parent Prefix
439ae115bc7Smrj                  */
440ae115bc7Smrj                 Path++;
441ae115bc7Smrj 
442ae115bc7Smrj                 /* Backup to the parent node */
443ae115bc7Smrj 
444ae115bc7Smrj                 NumCarats++;
44526f3cdf0SGordon Ross                 ThisNode = ThisNode->Parent;
446ae115bc7Smrj                 if (!ThisNode)
447ae115bc7Smrj                 {
448ae115bc7Smrj                     /* Current scope has no parent scope */
449ae115bc7Smrj 
450ae115bc7Smrj                     ACPI_ERROR ((AE_INFO,
451*de5d74c2SJerry Jelinek                         "%s: Path has too many parent prefixes (^) "
452*de5d74c2SJerry Jelinek                         "- reached beyond root node", Pathname));
453ae115bc7Smrj                     return_ACPI_STATUS (AE_NOT_FOUND);
454ae115bc7Smrj                 }
455ae115bc7Smrj             }
456ae115bc7Smrj 
457ae115bc7Smrj             if (SearchParentFlag == ACPI_NS_NO_UPSEARCH)
458ae115bc7Smrj             {
459ae115bc7Smrj                 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
46026f3cdf0SGordon Ross                     "Search scope is [%4.4s], path has %u carat(s)\n",
461ae115bc7Smrj                     AcpiUtGetNodeName (ThisNode), NumCarats));
462ae115bc7Smrj             }
463ae115bc7Smrj         }
464ae115bc7Smrj 
465ae115bc7Smrj         /*
466ae115bc7Smrj          * Determine the number of ACPI name segments in this pathname.
467ae115bc7Smrj          *
468ae115bc7Smrj          * The segment part consists of either:
469ae115bc7Smrj          *  - A Null name segment (0)
470ae115bc7Smrj          *  - A DualNamePrefix followed by two 4-byte name segments
471ae115bc7Smrj          *  - A MultiNamePrefix followed by a byte indicating the
472ae115bc7Smrj          *      number of segments and the segments themselves.
473ae115bc7Smrj          *  - A single 4-byte name segment
474ae115bc7Smrj          *
475ae115bc7Smrj          * Examine the name prefix opcode, if any, to determine the number of
476ae115bc7Smrj          * segments.
477ae115bc7Smrj          */
478ae115bc7Smrj         switch (*Path)
479ae115bc7Smrj         {
480ae115bc7Smrj         case 0:
481ae115bc7Smrj             /*
482ae115bc7Smrj              * Null name after a root or parent prefixes. We already
483ae115bc7Smrj              * have the correct target node and there are no name segments.
484ae115bc7Smrj              */
485ae115bc7Smrj             NumSegments  = 0;
486ae115bc7Smrj             Type = ThisNode->Type;
487ae115bc7Smrj 
488ae115bc7Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
489ae115bc7Smrj                 "Prefix-only Pathname (Zero name segments), Flags=%X\n",
490ae115bc7Smrj                 Flags));
491ae115bc7Smrj             break;
492ae115bc7Smrj 
493ae115bc7Smrj         case AML_DUAL_NAME_PREFIX:
494ae115bc7Smrj 
495ae115bc7Smrj             /* More than one NameSeg, search rules do not apply */
496ae115bc7Smrj 
497ae115bc7Smrj             SearchParentFlag = ACPI_NS_NO_UPSEARCH;
498ae115bc7Smrj 
499ae115bc7Smrj             /* Two segments, point to first name segment */
500ae115bc7Smrj 
501ae115bc7Smrj             NumSegments = 2;
502ae115bc7Smrj             Path++;
503ae115bc7Smrj 
504ae115bc7Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
505ae115bc7Smrj                 "Dual Pathname (2 segments, Flags=%X)\n", Flags));
506ae115bc7Smrj             break;
507ae115bc7Smrj 
508ae115bc7Smrj         case AML_MULTI_NAME_PREFIX_OP:
509ae115bc7Smrj 
510ae115bc7Smrj             /* More than one NameSeg, search rules do not apply */
511ae115bc7Smrj 
512ae115bc7Smrj             SearchParentFlag = ACPI_NS_NO_UPSEARCH;
513ae115bc7Smrj 
514ae115bc7Smrj             /* Extract segment count, point to first name segment */
515ae115bc7Smrj 
516ae115bc7Smrj             Path++;
517ae115bc7Smrj             NumSegments = (UINT32) (UINT8) *Path;
518ae115bc7Smrj             Path++;
519ae115bc7Smrj 
520ae115bc7Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
52126f3cdf0SGordon Ross                 "Multi Pathname (%u Segments, Flags=%X)\n",
522ae115bc7Smrj                 NumSegments, Flags));
523ae115bc7Smrj             break;
524ae115bc7Smrj 
525ae115bc7Smrj         default:
526ae115bc7Smrj             /*
527ae115bc7Smrj              * Not a Null name, no Dual or Multi prefix, hence there is
528ae115bc7Smrj              * only one name segment and Pathname is already pointing to it.
529ae115bc7Smrj              */
530ae115bc7Smrj             NumSegments = 1;
531ae115bc7Smrj 
532ae115bc7Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
533ae115bc7Smrj                 "Simple Pathname (1 segment, Flags=%X)\n", Flags));
534ae115bc7Smrj             break;
535ae115bc7Smrj         }
536ae115bc7Smrj 
537ae115bc7Smrj         ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path));
538ae115bc7Smrj     }
539ae115bc7Smrj 
540ae115bc7Smrj 
541ae115bc7Smrj     /*
542ae115bc7Smrj      * Search namespace for each segment of the name. Loop through and
543ae115bc7Smrj      * verify (or add to the namespace) each name segment.
544ae115bc7Smrj      *
545ae115bc7Smrj      * The object type is significant only at the last name
546ae115bc7Smrj      * segment. (We don't care about the types along the path, only
547ae115bc7Smrj      * the type of the final target object.)
548ae115bc7Smrj      */
549ae115bc7Smrj     ThisSearchType = ACPI_TYPE_ANY;
550ae115bc7Smrj     CurrentNode = ThisNode;
551ae115bc7Smrj     while (NumSegments && CurrentNode)
552ae115bc7Smrj     {
553ae115bc7Smrj         NumSegments--;
554ae115bc7Smrj         if (!NumSegments)
555ae115bc7Smrj         {
556aa2aa9a6SDana Myers             /* This is the last segment, enable typechecking */
557aa2aa9a6SDana Myers 
558ae115bc7Smrj             ThisSearchType = Type;
559ae115bc7Smrj 
560ae115bc7Smrj             /*
561ae115bc7Smrj              * Only allow automatic parent search (search rules) if the caller
562ae115bc7Smrj              * requested it AND we have a single, non-fully-qualified NameSeg
563ae115bc7Smrj              */
564ae115bc7Smrj             if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) &&
565ae115bc7Smrj                 (Flags & ACPI_NS_SEARCH_PARENT))
566ae115bc7Smrj             {
567ae115bc7Smrj                 LocalFlags |= ACPI_NS_SEARCH_PARENT;
568ae115bc7Smrj             }
569ae115bc7Smrj 
570ae115bc7Smrj             /* Set error flag according to caller */
571ae115bc7Smrj 
572ae115bc7Smrj             if (Flags & ACPI_NS_ERROR_IF_FOUND)
573ae115bc7Smrj             {
574ae115bc7Smrj                 LocalFlags |= ACPI_NS_ERROR_IF_FOUND;
575ae115bc7Smrj             }
576*de5d74c2SJerry Jelinek 
577*de5d74c2SJerry Jelinek             /* Set override flag according to caller */
578*de5d74c2SJerry Jelinek 
579*de5d74c2SJerry Jelinek             if (Flags & ACPI_NS_OVERRIDE_IF_FOUND)
580*de5d74c2SJerry Jelinek             {
581*de5d74c2SJerry Jelinek                 LocalFlags |= ACPI_NS_OVERRIDE_IF_FOUND;
582*de5d74c2SJerry Jelinek             }
583ae115bc7Smrj         }
584ae115bc7Smrj 
585ae115bc7Smrj         /* Extract one ACPI name from the front of the pathname */
586ae115bc7Smrj 
587ae115bc7Smrj         ACPI_MOVE_32_TO_32 (&SimpleName, Path);
588ae115bc7Smrj 
589ae115bc7Smrj         /* Try to find the single (4 character) ACPI name */
590ae115bc7Smrj 
591ae115bc7Smrj         Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode,
592ae115bc7Smrj             InterpreterMode, ThisSearchType, LocalFlags, &ThisNode);
593ae115bc7Smrj         if (ACPI_FAILURE (Status))
594ae115bc7Smrj         {
595ae115bc7Smrj             if (Status == AE_NOT_FOUND)
596ae115bc7Smrj             {
597ae115bc7Smrj                 /* Name not found in ACPI namespace */
598ae115bc7Smrj 
599ae115bc7Smrj                 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
600ae115bc7Smrj                     "Name [%4.4s] not found in scope [%4.4s] %p\n",
601ae115bc7Smrj                     (char *) &SimpleName, (char *) &CurrentNode->Name,
602ae115bc7Smrj                     CurrentNode));
603ae115bc7Smrj             }
604ae115bc7Smrj 
605ae115bc7Smrj             *ReturnNode = ThisNode;
606ae115bc7Smrj             return_ACPI_STATUS (Status);
607ae115bc7Smrj         }
608ae115bc7Smrj 
609db2bae30SDana Myers         /* More segments to follow? */
610db2bae30SDana Myers 
611db2bae30SDana Myers         if (NumSegments > 0)
612db2bae30SDana Myers         {
613db2bae30SDana Myers             /*
614db2bae30SDana Myers              * If we have an alias to an object that opens a scope (such as a
615aa2aa9a6SDana Myers              * device or processor), we need to dereference the alias here so
616aa2aa9a6SDana Myers              * that we can access any children of the original node (via the
617aa2aa9a6SDana Myers              * remaining segments).
618db2bae30SDana Myers              */
619db2bae30SDana Myers             if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS)
620db2bae30SDana Myers             {
621aa2aa9a6SDana Myers                 if (!ThisNode->Object)
622aa2aa9a6SDana Myers                 {
623aa2aa9a6SDana Myers                     return_ACPI_STATUS (AE_NOT_EXIST);
624aa2aa9a6SDana Myers                 }
625aa2aa9a6SDana Myers 
626aa2aa9a6SDana Myers                 if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *)
627aa2aa9a6SDana Myers                         ThisNode->Object)->Type))
628db2bae30SDana Myers                 {
629db2bae30SDana Myers                     ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object;
630db2bae30SDana Myers                 }
631db2bae30SDana Myers             }
632db2bae30SDana Myers         }
633db2bae30SDana Myers 
634db2bae30SDana Myers         /* Special handling for the last segment (NumSegments == 0) */
635db2bae30SDana Myers 
636db2bae30SDana Myers         else
637db2bae30SDana Myers         {
638ae115bc7Smrj             /*
639ae115bc7Smrj              * Sanity typecheck of the target object:
640ae115bc7Smrj              *
641ae115bc7Smrj              * If 1) This is the last segment (NumSegments == 0)
642ae115bc7Smrj              *    2) And we are looking for a specific type
643ae115bc7Smrj              *       (Not checking for TYPE_ANY)
644ae115bc7Smrj              *    3) Which is not an alias
645ae115bc7Smrj              *    4) Which is not a local type (TYPE_SCOPE)
646ae115bc7Smrj              *    5) And the type of target object is known (not TYPE_ANY)
647ae115bc7Smrj              *    6) And target object does not match what we are looking for
648ae115bc7Smrj              *
649ae115bc7Smrj              * Then we have a type mismatch. Just warn and ignore it.
650ae115bc7Smrj              */
651db2bae30SDana Myers             if ((TypeToCheckFor != ACPI_TYPE_ANY)                   &&
652ae115bc7Smrj                 (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS)           &&
653ae115bc7Smrj                 (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS)    &&
654ae115bc7Smrj                 (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE)           &&
655ae115bc7Smrj                 (ThisNode->Type != ACPI_TYPE_ANY)                   &&
656ae115bc7Smrj                 (ThisNode->Type != TypeToCheckFor))
657ae115bc7Smrj             {
658ae115bc7Smrj                 /* Complain about a type mismatch */
659ae115bc7Smrj 
660ae115bc7Smrj                 ACPI_WARNING ((AE_INFO,
661ae115bc7Smrj                     "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
662ae115bc7Smrj                     ACPI_CAST_PTR (char, &SimpleName),
663ae115bc7Smrj                     AcpiUtGetTypeName (ThisNode->Type),
664ae115bc7Smrj                     AcpiUtGetTypeName (TypeToCheckFor)));
665ae115bc7Smrj             }
666ae115bc7Smrj 
667ae115bc7Smrj             /*
668ae115bc7Smrj              * If this is the last name segment and we are not looking for a
669aa2aa9a6SDana Myers              * specific type, but the type of found object is known, use that
670aa2aa9a6SDana Myers              * type to (later) see if it opens a scope.
671ae115bc7Smrj              */
672db2bae30SDana Myers             if (Type == ACPI_TYPE_ANY)
673ae115bc7Smrj             {
674ae115bc7Smrj                 Type = ThisNode->Type;
675ae115bc7Smrj             }
676db2bae30SDana Myers         }
677ae115bc7Smrj 
678ae115bc7Smrj         /* Point to next name segment and make this node current */
679ae115bc7Smrj 
680ae115bc7Smrj         Path += ACPI_NAME_SIZE;
681ae115bc7Smrj         CurrentNode = ThisNode;
682ae115bc7Smrj     }
683ae115bc7Smrj 
684aa2aa9a6SDana Myers     /* Always check if we need to open a new scope */
685aa2aa9a6SDana Myers 
686ae115bc7Smrj     if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState))
687ae115bc7Smrj     {
688ae115bc7Smrj         /*
689ae115bc7Smrj          * If entry is a type which opens a scope, push the new scope on the
690ae115bc7Smrj          * scope stack.
691ae115bc7Smrj          */
692ae115bc7Smrj         if (AcpiNsOpensScope (Type))
693ae115bc7Smrj         {
694ae115bc7Smrj             Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState);
695ae115bc7Smrj             if (ACPI_FAILURE (Status))
696ae115bc7Smrj             {
697ae115bc7Smrj                 return_ACPI_STATUS (Status);
698ae115bc7Smrj             }
699ae115bc7Smrj         }
700ae115bc7Smrj     }
701ae115bc7Smrj 
702ae115bc7Smrj     *ReturnNode = ThisNode;
703ae115bc7Smrj     return_ACPI_STATUS (AE_OK);
704ae115bc7Smrj }
705