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