xref: /titanic_50/usr/src/uts/intel/io/acpica/namespace/nsutils.c (revision 9fa01faf81019677b9c27c7bdf6a310284d4ccb1)
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 - 2009, 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, 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 %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:    AcpiNsMapHandleToNode
861  *
862  * PARAMETERS:  Handle          - Handle to be converted to an Node
863  *
864  * RETURN:      A Name table entry pointer
865  *
866  * DESCRIPTION: Convert a namespace handle to a real Node
867  *
868  * Note: Real integer handles would allow for more verification
869  *       and keep all pointers within this subsystem - however this introduces
870  *       more (and perhaps unnecessary) overhead.
871  *
872  * The current implemenation is basically a placeholder until such time comes
873  * that it is needed.
874  *
875  ******************************************************************************/
876 
877 ACPI_NAMESPACE_NODE *
878 AcpiNsMapHandleToNode (
879     ACPI_HANDLE             Handle)
880 {
881 
882     ACPI_FUNCTION_ENTRY ();
883 
884 
885     /* Parameter validation */
886 
887     if ((!Handle) || (Handle == ACPI_ROOT_OBJECT))
888     {
889         return (AcpiGbl_RootNode);
890     }
891 
892     /* We can at least attempt to verify the handle */
893 
894     if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
895     {
896         return (NULL);
897     }
898 
899     return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
900 }
901 
902 
903 /*******************************************************************************
904  *
905  * FUNCTION:    AcpiNsConvertEntryToHandle
906  *
907  * PARAMETERS:  Node          - Node to be converted to a Handle
908  *
909  * RETURN:      A user handle
910  *
911  * DESCRIPTION: Convert a real Node to a namespace handle
912  *
913  ******************************************************************************/
914 
915 ACPI_HANDLE
916 AcpiNsConvertEntryToHandle (
917     ACPI_NAMESPACE_NODE         *Node)
918 {
919 
920 
921     /*
922      * Simple implementation for now;
923      */
924     return ((ACPI_HANDLE) Node);
925 
926 
927 /* Example future implementation ---------------------
928 
929     if (!Node)
930     {
931         return (NULL);
932     }
933 
934     if (Node == AcpiGbl_RootNode)
935     {
936         return (ACPI_ROOT_OBJECT);
937     }
938 
939 
940     return ((ACPI_HANDLE) Node);
941 ------------------------------------------------------*/
942 }
943 
944 
945 /*******************************************************************************
946  *
947  * FUNCTION:    AcpiNsTerminate
948  *
949  * PARAMETERS:  none
950  *
951  * RETURN:      none
952  *
953  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
954  *
955  ******************************************************************************/
956 
957 void
958 AcpiNsTerminate (
959     void)
960 {
961     ACPI_OPERAND_OBJECT     *ObjDesc;
962 
963 
964     ACPI_FUNCTION_TRACE (NsTerminate);
965 
966 
967     /*
968      * 1) Free the entire namespace -- all nodes and objects
969      *
970      * Delete all object descriptors attached to namepsace nodes
971      */
972     AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
973 
974     /* Detach any objects attached to the root */
975 
976     ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode);
977     if (ObjDesc)
978     {
979         AcpiNsDetachObject (AcpiGbl_RootNode);
980     }
981 
982     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
983     return_VOID;
984 }
985 
986 
987 /*******************************************************************************
988  *
989  * FUNCTION:    AcpiNsOpensScope
990  *
991  * PARAMETERS:  Type        - A valid namespace type
992  *
993  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
994  *              to the ACPI specification, else 0
995  *
996  ******************************************************************************/
997 
998 UINT32
999 AcpiNsOpensScope (
1000     ACPI_OBJECT_TYPE        Type)
1001 {
1002     ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type));
1003 
1004 
1005     if (!AcpiUtValidObjectType (Type))
1006     {
1007         /* type code out of range  */
1008 
1009         ACPI_WARNING ((AE_INFO, "Invalid Object Type %X", Type));
1010         return_UINT32 (ACPI_NS_NORMAL);
1011     }
1012 
1013     return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
1014 }
1015 
1016 
1017 /*******************************************************************************
1018  *
1019  * FUNCTION:    AcpiNsGetNode
1020  *
1021  * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
1022  *                            \ (backslash) and ^ (carat) prefixes, and the
1023  *                            . (period) to separate segments are supported.
1024  *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
1025  *                            root of the name space.  If Name is fully
1026  *                            qualified (first INT8 is '\'), the passed value
1027  *                            of Scope will not be accessed.
1028  *              Flags       - Used to indicate whether to perform upsearch or
1029  *                            not.
1030  *              ReturnNode  - Where the Node is returned
1031  *
1032  * DESCRIPTION: Look up a name relative to a given scope and return the
1033  *              corresponding Node.  NOTE: Scope can be null.
1034  *
1035  * MUTEX:       Locks namespace
1036  *
1037  ******************************************************************************/
1038 
1039 ACPI_STATUS
1040 AcpiNsGetNode (
1041     ACPI_NAMESPACE_NODE     *PrefixNode,
1042     const char              *Pathname,
1043     UINT32                  Flags,
1044     ACPI_NAMESPACE_NODE     **ReturnNode)
1045 {
1046     ACPI_GENERIC_STATE      ScopeInfo;
1047     ACPI_STATUS             Status;
1048     char                    *InternalPath;
1049 
1050 
1051     ACPI_FUNCTION_TRACE_PTR (NsGetNode, Pathname);
1052 
1053 
1054     if (!Pathname)
1055     {
1056         *ReturnNode = PrefixNode;
1057         if (!PrefixNode)
1058         {
1059             *ReturnNode = AcpiGbl_RootNode;
1060         }
1061         return_ACPI_STATUS (AE_OK);
1062     }
1063 
1064     /* Convert path to internal representation */
1065 
1066     Status = AcpiNsInternalizeName (Pathname, &InternalPath);
1067     if (ACPI_FAILURE (Status))
1068     {
1069         return_ACPI_STATUS (Status);
1070     }
1071 
1072     /* Must lock namespace during lookup */
1073 
1074     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1075     if (ACPI_FAILURE (Status))
1076     {
1077         goto Cleanup;
1078     }
1079 
1080     /* Setup lookup scope (search starting point) */
1081 
1082     ScopeInfo.Scope.Node = PrefixNode;
1083 
1084     /* Lookup the name in the namespace */
1085 
1086     Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
1087                 ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
1088                 NULL, ReturnNode);
1089     if (ACPI_FAILURE (Status))
1090     {
1091         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
1092                 Pathname, AcpiFormatException (Status)));
1093     }
1094 
1095     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1096 
1097 Cleanup:
1098     ACPI_FREE (InternalPath);
1099     return_ACPI_STATUS (Status);
1100 }
1101 
1102 
1103 /*******************************************************************************
1104  *
1105  * FUNCTION:    AcpiNsGetParentNode
1106  *
1107  * PARAMETERS:  Node       - Current table entry
1108  *
1109  * RETURN:      Parent entry of the given entry
1110  *
1111  * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
1112  *
1113  ******************************************************************************/
1114 
1115 ACPI_NAMESPACE_NODE *
1116 AcpiNsGetParentNode (
1117     ACPI_NAMESPACE_NODE     *Node)
1118 {
1119     ACPI_FUNCTION_ENTRY ();
1120 
1121 
1122     if (!Node)
1123     {
1124         return (NULL);
1125     }
1126 
1127     /*
1128      * Walk to the end of this peer list. The last entry is marked with a flag
1129      * and the peer pointer is really a pointer back to the parent. This saves
1130      * putting a parent back pointer in each and every named object!
1131      */
1132     while (!(Node->Flags & ANOBJ_END_OF_PEER_LIST))
1133     {
1134         Node = Node->Peer;
1135     }
1136 
1137     return (Node->Peer);
1138 }
1139 
1140 
1141 /*******************************************************************************
1142  *
1143  * FUNCTION:    AcpiNsGetNextValidNode
1144  *
1145  * PARAMETERS:  Node       - Current table entry
1146  *
1147  * RETURN:      Next valid Node in the linked node list. NULL if no more valid
1148  *              nodes.
1149  *
1150  * DESCRIPTION: Find the next valid node within a name table.
1151  *              Useful for implementing NULL-end-of-list loops.
1152  *
1153  ******************************************************************************/
1154 
1155 ACPI_NAMESPACE_NODE *
1156 AcpiNsGetNextValidNode (
1157     ACPI_NAMESPACE_NODE     *Node)
1158 {
1159 
1160     /* If we are at the end of this peer list, return NULL */
1161 
1162     if (Node->Flags & ANOBJ_END_OF_PEER_LIST)
1163     {
1164         return NULL;
1165     }
1166 
1167     /* Otherwise just return the next peer */
1168 
1169     return (Node->Peer);
1170 }
1171 
1172 
1173 #ifdef ACPI_OBSOLETE_FUNCTIONS
1174 /*******************************************************************************
1175  *
1176  * FUNCTION:    AcpiNsFindParentName
1177  *
1178  * PARAMETERS:  *ChildNode             - Named Obj whose name is to be found
1179  *
1180  * RETURN:      The ACPI name
1181  *
1182  * DESCRIPTION: Search for the given obj in its parent scope and return the
1183  *              name segment, or "????" if the parent name can't be found
1184  *              (which "should not happen").
1185  *
1186  ******************************************************************************/
1187 
1188 ACPI_NAME
1189 AcpiNsFindParentName (
1190     ACPI_NAMESPACE_NODE     *ChildNode)
1191 {
1192     ACPI_NAMESPACE_NODE     *ParentNode;
1193 
1194 
1195     ACPI_FUNCTION_TRACE (NsFindParentName);
1196 
1197 
1198     if (ChildNode)
1199     {
1200         /* Valid entry.  Get the parent Node */
1201 
1202         ParentNode = AcpiNsGetParentNode (ChildNode);
1203         if (ParentNode)
1204         {
1205             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
1206                 "Parent of %p [%4.4s] is %p [%4.4s]\n",
1207                 ChildNode,  AcpiUtGetNodeName (ChildNode),
1208                 ParentNode, AcpiUtGetNodeName (ParentNode)));
1209 
1210             if (ParentNode->Name.Integer)
1211             {
1212                 return_VALUE ((ACPI_NAME) ParentNode->Name.Integer);
1213             }
1214         }
1215 
1216         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
1217             "Unable to find parent of %p (%4.4s)\n",
1218             ChildNode, AcpiUtGetNodeName (ChildNode)));
1219     }
1220 
1221     return_VALUE (ACPI_UNKNOWN_NAME);
1222 }
1223 #endif
1224 
1225 
1226