xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/namespace/nsutils.c (revision 385ee03ba83b7a40d315e17b03031b3ca37820c0)
1 /******************************************************************************
2  *
3  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
4  *                        parents and siblings and Scope manipulation
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights. You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code. No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision. In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change. Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee. Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution. In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government. In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 #include "acpi.h"
118 #include "accommon.h"
119 #include "acnamesp.h"
120 #include "amlcode.h"
121 
122 #define _COMPONENT          ACPI_NAMESPACE
123         ACPI_MODULE_NAME    ("nsutils")
124 
125 /* Local prototypes */
126 
127 #ifdef ACPI_OBSOLETE_FUNCTIONS
128 ACPI_NAME
129 AcpiNsFindParentName (
130     ACPI_NAMESPACE_NODE     *NodeToSearch);
131 #endif
132 
133 
134 /*******************************************************************************
135  *
136  * FUNCTION:    AcpiNsPrintNodePathname
137  *
138  * PARAMETERS:  Node            - Object
139  *              Message         - Prefix message
140  *
141  * DESCRIPTION: Print an object's full namespace pathname
142  *              Manages allocation/freeing of a pathname buffer
143  *
144  ******************************************************************************/
145 
146 void
147 AcpiNsPrintNodePathname (
148     ACPI_NAMESPACE_NODE     *Node,
149     const char              *Message)
150 {
151     ACPI_BUFFER             Buffer;
152     ACPI_STATUS             Status;
153 
154 
155     if (!Node)
156     {
157         AcpiOsPrintf ("[NULL NAME]");
158         return;
159     }
160 
161     /* Convert handle to full pathname and print it (with supplied message) */
162 
163     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
164 
165     Status = AcpiNsHandleToPathname (Node, &Buffer, TRUE);
166     if (ACPI_SUCCESS (Status))
167     {
168         if (Message)
169         {
170             AcpiOsPrintf ("%s ", Message);
171         }
172 
173         AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
174         ACPI_FREE (Buffer.Pointer);
175     }
176 }
177 
178 
179 /*******************************************************************************
180  *
181  * FUNCTION:    AcpiNsGetType
182  *
183  * PARAMETERS:  Node        - Parent Node to be examined
184  *
185  * RETURN:      Type field from Node whose handle is passed
186  *
187  * DESCRIPTION: Return the type of a Namespace node
188  *
189  ******************************************************************************/
190 
191 ACPI_OBJECT_TYPE
192 AcpiNsGetType (
193     ACPI_NAMESPACE_NODE     *Node)
194 {
195     ACPI_FUNCTION_TRACE (NsGetType);
196 
197 
198     if (!Node)
199     {
200         ACPI_WARNING ((AE_INFO, "Null Node parameter"));
201         return_UINT8 (ACPI_TYPE_ANY);
202     }
203 
204     return_UINT8 (Node->Type);
205 }
206 
207 
208 /*******************************************************************************
209  *
210  * FUNCTION:    AcpiNsLocal
211  *
212  * PARAMETERS:  Type        - A namespace object type
213  *
214  * RETURN:      LOCAL if names must be found locally in objects of the
215  *              passed type, 0 if enclosing scopes should be searched
216  *
217  * DESCRIPTION: Returns scope rule for the given object type.
218  *
219  ******************************************************************************/
220 
221 UINT32
222 AcpiNsLocal (
223     ACPI_OBJECT_TYPE        Type)
224 {
225     ACPI_FUNCTION_TRACE (NsLocal);
226 
227 
228     if (!AcpiUtValidObjectType (Type))
229     {
230         /* Type code out of range  */
231 
232         ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
233         return_UINT32 (ACPI_NS_NORMAL);
234     }
235 
236     return_UINT32 (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
237 }
238 
239 
240 /*******************************************************************************
241  *
242  * FUNCTION:    AcpiNsGetInternalNameLength
243  *
244  * PARAMETERS:  Info            - Info struct initialized with the
245  *                                external name pointer.
246  *
247  * RETURN:      None
248  *
249  * DESCRIPTION: Calculate the length of the internal (AML) namestring
250  *              corresponding to the external (ASL) namestring.
251  *
252  ******************************************************************************/
253 
254 void
255 AcpiNsGetInternalNameLength (
256     ACPI_NAMESTRING_INFO    *Info)
257 {
258     const char              *NextExternalChar;
259     UINT32                  i;
260 
261 
262     ACPI_FUNCTION_ENTRY ();
263 
264 
265     NextExternalChar = Info->ExternalName;
266     Info->NumCarats = 0;
267     Info->NumSegments = 0;
268     Info->FullyQualified = FALSE;
269 
270     /*
271      * For the internal name, the required length is 4 bytes per segment,
272      * plus 1 each for RootPrefix, MultiNamePrefixOp, segment count,
273      * trailing null (which is not really needed, but no there's harm in
274      * putting it there)
275      *
276      * strlen() + 1 covers the first NameSeg, which has no path separator
277      */
278     if (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
279     {
280         Info->FullyQualified = TRUE;
281         NextExternalChar++;
282 
283         /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
284 
285         while (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
286         {
287             NextExternalChar++;
288         }
289     }
290     else
291     {
292         /* Handle Carat prefixes */
293 
294         while (ACPI_IS_PARENT_PREFIX (*NextExternalChar))
295         {
296             Info->NumCarats++;
297             NextExternalChar++;
298         }
299     }
300 
301     /*
302      * Determine the number of ACPI name "segments" by counting the number of
303      * path separators within the string. Start with one segment since the
304      * segment count is [(# separators) + 1], and zero separators is ok.
305      */
306     if (*NextExternalChar)
307     {
308         Info->NumSegments = 1;
309         for (i = 0; NextExternalChar[i]; i++)
310         {
311             if (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i]))
312             {
313                 Info->NumSegments++;
314             }
315         }
316     }
317 
318     Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
319         4 + Info->NumCarats;
320 
321     Info->NextExternalChar = NextExternalChar;
322 }
323 
324 
325 /*******************************************************************************
326  *
327  * FUNCTION:    AcpiNsBuildInternalName
328  *
329  * PARAMETERS:  Info            - Info struct fully initialized
330  *
331  * RETURN:      Status
332  *
333  * DESCRIPTION: Construct the internal (AML) namestring
334  *              corresponding to the external (ASL) namestring.
335  *
336  ******************************************************************************/
337 
338 ACPI_STATUS
339 AcpiNsBuildInternalName (
340     ACPI_NAMESTRING_INFO    *Info)
341 {
342     UINT32                  NumSegments = Info->NumSegments;
343     char                    *InternalName = Info->InternalName;
344     const char              *ExternalName = Info->NextExternalChar;
345     char                    *Result = NULL;
346     UINT32                  i;
347 
348 
349     ACPI_FUNCTION_TRACE (NsBuildInternalName);
350 
351 
352     /* Setup the correct prefixes, counts, and pointers */
353 
354     if (Info->FullyQualified)
355     {
356         InternalName[0] = AML_ROOT_PREFIX;
357 
358         if (NumSegments <= 1)
359         {
360             Result = &InternalName[1];
361         }
362         else if (NumSegments == 2)
363         {
364             InternalName[1] = AML_DUAL_NAME_PREFIX;
365             Result = &InternalName[2];
366         }
367         else
368         {
369             InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
370             InternalName[2] = (char) NumSegments;
371             Result = &InternalName[3];
372         }
373     }
374     else
375     {
376         /*
377          * Not fully qualified.
378          * Handle Carats first, then append the name segments
379          */
380         i = 0;
381         if (Info->NumCarats)
382         {
383             for (i = 0; i < Info->NumCarats; i++)
384             {
385                 InternalName[i] = AML_PARENT_PREFIX;
386             }
387         }
388 
389         if (NumSegments <= 1)
390         {
391             Result = &InternalName[i];
392         }
393         else if (NumSegments == 2)
394         {
395             InternalName[i] = AML_DUAL_NAME_PREFIX;
396             Result = &InternalName[(ACPI_SIZE) i+1];
397         }
398         else
399         {
400             InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
401             InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
402             Result = &InternalName[(ACPI_SIZE) i+2];
403         }
404     }
405 
406     /* Build the name (minus path separators) */
407 
408     for (; NumSegments; NumSegments--)
409     {
410         for (i = 0; i < ACPI_NAME_SIZE; i++)
411         {
412             if (ACPI_IS_PATH_SEPARATOR (*ExternalName) ||
413                (*ExternalName == 0))
414             {
415                 /* Pad the segment with underscore(s) if segment is short */
416 
417                 Result[i] = '_';
418             }
419             else
420             {
421                 /* Convert the character to uppercase and save it */
422 
423                 Result[i] = (char) toupper ((int) *ExternalName);
424                 ExternalName++;
425             }
426         }
427 
428         /* Now we must have a path separator, or the pathname is bad */
429 
430         if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) &&
431             (*ExternalName != 0))
432         {
433             return_ACPI_STATUS (AE_BAD_PATHNAME);
434         }
435 
436         /* Move on the next segment */
437 
438         ExternalName++;
439         Result += ACPI_NAME_SIZE;
440     }
441 
442     /* Terminate the string */
443 
444     *Result = 0;
445 
446     if (Info->FullyQualified)
447     {
448         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
449             InternalName, InternalName));
450     }
451     else
452     {
453         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
454             InternalName, InternalName));
455     }
456 
457     return_ACPI_STATUS (AE_OK);
458 }
459 
460 
461 /*******************************************************************************
462  *
463  * FUNCTION:    AcpiNsInternalizeName
464  *
465  * PARAMETERS:  *ExternalName           - External representation of name
466  *              **Converted Name        - Where to return the resulting
467  *                                        internal represention of the name
468  *
469  * RETURN:      Status
470  *
471  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
472  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
473  *
474  *******************************************************************************/
475 
476 ACPI_STATUS
477 AcpiNsInternalizeName (
478     const char              *ExternalName,
479     char                    **ConvertedName)
480 {
481     char                    *InternalName;
482     ACPI_NAMESTRING_INFO    Info;
483     ACPI_STATUS             Status;
484 
485 
486     ACPI_FUNCTION_TRACE (NsInternalizeName);
487 
488 
489     if ((!ExternalName)      ||
490         (*ExternalName == 0) ||
491         (!ConvertedName))
492     {
493         return_ACPI_STATUS (AE_BAD_PARAMETER);
494     }
495 
496     /* Get the length of the new internal name */
497 
498     Info.ExternalName = ExternalName;
499     AcpiNsGetInternalNameLength (&Info);
500 
501     /* We need a segment to store the internal  name */
502 
503     InternalName = ACPI_ALLOCATE_ZEROED (Info.Length);
504     if (!InternalName)
505     {
506         return_ACPI_STATUS (AE_NO_MEMORY);
507     }
508 
509     /* Build the name */
510 
511     Info.InternalName = InternalName;
512     Status = AcpiNsBuildInternalName (&Info);
513     if (ACPI_FAILURE (Status))
514     {
515         ACPI_FREE (InternalName);
516         return_ACPI_STATUS (Status);
517     }
518 
519     *ConvertedName = InternalName;
520     return_ACPI_STATUS (AE_OK);
521 }
522 
523 
524 /*******************************************************************************
525  *
526  * FUNCTION:    AcpiNsExternalizeName
527  *
528  * PARAMETERS:  InternalNameLength  - Lenth of the internal name below
529  *              InternalName        - Internal representation of name
530  *              ConvertedNameLength - Where the length is returned
531  *              ConvertedName       - Where the resulting external name
532  *                                    is returned
533  *
534  * RETURN:      Status
535  *
536  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
537  *              to its external (printable) form (e.g. "\_PR_.CPU0")
538  *
539  ******************************************************************************/
540 
541 ACPI_STATUS
542 AcpiNsExternalizeName (
543     UINT32                  InternalNameLength,
544     const char              *InternalName,
545     UINT32                  *ConvertedNameLength,
546     char                    **ConvertedName)
547 {
548     UINT32                  NamesIndex = 0;
549     UINT32                  NumSegments = 0;
550     UINT32                  RequiredLength;
551     UINT32                  PrefixLength = 0;
552     UINT32                  i = 0;
553     UINT32                  j = 0;
554 
555 
556     ACPI_FUNCTION_TRACE (NsExternalizeName);
557 
558 
559     if (!InternalNameLength     ||
560         !InternalName           ||
561         !ConvertedName)
562     {
563         return_ACPI_STATUS (AE_BAD_PARAMETER);
564     }
565 
566     /* Check for a prefix (one '\' | one or more '^') */
567 
568     switch (InternalName[0])
569     {
570     case AML_ROOT_PREFIX:
571 
572         PrefixLength = 1;
573         break;
574 
575     case AML_PARENT_PREFIX:
576 
577         for (i = 0; i < InternalNameLength; i++)
578         {
579             if (ACPI_IS_PARENT_PREFIX (InternalName[i]))
580             {
581                 PrefixLength = i + 1;
582             }
583             else
584             {
585                 break;
586             }
587         }
588 
589         if (i == InternalNameLength)
590         {
591             PrefixLength = i;
592         }
593 
594         break;
595 
596     default:
597 
598         break;
599     }
600 
601     /*
602      * Check for object names. Note that there could be 0-255 of these
603      * 4-byte elements.
604      */
605     if (PrefixLength < InternalNameLength)
606     {
607         switch (InternalName[PrefixLength])
608         {
609         case AML_MULTI_NAME_PREFIX_OP:
610 
611             /* <count> 4-byte names */
612 
613             NamesIndex = PrefixLength + 2;
614             NumSegments = (UINT8)
615                 InternalName[(ACPI_SIZE) PrefixLength + 1];
616             break;
617 
618         case AML_DUAL_NAME_PREFIX:
619 
620             /* Two 4-byte names */
621 
622             NamesIndex = PrefixLength + 1;
623             NumSegments = 2;
624             break;
625 
626         case 0:
627 
628             /* NullName */
629 
630             NamesIndex = 0;
631             NumSegments = 0;
632             break;
633 
634         default:
635 
636             /* one 4-byte name */
637 
638             NamesIndex = PrefixLength;
639             NumSegments = 1;
640             break;
641         }
642     }
643 
644     /*
645      * Calculate the length of ConvertedName, which equals the length
646      * of the prefix, length of all object names, length of any required
647      * punctuation ('.') between object names, plus the NULL terminator.
648      */
649     RequiredLength = PrefixLength + (4 * NumSegments) +
650         ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
651 
652     /*
653      * Check to see if we're still in bounds. If not, there's a problem
654      * with InternalName (invalid format).
655      */
656     if (RequiredLength > InternalNameLength)
657     {
658         ACPI_ERROR ((AE_INFO, "Invalid internal name"));
659         return_ACPI_STATUS (AE_BAD_PATHNAME);
660     }
661 
662     /* Build the ConvertedName */
663 
664     *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength);
665     if (!(*ConvertedName))
666     {
667         return_ACPI_STATUS (AE_NO_MEMORY);
668     }
669 
670     j = 0;
671 
672     for (i = 0; i < PrefixLength; i++)
673     {
674         (*ConvertedName)[j++] = InternalName[i];
675     }
676 
677     if (NumSegments > 0)
678     {
679         for (i = 0; i < NumSegments; i++)
680         {
681             if (i > 0)
682             {
683                 (*ConvertedName)[j++] = '.';
684             }
685 
686             /* Copy and validate the 4-char name segment */
687 
688             ACPI_MOVE_NAME (&(*ConvertedName)[j],
689                 &InternalName[NamesIndex]);
690             AcpiUtRepairName (&(*ConvertedName)[j]);
691 
692             j += ACPI_NAME_SIZE;
693             NamesIndex += ACPI_NAME_SIZE;
694         }
695     }
696 
697     if (ConvertedNameLength)
698     {
699         *ConvertedNameLength = (UINT32) RequiredLength;
700     }
701 
702     return_ACPI_STATUS (AE_OK);
703 }
704 
705 
706 /*******************************************************************************
707  *
708  * FUNCTION:    AcpiNsValidateHandle
709  *
710  * PARAMETERS:  Handle          - Handle to be validated and typecast to a
711  *                                namespace node.
712  *
713  * RETURN:      A pointer to a namespace node
714  *
715  * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
716  *              cases for the root node.
717  *
718  * NOTE: Real integer handles would allow for more verification
719  *       and keep all pointers within this subsystem - however this introduces
720  *       more overhead and has not been necessary to this point. Drivers
721  *       holding handles are typically notified before a node becomes invalid
722  *       due to a table unload.
723  *
724  ******************************************************************************/
725 
726 ACPI_NAMESPACE_NODE *
727 AcpiNsValidateHandle (
728     ACPI_HANDLE             Handle)
729 {
730 
731     ACPI_FUNCTION_ENTRY ();
732 
733 
734     /* Parameter validation */
735 
736     if ((!Handle) || (Handle == ACPI_ROOT_OBJECT))
737     {
738         return (AcpiGbl_RootNode);
739     }
740 
741     /* We can at least attempt to verify the handle */
742 
743     if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
744     {
745         return (NULL);
746     }
747 
748     return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
749 }
750 
751 
752 /*******************************************************************************
753  *
754  * FUNCTION:    AcpiNsTerminate
755  *
756  * PARAMETERS:  none
757  *
758  * RETURN:      none
759  *
760  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
761  *
762  ******************************************************************************/
763 
764 void
765 AcpiNsTerminate (
766     void)
767 {
768     ACPI_STATUS             Status;
769 
770 
771     ACPI_FUNCTION_TRACE (NsTerminate);
772 
773 
774 #ifdef ACPI_EXEC_APP
775     {
776         ACPI_OPERAND_OBJECT     *Prev;
777         ACPI_OPERAND_OBJECT     *Next;
778 
779         /* Delete any module-level code blocks */
780 
781         Next = AcpiGbl_ModuleCodeList;
782         while (Next)
783         {
784             Prev = Next;
785             Next = Next->Method.Mutex;
786             Prev->Method.Mutex = NULL; /* Clear the Mutex (cheated) field */
787             AcpiUtRemoveReference (Prev);
788         }
789     }
790 #endif
791 
792     /*
793      * Free the entire namespace -- all nodes and all objects
794      * attached to the nodes
795      */
796     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
797 
798     /* Delete any objects attached to the root node */
799 
800     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
801     if (ACPI_FAILURE (Status))
802     {
803         return_VOID;
804     }
805 
806     AcpiNsDeleteNode (AcpiGbl_RootNode);
807     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
808 
809     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
810     return_VOID;
811 }
812 
813 
814 /*******************************************************************************
815  *
816  * FUNCTION:    AcpiNsOpensScope
817  *
818  * PARAMETERS:  Type        - A valid namespace type
819  *
820  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
821  *              to the ACPI specification, else 0
822  *
823  ******************************************************************************/
824 
825 UINT32
826 AcpiNsOpensScope (
827     ACPI_OBJECT_TYPE        Type)
828 {
829     ACPI_FUNCTION_ENTRY ();
830 
831 
832     if (Type > ACPI_TYPE_LOCAL_MAX)
833     {
834         /* type code out of range  */
835 
836         ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
837         return (ACPI_NS_NORMAL);
838     }
839 
840     return (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
841 }
842 
843 
844 /*******************************************************************************
845  *
846  * FUNCTION:    AcpiNsGetNode
847  *
848  * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
849  *                            \ (backslash) and ^ (carat) prefixes, and the
850  *                            . (period) to separate segments are supported.
851  *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
852  *                            root of the name space. If Name is fully
853  *                            qualified (first INT8 is '\'), the passed value
854  *                            of Scope will not be accessed.
855  *              Flags       - Used to indicate whether to perform upsearch or
856  *                            not.
857  *              ReturnNode  - Where the Node is returned
858  *
859  * DESCRIPTION: Look up a name relative to a given scope and return the
860  *              corresponding Node. NOTE: Scope can be null.
861  *
862  * MUTEX:       Locks namespace
863  *
864  ******************************************************************************/
865 
866 ACPI_STATUS
867 AcpiNsGetNode (
868     ACPI_NAMESPACE_NODE     *PrefixNode,
869     const char              *Pathname,
870     UINT32                  Flags,
871     ACPI_NAMESPACE_NODE     **ReturnNode)
872 {
873     ACPI_GENERIC_STATE      ScopeInfo;
874     ACPI_STATUS             Status;
875     char                    *InternalPath;
876 
877 
878     ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
879 
880 
881     /* Simplest case is a null pathname */
882 
883     if (!Pathname)
884     {
885         *ReturnNode = PrefixNode;
886         if (!PrefixNode)
887         {
888             *ReturnNode = AcpiGbl_RootNode;
889         }
890 
891         return_ACPI_STATUS (AE_OK);
892     }
893 
894     /* Quick check for a reference to the root */
895 
896     if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1]))
897     {
898         *ReturnNode = AcpiGbl_RootNode;
899         return_ACPI_STATUS (AE_OK);
900     }
901 
902     /* Convert path to internal representation */
903 
904     Status = AcpiNsInternalizeName (Pathname, &InternalPath);
905     if (ACPI_FAILURE (Status))
906     {
907         return_ACPI_STATUS (Status);
908     }
909 
910     /* Must lock namespace during lookup */
911 
912     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
913     if (ACPI_FAILURE (Status))
914     {
915         goto Cleanup;
916     }
917 
918     /* Setup lookup scope (search starting point) */
919 
920     ScopeInfo.Scope.Node = PrefixNode;
921 
922     /* Lookup the name in the namespace */
923 
924     Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
925         ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
926         NULL, ReturnNode);
927     if (ACPI_FAILURE (Status))
928     {
929         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
930             Pathname, AcpiFormatException (Status)));
931     }
932 
933     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
934 
935 Cleanup:
936     ACPI_FREE (InternalPath);
937     return_ACPI_STATUS (Status);
938 }
939