Merge branch 'openssh'
[dragonfly.git] / sys / contrib / dev / acpica / source / components / namespace / nsutils.c
1 /******************************************************************************
2  *
3  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
4  *                        parents and siblings and Scope manipulation
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2014, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45 #include "acpi.h"
46 #include "accommon.h"
47 #include "acnamesp.h"
48 #include "amlcode.h"
49
50 #define _COMPONENT          ACPI_NAMESPACE
51         ACPI_MODULE_NAME    ("nsutils")
52
53 /* Local prototypes */
54
55 #ifdef ACPI_OBSOLETE_FUNCTIONS
56 ACPI_NAME
57 AcpiNsFindParentName (
58     ACPI_NAMESPACE_NODE     *NodeToSearch);
59 #endif
60
61
62 /*******************************************************************************
63  *
64  * FUNCTION:    AcpiNsPrintNodePathname
65  *
66  * PARAMETERS:  Node            - Object
67  *              Message         - Prefix message
68  *
69  * DESCRIPTION: Print an object's full namespace pathname
70  *              Manages allocation/freeing of a pathname buffer
71  *
72  ******************************************************************************/
73
74 void
75 AcpiNsPrintNodePathname (
76     ACPI_NAMESPACE_NODE     *Node,
77     const char              *Message)
78 {
79     ACPI_BUFFER             Buffer;
80     ACPI_STATUS             Status;
81
82
83     if (!Node)
84     {
85         AcpiOsPrintf ("[NULL NAME]");
86         return;
87     }
88
89     /* Convert handle to full pathname and print it (with supplied message) */
90
91     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
92
93     Status = AcpiNsHandleToPathname (Node, &Buffer);
94     if (ACPI_SUCCESS (Status))
95     {
96         if (Message)
97         {
98             AcpiOsPrintf ("%s ", Message);
99         }
100
101         AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
102         ACPI_FREE (Buffer.Pointer);
103     }
104 }
105
106
107 /*******************************************************************************
108  *
109  * FUNCTION:    AcpiNsGetType
110  *
111  * PARAMETERS:  Node        - Parent Node to be examined
112  *
113  * RETURN:      Type field from Node whose handle is passed
114  *
115  * DESCRIPTION: Return the type of a Namespace node
116  *
117  ******************************************************************************/
118
119 ACPI_OBJECT_TYPE
120 AcpiNsGetType (
121     ACPI_NAMESPACE_NODE     *Node)
122 {
123     ACPI_FUNCTION_TRACE (NsGetType);
124
125
126     if (!Node)
127     {
128         ACPI_WARNING ((AE_INFO, "Null Node parameter"));
129         return_UINT8 (ACPI_TYPE_ANY);
130     }
131
132     return_UINT8 (Node->Type);
133 }
134
135
136 /*******************************************************************************
137  *
138  * FUNCTION:    AcpiNsLocal
139  *
140  * PARAMETERS:  Type        - A namespace object type
141  *
142  * RETURN:      LOCAL if names must be found locally in objects of the
143  *              passed type, 0 if enclosing scopes should be searched
144  *
145  * DESCRIPTION: Returns scope rule for the given object type.
146  *
147  ******************************************************************************/
148
149 UINT32
150 AcpiNsLocal (
151     ACPI_OBJECT_TYPE        Type)
152 {
153     ACPI_FUNCTION_TRACE (NsLocal);
154
155
156     if (!AcpiUtValidObjectType (Type))
157     {
158         /* Type code out of range  */
159
160         ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
161         return_UINT32 (ACPI_NS_NORMAL);
162     }
163
164     return_UINT32 (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
165 }
166
167
168 /*******************************************************************************
169  *
170  * FUNCTION:    AcpiNsGetInternalNameLength
171  *
172  * PARAMETERS:  Info            - Info struct initialized with the
173  *                                external name pointer.
174  *
175  * RETURN:      None
176  *
177  * DESCRIPTION: Calculate the length of the internal (AML) namestring
178  *              corresponding to the external (ASL) namestring.
179  *
180  ******************************************************************************/
181
182 void
183 AcpiNsGetInternalNameLength (
184     ACPI_NAMESTRING_INFO    *Info)
185 {
186     const char              *NextExternalChar;
187     UINT32                  i;
188
189
190     ACPI_FUNCTION_ENTRY ();
191
192
193     NextExternalChar = Info->ExternalName;
194     Info->NumCarats = 0;
195     Info->NumSegments = 0;
196     Info->FullyQualified = FALSE;
197
198     /*
199      * For the internal name, the required length is 4 bytes per segment, plus
200      * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null
201      * (which is not really needed, but no there's harm in putting it there)
202      *
203      * strlen() + 1 covers the first NameSeg, which has no path separator
204      */
205     if (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
206     {
207         Info->FullyQualified = TRUE;
208         NextExternalChar++;
209
210         /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
211
212         while (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
213         {
214             NextExternalChar++;
215         }
216     }
217     else
218     {
219         /* Handle Carat prefixes */
220
221         while (ACPI_IS_PARENT_PREFIX (*NextExternalChar))
222         {
223             Info->NumCarats++;
224             NextExternalChar++;
225         }
226     }
227
228     /*
229      * Determine the number of ACPI name "segments" by counting the number of
230      * path separators within the string. Start with one segment since the
231      * segment count is [(# separators) + 1], and zero separators is ok.
232      */
233     if (*NextExternalChar)
234     {
235         Info->NumSegments = 1;
236         for (i = 0; NextExternalChar[i]; i++)
237         {
238             if (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i]))
239             {
240                 Info->NumSegments++;
241             }
242         }
243     }
244
245     Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
246                     4 + Info->NumCarats;
247
248     Info->NextExternalChar = NextExternalChar;
249 }
250
251
252 /*******************************************************************************
253  *
254  * FUNCTION:    AcpiNsBuildInternalName
255  *
256  * PARAMETERS:  Info            - Info struct fully initialized
257  *
258  * RETURN:      Status
259  *
260  * DESCRIPTION: Construct the internal (AML) namestring
261  *              corresponding to the external (ASL) namestring.
262  *
263  ******************************************************************************/
264
265 ACPI_STATUS
266 AcpiNsBuildInternalName (
267     ACPI_NAMESTRING_INFO    *Info)
268 {
269     UINT32                  NumSegments = Info->NumSegments;
270     char                    *InternalName = Info->InternalName;
271     const char              *ExternalName = Info->NextExternalChar;
272     char                    *Result = NULL;
273     UINT32                  i;
274
275
276     ACPI_FUNCTION_TRACE (NsBuildInternalName);
277
278
279     /* Setup the correct prefixes, counts, and pointers */
280
281     if (Info->FullyQualified)
282     {
283         InternalName[0] = AML_ROOT_PREFIX;
284
285         if (NumSegments <= 1)
286         {
287             Result = &InternalName[1];
288         }
289         else if (NumSegments == 2)
290         {
291             InternalName[1] = AML_DUAL_NAME_PREFIX;
292             Result = &InternalName[2];
293         }
294         else
295         {
296             InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
297             InternalName[2] = (char) NumSegments;
298             Result = &InternalName[3];
299         }
300     }
301     else
302     {
303         /*
304          * Not fully qualified.
305          * Handle Carats first, then append the name segments
306          */
307         i = 0;
308         if (Info->NumCarats)
309         {
310             for (i = 0; i < Info->NumCarats; i++)
311             {
312                 InternalName[i] = AML_PARENT_PREFIX;
313             }
314         }
315
316         if (NumSegments <= 1)
317         {
318             Result = &InternalName[i];
319         }
320         else if (NumSegments == 2)
321         {
322             InternalName[i] = AML_DUAL_NAME_PREFIX;
323             Result = &InternalName[(ACPI_SIZE) i+1];
324         }
325         else
326         {
327             InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
328             InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
329             Result = &InternalName[(ACPI_SIZE) i+2];
330         }
331     }
332
333     /* Build the name (minus path separators) */
334
335     for (; NumSegments; NumSegments--)
336     {
337         for (i = 0; i < ACPI_NAME_SIZE; i++)
338         {
339             if (ACPI_IS_PATH_SEPARATOR (*ExternalName) ||
340                (*ExternalName == 0))
341             {
342                 /* Pad the segment with underscore(s) if segment is short */
343
344                 Result[i] = '_';
345             }
346             else
347             {
348                 /* Convert the character to uppercase and save it */
349
350                 Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
351                 ExternalName++;
352             }
353         }
354
355         /* Now we must have a path separator, or the pathname is bad */
356
357         if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) &&
358             (*ExternalName != 0))
359         {
360             return_ACPI_STATUS (AE_BAD_PATHNAME);
361         }
362
363         /* Move on the next segment */
364
365         ExternalName++;
366         Result += ACPI_NAME_SIZE;
367     }
368
369     /* Terminate the string */
370
371     *Result = 0;
372
373     if (Info->FullyQualified)
374     {
375         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
376             InternalName, InternalName));
377     }
378     else
379     {
380         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
381             InternalName, InternalName));
382     }
383
384     return_ACPI_STATUS (AE_OK);
385 }
386
387
388 /*******************************************************************************
389  *
390  * FUNCTION:    AcpiNsInternalizeName
391  *
392  * PARAMETERS:  *ExternalName           - External representation of name
393  *              **Converted Name        - Where to return the resulting
394  *                                        internal represention of the name
395  *
396  * RETURN:      Status
397  *
398  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
399  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
400  *
401  *******************************************************************************/
402
403 ACPI_STATUS
404 AcpiNsInternalizeName (
405     const char              *ExternalName,
406     char                    **ConvertedName)
407 {
408     char                    *InternalName;
409     ACPI_NAMESTRING_INFO    Info;
410     ACPI_STATUS             Status;
411
412
413     ACPI_FUNCTION_TRACE (NsInternalizeName);
414
415
416     if ((!ExternalName)      ||
417         (*ExternalName == 0) ||
418         (!ConvertedName))
419     {
420         return_ACPI_STATUS (AE_BAD_PARAMETER);
421     }
422
423     /* Get the length of the new internal name */
424
425     Info.ExternalName = ExternalName;
426     AcpiNsGetInternalNameLength (&Info);
427
428     /* We need a segment to store the internal  name */
429
430     InternalName = ACPI_ALLOCATE_ZEROED (Info.Length);
431     if (!InternalName)
432     {
433         return_ACPI_STATUS (AE_NO_MEMORY);
434     }
435
436     /* Build the name */
437
438     Info.InternalName = InternalName;
439     Status = AcpiNsBuildInternalName (&Info);
440     if (ACPI_FAILURE (Status))
441     {
442         ACPI_FREE (InternalName);
443         return_ACPI_STATUS (Status);
444     }
445
446     *ConvertedName = InternalName;
447     return_ACPI_STATUS (AE_OK);
448 }
449
450
451 /*******************************************************************************
452  *
453  * FUNCTION:    AcpiNsExternalizeName
454  *
455  * PARAMETERS:  InternalNameLength  - Lenth of the internal name below
456  *              InternalName        - Internal representation of name
457  *              ConvertedNameLength - Where the length is returned
458  *              ConvertedName       - Where the resulting external name
459  *                                    is returned
460  *
461  * RETURN:      Status
462  *
463  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
464  *              to its external (printable) form (e.g. "\_PR_.CPU0")
465  *
466  ******************************************************************************/
467
468 ACPI_STATUS
469 AcpiNsExternalizeName (
470     UINT32                  InternalNameLength,
471     const char              *InternalName,
472     UINT32                  *ConvertedNameLength,
473     char                    **ConvertedName)
474 {
475     UINT32                  NamesIndex = 0;
476     UINT32                  NumSegments = 0;
477     UINT32                  RequiredLength;
478     UINT32                  PrefixLength = 0;
479     UINT32                  i = 0;
480     UINT32                  j = 0;
481
482
483     ACPI_FUNCTION_TRACE (NsExternalizeName);
484
485
486     if (!InternalNameLength     ||
487         !InternalName           ||
488         !ConvertedName)
489     {
490         return_ACPI_STATUS (AE_BAD_PARAMETER);
491     }
492
493     /* Check for a prefix (one '\' | one or more '^') */
494
495     switch (InternalName[0])
496     {
497     case AML_ROOT_PREFIX:
498
499         PrefixLength = 1;
500         break;
501
502     case AML_PARENT_PREFIX:
503
504         for (i = 0; i < InternalNameLength; i++)
505         {
506             if (ACPI_IS_PARENT_PREFIX (InternalName[i]))
507             {
508                 PrefixLength = i + 1;
509             }
510             else
511             {
512                 break;
513             }
514         }
515
516         if (i == InternalNameLength)
517         {
518             PrefixLength = i;
519         }
520
521         break;
522
523     default:
524
525         break;
526     }
527
528     /*
529      * Check for object names. Note that there could be 0-255 of these
530      * 4-byte elements.
531      */
532     if (PrefixLength < InternalNameLength)
533     {
534         switch (InternalName[PrefixLength])
535         {
536         case AML_MULTI_NAME_PREFIX_OP:
537
538             /* <count> 4-byte names */
539
540             NamesIndex = PrefixLength + 2;
541             NumSegments = (UINT8)
542                 InternalName[(ACPI_SIZE) PrefixLength + 1];
543             break;
544
545         case AML_DUAL_NAME_PREFIX:
546
547             /* Two 4-byte names */
548
549             NamesIndex = PrefixLength + 1;
550             NumSegments = 2;
551             break;
552
553         case 0:
554
555             /* NullName */
556
557             NamesIndex = 0;
558             NumSegments = 0;
559             break;
560
561         default:
562
563             /* one 4-byte name */
564
565             NamesIndex = PrefixLength;
566             NumSegments = 1;
567             break;
568         }
569     }
570
571     /*
572      * Calculate the length of ConvertedName, which equals the length
573      * of the prefix, length of all object names, length of any required
574      * punctuation ('.') between object names, plus the NULL terminator.
575      */
576     RequiredLength = PrefixLength + (4 * NumSegments) +
577                         ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
578
579     /*
580      * Check to see if we're still in bounds. If not, there's a problem
581      * with InternalName (invalid format).
582      */
583     if (RequiredLength > InternalNameLength)
584     {
585         ACPI_ERROR ((AE_INFO, "Invalid internal name"));
586         return_ACPI_STATUS (AE_BAD_PATHNAME);
587     }
588
589     /* Build the ConvertedName */
590
591     *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength);
592     if (!(*ConvertedName))
593     {
594         return_ACPI_STATUS (AE_NO_MEMORY);
595     }
596
597     j = 0;
598
599     for (i = 0; i < PrefixLength; i++)
600     {
601         (*ConvertedName)[j++] = InternalName[i];
602     }
603
604     if (NumSegments > 0)
605     {
606         for (i = 0; i < NumSegments; i++)
607         {
608             if (i > 0)
609             {
610                 (*ConvertedName)[j++] = '.';
611             }
612
613             /* Copy and validate the 4-char name segment */
614
615             ACPI_MOVE_NAME (&(*ConvertedName)[j], &InternalName[NamesIndex]);
616             AcpiUtRepairName (&(*ConvertedName)[j]);
617
618             j += ACPI_NAME_SIZE;
619             NamesIndex += ACPI_NAME_SIZE;
620         }
621     }
622
623     if (ConvertedNameLength)
624     {
625         *ConvertedNameLength = (UINT32) RequiredLength;
626     }
627
628     return_ACPI_STATUS (AE_OK);
629 }
630
631
632 /*******************************************************************************
633  *
634  * FUNCTION:    AcpiNsValidateHandle
635  *
636  * PARAMETERS:  Handle          - Handle to be validated and typecast to a
637  *                                namespace node.
638  *
639  * RETURN:      A pointer to a namespace node
640  *
641  * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
642  *              cases for the root node.
643  *
644  * NOTE: Real integer handles would allow for more verification
645  *       and keep all pointers within this subsystem - however this introduces
646  *       more overhead and has not been necessary to this point. Drivers
647  *       holding handles are typically notified before a node becomes invalid
648  *       due to a table unload.
649  *
650  ******************************************************************************/
651
652 ACPI_NAMESPACE_NODE *
653 AcpiNsValidateHandle (
654     ACPI_HANDLE             Handle)
655 {
656
657     ACPI_FUNCTION_ENTRY ();
658
659
660     /* Parameter validation */
661
662     if ((!Handle) || (Handle == ACPI_ROOT_OBJECT))
663     {
664         return (AcpiGbl_RootNode);
665     }
666
667     /* We can at least attempt to verify the handle */
668
669     if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
670     {
671         return (NULL);
672     }
673
674     return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
675 }
676
677
678 /*******************************************************************************
679  *
680  * FUNCTION:    AcpiNsTerminate
681  *
682  * PARAMETERS:  none
683  *
684  * RETURN:      none
685  *
686  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
687  *
688  ******************************************************************************/
689
690 void
691 AcpiNsTerminate (
692     void)
693 {
694     ACPI_STATUS             Status;
695
696
697     ACPI_FUNCTION_TRACE (NsTerminate);
698
699
700     /*
701      * Free the entire namespace -- all nodes and all objects
702      * attached to the nodes
703      */
704     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
705
706     /* Delete any objects attached to the root node */
707
708     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
709     if (ACPI_FAILURE (Status))
710     {
711         return_VOID;
712     }
713
714     AcpiNsDeleteNode (AcpiGbl_RootNode);
715     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
716
717     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
718     return_VOID;
719 }
720
721
722 /*******************************************************************************
723  *
724  * FUNCTION:    AcpiNsOpensScope
725  *
726  * PARAMETERS:  Type        - A valid namespace type
727  *
728  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
729  *              to the ACPI specification, else 0
730  *
731  ******************************************************************************/
732
733 UINT32
734 AcpiNsOpensScope (
735     ACPI_OBJECT_TYPE        Type)
736 {
737     ACPI_FUNCTION_ENTRY ();
738
739
740     if (Type > ACPI_TYPE_LOCAL_MAX)
741     {
742         /* type code out of range  */
743
744         ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
745         return (ACPI_NS_NORMAL);
746     }
747
748     return (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
749 }
750
751
752 /*******************************************************************************
753  *
754  * FUNCTION:    AcpiNsGetNode
755  *
756  * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
757  *                            \ (backslash) and ^ (carat) prefixes, and the
758  *                            . (period) to separate segments are supported.
759  *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
760  *                            root of the name space. If Name is fully
761  *                            qualified (first INT8 is '\'), the passed value
762  *                            of Scope will not be accessed.
763  *              Flags       - Used to indicate whether to perform upsearch or
764  *                            not.
765  *              ReturnNode  - Where the Node is returned
766  *
767  * DESCRIPTION: Look up a name relative to a given scope and return the
768  *              corresponding Node. NOTE: Scope can be null.
769  *
770  * MUTEX:       Locks namespace
771  *
772  ******************************************************************************/
773
774 ACPI_STATUS
775 AcpiNsGetNode (
776     ACPI_NAMESPACE_NODE     *PrefixNode,
777     const char              *Pathname,
778     UINT32                  Flags,
779     ACPI_NAMESPACE_NODE     **ReturnNode)
780 {
781     ACPI_GENERIC_STATE      ScopeInfo;
782     ACPI_STATUS             Status;
783     char                    *InternalPath;
784
785
786     ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
787
788
789     /* Simplest case is a null pathname */
790
791     if (!Pathname)
792     {
793         *ReturnNode = PrefixNode;
794         if (!PrefixNode)
795         {
796             *ReturnNode = AcpiGbl_RootNode;
797         }
798         return_ACPI_STATUS (AE_OK);
799     }
800
801     /* Quick check for a reference to the root */
802
803     if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1]))
804     {
805         *ReturnNode = AcpiGbl_RootNode;
806         return_ACPI_STATUS (AE_OK);
807     }
808
809     /* Convert path to internal representation */
810
811     Status = AcpiNsInternalizeName (Pathname, &InternalPath);
812     if (ACPI_FAILURE (Status))
813     {
814         return_ACPI_STATUS (Status);
815     }
816
817     /* Must lock namespace during lookup */
818
819     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
820     if (ACPI_FAILURE (Status))
821     {
822         goto Cleanup;
823     }
824
825     /* Setup lookup scope (search starting point) */
826
827     ScopeInfo.Scope.Node = PrefixNode;
828
829     /* Lookup the name in the namespace */
830
831     Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
832                 ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
833                 NULL, ReturnNode);
834     if (ACPI_FAILURE (Status))
835     {
836         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
837                 Pathname, AcpiFormatException (Status)));
838     }
839
840     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
841
842 Cleanup:
843     ACPI_FREE (InternalPath);
844     return_ACPI_STATUS (Status);
845 }