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