]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/contrib/dev/acpica/namespace/nsutils.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / contrib / dev / acpica / namespace / nsutils.c
1 /******************************************************************************
2  *
3  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
4  *                        parents and siblings and Scope manipulation
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
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 <contrib/dev/acpica/include/acpi.h>
120 #include <contrib/dev/acpica/include/accommon.h>
121 #include <contrib/dev/acpica/include/acnamesp.h>
122 #include <contrib/dev/acpica/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
1061
1062 /*******************************************************************************
1063  *
1064  * FUNCTION:    AcpiNsGetParentNode
1065  *
1066  * PARAMETERS:  Node       - Current table entry
1067  *
1068  * RETURN:      Parent entry of the given entry
1069  *
1070  * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
1071  *
1072  ******************************************************************************/
1073
1074 ACPI_NAMESPACE_NODE *
1075 AcpiNsGetParentNode (
1076     ACPI_NAMESPACE_NODE     *Node)
1077 {
1078     ACPI_FUNCTION_ENTRY ();
1079
1080
1081     if (!Node)
1082     {
1083         return (NULL);
1084     }
1085
1086     /*
1087      * Walk to the end of this peer list. The last entry is marked with a flag
1088      * and the peer pointer is really a pointer back to the parent. This saves
1089      * putting a parent back pointer in each and every named object!
1090      */
1091     while (!(Node->Flags & ANOBJ_END_OF_PEER_LIST))
1092     {
1093         Node = Node->Peer;
1094     }
1095
1096     return (Node->Peer);
1097 }
1098
1099
1100 /*******************************************************************************
1101  *
1102  * FUNCTION:    AcpiNsGetNextValidNode
1103  *
1104  * PARAMETERS:  Node       - Current table entry
1105  *
1106  * RETURN:      Next valid Node in the linked node list. NULL if no more valid
1107  *              nodes.
1108  *
1109  * DESCRIPTION: Find the next valid node within a name table.
1110  *              Useful for implementing NULL-end-of-list loops.
1111  *
1112  ******************************************************************************/
1113
1114 ACPI_NAMESPACE_NODE *
1115 AcpiNsGetNextValidNode (
1116     ACPI_NAMESPACE_NODE     *Node)
1117 {
1118
1119     /* If we are at the end of this peer list, return NULL */
1120
1121     if (Node->Flags & ANOBJ_END_OF_PEER_LIST)
1122     {
1123         return NULL;
1124     }
1125
1126     /* Otherwise just return the next peer */
1127
1128     return (Node->Peer);
1129 }
1130
1131
1132 #ifdef ACPI_OBSOLETE_FUNCTIONS
1133 /*******************************************************************************
1134  *
1135  * FUNCTION:    AcpiNsFindParentName
1136  *
1137  * PARAMETERS:  *ChildNode             - Named Obj whose name is to be found
1138  *
1139  * RETURN:      The ACPI name
1140  *
1141  * DESCRIPTION: Search for the given obj in its parent scope and return the
1142  *              name segment, or "????" if the parent name can't be found
1143  *              (which "should not happen").
1144  *
1145  ******************************************************************************/
1146
1147 ACPI_NAME
1148 AcpiNsFindParentName (
1149     ACPI_NAMESPACE_NODE     *ChildNode)
1150 {
1151     ACPI_NAMESPACE_NODE     *ParentNode;
1152
1153
1154     ACPI_FUNCTION_TRACE (NsFindParentName);
1155
1156
1157     if (ChildNode)
1158     {
1159         /* Valid entry.  Get the parent Node */
1160
1161         ParentNode = AcpiNsGetParentNode (ChildNode);
1162         if (ParentNode)
1163         {
1164             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
1165                 "Parent of %p [%4.4s] is %p [%4.4s]\n",
1166                 ChildNode,  AcpiUtGetNodeName (ChildNode),
1167                 ParentNode, AcpiUtGetNodeName (ParentNode)));
1168
1169             if (ParentNode->Name.Integer)
1170             {
1171                 return_VALUE ((ACPI_NAME) ParentNode->Name.Integer);
1172             }
1173         }
1174
1175         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
1176             "Unable to find parent of %p (%4.4s)\n",
1177             ChildNode, AcpiUtGetNodeName (ChildNode)));
1178     }
1179
1180     return_VALUE (ACPI_UNKNOWN_NAME);
1181 }
1182 #endif
1183
1184