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