machine/stdarg provides __va* macros, not va* macros, use <stdarg.h> instead
[dragonfly.git] / sys / contrib / dev / acpica / nsutils.c
1 /******************************************************************************
2  *
3  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
4  *                        parents and siblings and Scope manipulation
5  *              $Revision: 122 $
6  *
7  *****************************************************************************/
8
9 /******************************************************************************
10  *
11  * 1. Copyright Notice
12  *
13  * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
14  * All rights reserved.
15  *
16  * 2. License
17  *
18  * 2.1. This is your license from Intel Corp. under its intellectual property
19  * rights.  You may have additional license terms from the party that provided
20  * you this software, covering your right to use that party's intellectual
21  * property rights.
22  *
23  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24  * copy of the source code appearing in this file ("Covered Code") an
25  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26  * base code distributed originally by Intel ("Original Intel Code") to copy,
27  * make derivatives, distribute, use and display any portion of the Covered
28  * Code in any form, with the right to sublicense such rights; and
29  *
30  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31  * license (with the right to sublicense), under only those claims of Intel
32  * patents that are infringed by the Original Intel Code, to make, use, sell,
33  * offer to sell, and import the Covered Code and derivative works thereof
34  * solely to the minimum extent necessary to exercise the above copyright
35  * license, and in no event shall the patent license extend to any additions
36  * to or modifications of the Original Intel Code.  No other license or right
37  * is granted directly or by implication, estoppel or otherwise;
38  *
39  * The above copyright and patent license is granted only if the following
40  * conditions are met:
41  *
42  * 3. Conditions
43  *
44  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45  * Redistribution of source code of any substantial portion of the Covered
46  * Code or modification with rights to further distribute source must include
47  * the above Copyright Notice, the above License, this list of Conditions,
48  * and the following Disclaimer and Export Compliance provision.  In addition,
49  * Licensee must cause all Covered Code to which Licensee contributes to
50  * contain a file documenting the changes Licensee made to create that Covered
51  * Code and the date of any change.  Licensee must include in that file the
52  * documentation of any changes made by any predecessor Licensee.  Licensee
53  * must include a prominent statement that the modification is derived,
54  * directly or indirectly, from Original Intel Code.
55  *
56  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57  * Redistribution of source code of any substantial portion of the Covered
58  * Code or modification without rights to further distribute source must
59  * include the following Disclaimer and Export Compliance provision in the
60  * documentation and/or other materials provided with distribution.  In
61  * addition, Licensee may not authorize further sublicense of source of any
62  * portion of the Covered Code, and must include terms to the effect that the
63  * license from Licensee to its licensee is limited to the intellectual
64  * property embodied in the software Licensee provides to its licensee, and
65  * not to intellectual property embodied in modifications its licensee may
66  * make.
67  *
68  * 3.3. Redistribution of Executable. Redistribution in executable form of any
69  * substantial portion of the Covered Code or modification must reproduce the
70  * above Copyright Notice, and the following Disclaimer and Export Compliance
71  * provision in the documentation and/or other materials provided with the
72  * distribution.
73  *
74  * 3.4. Intel retains all right, title, and interest in and to the Original
75  * Intel Code.
76  *
77  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78  * Intel shall be used in advertising or otherwise to promote the sale, use or
79  * other dealings in products derived from or relating to the Covered Code
80  * without prior written authorization from Intel.
81  *
82  * 4. Disclaimer and Export Compliance
83  *
84  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
87  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
89  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90  * PARTICULAR PURPOSE.
91  *
92  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
98  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99  * LIMITED REMEDY.
100  *
101  * 4.3. Licensee shall not export, either directly or indirectly, any of this
102  * software or system incorporating such software without first obtaining any
103  * required license or other approval from the U. S. Department of Commerce or
104  * any other agency or department of the United States Government.  In the
105  * event Licensee exports any such software from the United States or
106  * re-exports any such software from a foreign destination, Licensee shall
107  * ensure that the distribution and export/re-export of the software is in
108  * compliance with all laws, regulations, orders, or other restrictions of the
109  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110  * any of its subsidiaries will export/re-export any technical data, process,
111  * software, or service, directly or indirectly, to any country for which the
112  * United States government or any agency thereof requires an export license,
113  * other governmental approval, or letter of assurance, without first obtaining
114  * such license, approval or letter.
115  *
116  *****************************************************************************/
117 /* $DragonFly: src/sys/contrib/dev/acpica/Attic/nsutils.c,v 1.1 2003/09/24 03:32:16 drhodus Exp $                                                               */
118
119 #define __NSUTILS_C__
120
121 #include "acpi.h"
122 #include "acnamesp.h"
123 #include "amlcode.h"
124 #include "actables.h"
125
126 #define _COMPONENT          ACPI_NAMESPACE
127         ACPI_MODULE_NAME    ("nsutils")
128
129
130 /*******************************************************************************
131  *
132  * FUNCTION:    AcpiNsReportError
133  *
134  * PARAMETERS:  ModuleName          - Caller's module name (for error output)
135  *              LineNumber          - Caller's line number (for error output)
136  *              ComponentId         - Caller's component ID (for error output)
137  *              Message             - Error message to use on failure
138  *
139  * RETURN:      None
140  *
141  * DESCRIPTION: Print warning message with full pathname
142  *
143  ******************************************************************************/
144
145 void
146 AcpiNsReportError (
147     char                    *ModuleName,
148     UINT32                  LineNumber,
149     UINT32                  ComponentId,
150     char                    *InternalName,
151     ACPI_STATUS             LookupStatus)
152 {
153     ACPI_STATUS             Status;
154     char                    *Name;
155
156
157     /* Convert path to external format */
158
159     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalName, NULL, &Name);
160
161     AcpiOsPrintf ("%8s-%04d: *** Error: Looking up ",
162         ModuleName, LineNumber);
163
164     /* Print target name */
165
166     if (ACPI_SUCCESS (Status))
167     {
168         AcpiOsPrintf ("[%s]", Name);
169     }
170     else
171     {
172         AcpiOsPrintf ("[COULD NOT EXTERNALIZE NAME]");
173     }
174
175     AcpiOsPrintf (" in namespace, %s\n",
176         AcpiFormatException (LookupStatus));
177
178     if (Name)
179     {
180         ACPI_MEM_FREE (Name);
181     }
182 }
183
184
185 /*******************************************************************************
186  *
187  * FUNCTION:    AcpiNsReportMethodError
188  *
189  * PARAMETERS:  ModuleName          - Caller's module name (for error output)
190  *              LineNumber          - Caller's line number (for error output)
191  *              ComponentId         - Caller's component ID (for error output)
192  *              Message             - Error message to use on failure
193  *
194  * RETURN:      None
195  *
196  * DESCRIPTION: Print warning message with full pathname
197  *
198  ******************************************************************************/
199
200 void
201 AcpiNsReportMethodError (
202     char                    *ModuleName,
203     UINT32                  LineNumber,
204     UINT32                  ComponentId,
205     char                    *Message,
206     ACPI_NAMESPACE_NODE     *PrefixNode,
207     char                    *Path,
208     ACPI_STATUS             MethodStatus)
209 {
210     ACPI_STATUS             Status;
211     ACPI_NAMESPACE_NODE     *Node = PrefixNode;
212
213
214     if (Path)
215     {
216         Status = AcpiNsGetNodeByPath (Path, PrefixNode, ACPI_NS_NO_UPSEARCH, &Node);
217         if (ACPI_FAILURE (Status))
218         {
219             AcpiOsPrintf ("ReportMethodError: Could not get node\n");
220             return;
221         }
222     }
223
224     AcpiOsPrintf ("%8s-%04d: *** Error: ", ModuleName, LineNumber);
225     AcpiNsPrintNodePathname (Node, Message);
226     AcpiOsPrintf (", %s\n", AcpiFormatException (MethodStatus));
227 }
228
229
230 /*******************************************************************************
231  *
232  * FUNCTION:    AcpiNsPrintNodePathname
233  *
234  * PARAMETERS:  Node                - Object
235  *              Msg                 - Prefix message
236  *
237  * DESCRIPTION: Print an object's full namespace pathname
238  *              Manages allocation/freeing of a pathname buffer
239  *
240  ******************************************************************************/
241
242 void
243 AcpiNsPrintNodePathname (
244     ACPI_NAMESPACE_NODE     *Node,
245     char                    *Msg)
246 {
247     ACPI_BUFFER             Buffer;
248     ACPI_STATUS             Status;
249
250
251     /* Convert handle to a full pathname and print it (with supplied message) */
252
253     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
254
255     Status = AcpiNsHandleToPathname (Node, &Buffer);
256     if (ACPI_SUCCESS (Status))
257     {
258         AcpiOsPrintf ("%s [%s] (Node %p)", Msg, (char *) Buffer.Pointer, Node);
259         ACPI_MEM_FREE (Buffer.Pointer);
260     }
261 }
262
263
264 /*******************************************************************************
265  *
266  * FUNCTION:    AcpiNsValidRootPrefix
267  *
268  * PARAMETERS:  Prefix          - Character to be checked
269  *
270  * RETURN:      TRUE if a valid prefix
271  *
272  * DESCRIPTION: Check if a character is a valid ACPI Root prefix
273  *
274  ******************************************************************************/
275
276 BOOLEAN
277 AcpiNsValidRootPrefix (
278     char                    Prefix)
279 {
280
281     return ((BOOLEAN) (Prefix == '\\'));
282 }
283
284
285 /*******************************************************************************
286  *
287  * FUNCTION:    AcpiNsValidPathSeparator
288  *
289  * PARAMETERS:  Sep              - Character to be checked
290  *
291  * RETURN:      TRUE if a valid path separator
292  *
293  * DESCRIPTION: Check if a character is a valid ACPI path separator
294  *
295  ******************************************************************************/
296
297 BOOLEAN
298 AcpiNsValidPathSeparator (
299     char                    Sep)
300 {
301
302     return ((BOOLEAN) (Sep == '.'));
303 }
304
305
306 /*******************************************************************************
307  *
308  * FUNCTION:    AcpiNsGetType
309  *
310  * PARAMETERS:  Handle              - Parent Node to be examined
311  *
312  * RETURN:      Type field from Node whose handle is passed
313  *
314  ******************************************************************************/
315
316 ACPI_OBJECT_TYPE
317 AcpiNsGetType (
318     ACPI_NAMESPACE_NODE     *Node)
319 {
320     ACPI_FUNCTION_TRACE ("NsGetType");
321
322
323     if (!Node)
324     {
325         ACPI_REPORT_WARNING (("NsGetType: Null Node ptr"));
326         return_VALUE (ACPI_TYPE_ANY);
327     }
328
329     return_VALUE ((ACPI_OBJECT_TYPE) Node->Type);
330 }
331
332
333 /*******************************************************************************
334  *
335  * FUNCTION:    AcpiNsLocal
336  *
337  * PARAMETERS:  Type            - A namespace object type
338  *
339  * RETURN:      LOCAL if names must be found locally in objects of the
340  *              passed type, 0 if enclosing scopes should be searched
341  *
342  ******************************************************************************/
343
344 UINT32
345 AcpiNsLocal (
346     ACPI_OBJECT_TYPE        Type)
347 {
348     ACPI_FUNCTION_TRACE ("NsLocal");
349
350
351     if (!AcpiUtValidObjectType (Type))
352     {
353         /* Type code out of range  */
354
355         ACPI_REPORT_WARNING (("NsLocal: Invalid Object Type\n"));
356         return_VALUE (ACPI_NS_NORMAL);
357     }
358
359     return_VALUE ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
360 }
361
362
363 /*******************************************************************************
364  *
365  * FUNCTION:    AcpiNsGetInternalNameLength
366  *
367  * PARAMETERS:  Info            - Info struct initialized with the
368  *                                external name pointer.
369  *
370  * RETURN:      Status
371  *
372  * DESCRIPTION: Calculate the length of the internal (AML) namestring
373  *              corresponding to the external (ASL) namestring.
374  *
375  ******************************************************************************/
376
377 void
378 AcpiNsGetInternalNameLength (
379     ACPI_NAMESTRING_INFO    *Info)
380 {
381     char                    *NextExternalChar;
382     UINT32                  i;
383
384
385     ACPI_FUNCTION_ENTRY ();
386
387
388     NextExternalChar = Info->ExternalName;
389     Info->NumCarats = 0;
390     Info->NumSegments = 0;
391     Info->FullyQualified = FALSE;
392
393     /*
394      * For the internal name, the required length is 4 bytes
395      * per segment, plus 1 each for RootPrefix, MultiNamePrefixOp,
396      * segment count, trailing null (which is not really needed,
397      * but no there's harm in putting it there)
398      *
399      * strlen() + 1 covers the first NameSeg, which has no
400      * path separator
401      */
402     if (AcpiNsValidRootPrefix (NextExternalChar[0]))
403     {
404         Info->FullyQualified = TRUE;
405         NextExternalChar++;
406     }
407     else
408     {
409         /*
410          * Handle Carat prefixes
411          */
412         while (*NextExternalChar == '^')
413         {
414             Info->NumCarats++;
415             NextExternalChar++;
416         }
417     }
418
419     /*
420      * Determine the number of ACPI name "segments" by counting
421      * the number of path separators within the string.  Start
422      * with one segment since the segment count is (# separators)
423      * + 1, and zero separators is ok.
424      */
425     if (*NextExternalChar)
426     {
427         Info->NumSegments = 1;
428         for (i = 0; NextExternalChar[i]; i++)
429         {
430             if (AcpiNsValidPathSeparator (NextExternalChar[i]))
431             {
432                 Info->NumSegments++;
433             }
434         }
435     }
436
437     Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
438                     4 + Info->NumCarats;
439
440     Info->NextExternalChar = NextExternalChar;
441 }
442
443
444 /*******************************************************************************
445  *
446  * FUNCTION:    AcpiNsBuildInternalName
447  *
448  * PARAMETERS:  Info            - Info struct fully initialized
449  *
450  * RETURN:      Status
451  *
452  * DESCRIPTION: Construct the internal (AML) namestring
453  *              corresponding to the external (ASL) namestring.
454  *
455  ******************************************************************************/
456
457 ACPI_STATUS
458 AcpiNsBuildInternalName (
459     ACPI_NAMESTRING_INFO    *Info)
460 {
461     UINT32                  NumSegments = Info->NumSegments;
462     char                    *InternalName = Info->InternalName;
463     char                    *ExternalName = Info->NextExternalChar;
464     char                    *Result = NULL;
465     ACPI_NATIVE_UINT        i;
466
467
468     ACPI_FUNCTION_TRACE ("NsBuildInternalName");
469
470
471     /* Setup the correct prefixes, counts, and pointers */
472
473     if (Info->FullyQualified)
474     {
475         InternalName[0] = '\\';
476
477         if (NumSegments <= 1)
478         {
479             Result = &InternalName[1];
480         }
481         else if (NumSegments == 2)
482         {
483             InternalName[1] = AML_DUAL_NAME_PREFIX;
484             Result = &InternalName[2];
485         }
486         else
487         {
488             InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
489             InternalName[2] = (char) NumSegments;
490             Result = &InternalName[3];
491         }
492     }
493     else
494     {
495         /*
496          * Not fully qualified.
497          * Handle Carats first, then append the name segments
498          */
499         i = 0;
500         if (Info->NumCarats)
501         {
502             for (i = 0; i < Info->NumCarats; i++)
503             {
504                 InternalName[i] = '^';
505             }
506         }
507
508         if (NumSegments <= 1)
509         {
510             Result = &InternalName[i];
511         }
512         else if (NumSegments == 2)
513         {
514             InternalName[i] = AML_DUAL_NAME_PREFIX;
515             Result = &InternalName[(ACPI_NATIVE_UINT) (i+1)];
516         }
517         else
518         {
519             InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
520             InternalName[(ACPI_NATIVE_UINT) (i+1)] = (char) NumSegments;
521             Result = &InternalName[(ACPI_NATIVE_UINT) (i+2)];
522         }
523     }
524
525     /* Build the name (minus path separators) */
526
527     for (; NumSegments; NumSegments--)
528     {
529         for (i = 0; i < ACPI_NAME_SIZE; i++)
530         {
531             if (AcpiNsValidPathSeparator (*ExternalName) ||
532                (*ExternalName == 0))
533             {
534                 /* Pad the segment with underscore(s) if segment is short */
535
536                 Result[i] = '_';
537             }
538             else
539             {
540                 /* Convert the character to uppercase and save it */
541
542                 Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
543                 ExternalName++;
544             }
545         }
546
547         /* Now we must have a path separator, or the pathname is bad */
548
549         if (!AcpiNsValidPathSeparator (*ExternalName) &&
550             (*ExternalName != 0))
551         {
552             return_ACPI_STATUS (AE_BAD_PARAMETER);
553         }
554
555         /* Move on the next segment */
556
557         ExternalName++;
558         Result += ACPI_NAME_SIZE;
559     }
560
561     /* Terminate the string */
562
563     *Result = 0;
564
565     if (Info->FullyQualified)
566     {
567         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "returning [%p] (abs) \"\\%s\"\n",
568             InternalName, InternalName));
569     }
570     else
571     {
572         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "returning [%p] (rel) \"%s\"\n",
573             InternalName, InternalName));
574     }
575
576     return_ACPI_STATUS (AE_OK);
577 }
578
579
580 /*******************************************************************************
581  *
582  * FUNCTION:    AcpiNsInternalizeName
583  *
584  * PARAMETERS:  *ExternalName           - External representation of name
585  *              **Converted Name        - Where to return the resulting
586  *                                        internal represention of the name
587  *
588  * RETURN:      Status
589  *
590  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
591  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
592  *
593  *******************************************************************************/
594
595 ACPI_STATUS
596 AcpiNsInternalizeName (
597     char                    *ExternalName,
598     char                    **ConvertedName)
599 {
600     char                    *InternalName;
601     ACPI_NAMESTRING_INFO    Info;
602     ACPI_STATUS             Status;
603
604
605     ACPI_FUNCTION_TRACE ("NsInternalizeName");
606
607
608     if ((!ExternalName)      ||
609         (*ExternalName == 0) ||
610         (!ConvertedName))
611     {
612         return_ACPI_STATUS (AE_BAD_PARAMETER);
613     }
614
615     /* Get the length of the new internal name */
616
617     Info.ExternalName = ExternalName;
618     AcpiNsGetInternalNameLength (&Info);
619
620     /* We need a segment to store the internal  name */
621
622     InternalName = ACPI_MEM_CALLOCATE (Info.Length);
623     if (!InternalName)
624     {
625         return_ACPI_STATUS (AE_NO_MEMORY);
626     }
627
628     /* Build the name */
629
630     Info.InternalName = InternalName;
631     Status = AcpiNsBuildInternalName (&Info);
632     if (ACPI_FAILURE (Status))
633     {
634         ACPI_MEM_FREE (InternalName);
635         return_ACPI_STATUS (Status);
636     }
637
638     *ConvertedName = InternalName;
639     return_ACPI_STATUS (AE_OK);
640 }
641
642
643 /*******************************************************************************
644  *
645  * FUNCTION:    AcpiNsExternalizeName
646  *
647  * PARAMETERS:  *InternalName          - Internal representation of name
648  *              **ConvertedName        - Where to return the resulting
649  *                                       external representation of name
650  *
651  * RETURN:      Status
652  *
653  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
654  *              to its external form (e.g. "\_PR_.CPU0")
655  *
656  ******************************************************************************/
657
658 ACPI_STATUS
659 AcpiNsExternalizeName (
660     UINT32                  InternalNameLength,
661     char                    *InternalName,
662     UINT32                  *ConvertedNameLength,
663     char                    **ConvertedName)
664 {
665     ACPI_NATIVE_UINT        NamesIndex = 0;
666     ACPI_NATIVE_UINT        NumSegments = 0;
667     ACPI_NATIVE_UINT        RequiredLength;
668     ACPI_NATIVE_UINT        PrefixLength = 0;
669     ACPI_NATIVE_UINT        i = 0;
670     ACPI_NATIVE_UINT        j = 0;
671
672
673     ACPI_FUNCTION_TRACE ("NsExternalizeName");
674
675
676     if (!InternalNameLength     ||
677         !InternalName           ||
678         !ConvertedName)
679     {
680         return_ACPI_STATUS (AE_BAD_PARAMETER);
681     }
682
683     /*
684      * Check for a prefix (one '\' | one or more '^').
685      */
686     switch (InternalName[0])
687     {
688     case '\\':
689         PrefixLength = 1;
690         break;
691
692     case '^':
693         for (i = 0; i < InternalNameLength; i++)
694         {
695             if (InternalName[i] == '^')
696             {
697                 PrefixLength = i + 1;
698             }
699             else
700             {
701                 break;
702             }
703         }
704
705         if (i == InternalNameLength)
706         {
707             PrefixLength = i;
708         }
709
710         break;
711
712     default:
713         break;
714     }
715
716     /*
717      * Check for object names.  Note that there could be 0-255 of these
718      * 4-byte elements.
719      */
720     if (PrefixLength < InternalNameLength)
721     {
722         switch (InternalName[PrefixLength])
723         {
724         case AML_MULTI_NAME_PREFIX_OP:
725
726             /* <count> 4-byte names */
727
728             NamesIndex = PrefixLength + 2;
729             NumSegments = (UINT32) (UINT8) InternalName[(ACPI_NATIVE_UINT) (PrefixLength + 1)];
730             break;
731
732         case AML_DUAL_NAME_PREFIX:
733
734             /* Two 4-byte names */
735
736             NamesIndex = PrefixLength + 1;
737             NumSegments = 2;
738             break;
739
740         case 0:
741
742             /* NullName */
743
744             NamesIndex = 0;
745             NumSegments = 0;
746             break;
747
748         default:
749
750             /* one 4-byte name */
751
752             NamesIndex = PrefixLength;
753             NumSegments = 1;
754             break;
755         }
756     }
757
758     /*
759      * Calculate the length of ConvertedName, which equals the length
760      * of the prefix, length of all object names, length of any required
761      * punctuation ('.') between object names, plus the NULL terminator.
762      */
763     RequiredLength = PrefixLength + (4 * NumSegments) +
764                         ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
765
766     /*
767      * Check to see if we're still in bounds.  If not, there's a problem
768      * with InternalName (invalid format).
769      */
770     if (RequiredLength > InternalNameLength)
771     {
772         ACPI_REPORT_ERROR (("NsExternalizeName: Invalid internal name\n"));
773         return_ACPI_STATUS (AE_BAD_PATHNAME);
774     }
775
776     /*
777      * Build ConvertedName...
778      */
779     *ConvertedName = ACPI_MEM_CALLOCATE (RequiredLength);
780     if (!(*ConvertedName))
781     {
782         return_ACPI_STATUS (AE_NO_MEMORY);
783     }
784
785     j = 0;
786
787     for (i = 0; i < PrefixLength; i++)
788     {
789         (*ConvertedName)[j++] = InternalName[i];
790     }
791
792     if (NumSegments > 0)
793     {
794         for (i = 0; i < NumSegments; i++)
795         {
796             if (i > 0)
797             {
798                 (*ConvertedName)[j++] = '.';
799             }
800
801             (*ConvertedName)[j++] = InternalName[NamesIndex++];
802             (*ConvertedName)[j++] = InternalName[NamesIndex++];
803             (*ConvertedName)[j++] = InternalName[NamesIndex++];
804             (*ConvertedName)[j++] = InternalName[NamesIndex++];
805         }
806     }
807
808     if (ConvertedNameLength)
809     {
810         *ConvertedNameLength = (UINT32) RequiredLength;
811     }
812
813     return_ACPI_STATUS (AE_OK);
814 }
815
816
817 /*******************************************************************************
818  *
819  * FUNCTION:    AcpiNsMapHandleToNode
820  *
821  * PARAMETERS:  Handle          - Handle to be converted to an Node
822  *
823  * RETURN:      A Name table entry pointer
824  *
825  * DESCRIPTION: Convert a namespace handle to a real Node
826  *
827  * Note: Real integer handles allow for more verification
828  *       and keep all pointers within this subsystem.
829  *
830  ******************************************************************************/
831
832 ACPI_NAMESPACE_NODE *
833 AcpiNsMapHandleToNode (
834     ACPI_HANDLE             Handle)
835 {
836
837     ACPI_FUNCTION_ENTRY ();
838
839
840     /*
841      * Simple implementation.
842      */
843     if (!Handle)
844     {
845         return (NULL);
846     }
847
848     if (Handle == ACPI_ROOT_OBJECT)
849     {
850         return (AcpiGbl_RootNode);
851     }
852
853     /* We can at least attempt to verify the handle */
854
855     if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
856     {
857         return (NULL);
858     }
859
860     return ((ACPI_NAMESPACE_NODE *) Handle);
861 }
862
863
864 /*******************************************************************************
865  *
866  * FUNCTION:    AcpiNsConvertEntryToHandle
867  *
868  * PARAMETERS:  Node          - Node to be converted to a Handle
869  *
870  * RETURN:      An USER ACPI_HANDLE
871  *
872  * DESCRIPTION: Convert a real Node to a namespace handle
873  *
874  ******************************************************************************/
875
876 ACPI_HANDLE
877 AcpiNsConvertEntryToHandle (
878     ACPI_NAMESPACE_NODE         *Node)
879 {
880
881
882     /*
883      * Simple implementation for now;
884      */
885     return ((ACPI_HANDLE) Node);
886
887
888 /* ---------------------------------------------------
889
890     if (!Node)
891     {
892         return (NULL);
893     }
894
895     if (Node == AcpiGbl_RootNode)
896     {
897         return (ACPI_ROOT_OBJECT);
898     }
899
900
901     return ((ACPI_HANDLE) Node);
902 ------------------------------------------------------*/
903 }
904
905
906 /*******************************************************************************
907  *
908  * FUNCTION:    AcpiNsTerminate
909  *
910  * PARAMETERS:  none
911  *
912  * RETURN:      none
913  *
914  * DESCRIPTION: free memory allocated for table storage.
915  *
916  ******************************************************************************/
917
918 void
919 AcpiNsTerminate (void)
920 {
921     ACPI_OPERAND_OBJECT     *ObjDesc;
922     ACPI_NAMESPACE_NODE     *ThisNode;
923
924
925     ACPI_FUNCTION_TRACE ("NsTerminate");
926
927
928     ThisNode = AcpiGbl_RootNode;
929
930     /*
931      * 1) Free the entire namespace -- all objects, tables, and stacks
932      *
933      * Delete all objects linked to the root
934      * (additional table descriptors)
935      */
936     AcpiNsDeleteNamespaceSubtree (ThisNode);
937
938     /* Detach any object(s) attached to the root */
939
940     ObjDesc = AcpiNsGetAttachedObject (ThisNode);
941     if (ObjDesc)
942     {
943         AcpiNsDetachObject (ThisNode);
944         AcpiUtRemoveReference (ObjDesc);
945     }
946
947     AcpiNsDeleteChildren (ThisNode);
948     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
949
950
951     /*
952      * 2) Now we can delete the ACPI tables
953      */
954     AcpiTbDeleteAcpiTables ();
955     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
956
957     return_VOID;
958 }
959
960
961 /*******************************************************************************
962  *
963  * FUNCTION:    AcpiNsOpensScope
964  *
965  * PARAMETERS:  Type        - A valid namespace type
966  *
967  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
968  *              to the ACPI specification, else 0
969  *
970  ******************************************************************************/
971
972 UINT32
973 AcpiNsOpensScope (
974     ACPI_OBJECT_TYPE        Type)
975 {
976     ACPI_FUNCTION_TRACE_STR ("NsOpensScope", AcpiUtGetTypeName (Type));
977
978
979     if (!AcpiUtValidObjectType (Type))
980     {
981         /* type code out of range  */
982
983         ACPI_REPORT_WARNING (("NsOpensScope: Invalid Object Type %X\n", Type));
984         return_VALUE (ACPI_NS_NORMAL);
985     }
986
987     return_VALUE (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
988 }
989
990
991 /*******************************************************************************
992  *
993  * FUNCTION:    AcpiNsGetNodeByPath
994  *
995  * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
996  *                            \ (backslash) and ^ (carat) prefixes, and the
997  *                            . (period) to separate segments are supported.
998  *              StartNode   - Root of subtree to be searched, or NS_ALL for the
999  *                            root of the name space.  If Name is fully
1000  *                            qualified (first INT8 is '\'), the passed value
1001  *                            of Scope will not be accessed.
1002  *              Flags       - Used to indicate whether to perform upsearch or
1003  *                            not.
1004  *              ReturnNode  - Where the Node is returned
1005  *
1006  * DESCRIPTION: Look up a name relative to a given scope and return the
1007  *              corresponding Node.  NOTE: Scope can be null.
1008  *
1009  * MUTEX:       Locks namespace
1010  *
1011  ******************************************************************************/
1012
1013 ACPI_STATUS
1014 AcpiNsGetNodeByPath (
1015     char                    *Pathname,
1016     ACPI_NAMESPACE_NODE     *StartNode,
1017     UINT32                  Flags,
1018     ACPI_NAMESPACE_NODE     **ReturnNode)
1019 {
1020     ACPI_GENERIC_STATE      ScopeInfo;
1021     ACPI_STATUS             Status;
1022     char                    *InternalPath = NULL;
1023
1024
1025     ACPI_FUNCTION_TRACE_PTR ("NsGetNodeByPath", Pathname);
1026
1027
1028     if (Pathname)
1029     {
1030         /* Convert path to internal representation */
1031
1032         Status = AcpiNsInternalizeName (Pathname, &InternalPath);
1033         if (ACPI_FAILURE (Status))
1034         {
1035             return_ACPI_STATUS (Status);
1036         }
1037     }
1038
1039     /* Must lock namespace during lookup */
1040
1041     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1042     if (ACPI_FAILURE (Status))
1043     {
1044         return_ACPI_STATUS (Status);
1045     }
1046
1047     /* Setup lookup scope (search starting point) */
1048
1049     ScopeInfo.Scope.Node = StartNode;
1050
1051     /* Lookup the name in the namespace */
1052
1053     Status = AcpiNsLookup (&ScopeInfo, InternalPath,
1054                             ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
1055                             (Flags | ACPI_NS_DONT_OPEN_SCOPE),
1056                             NULL, ReturnNode);
1057     if (ACPI_FAILURE (Status))
1058     {
1059         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s, %s\n",
1060                 InternalPath, AcpiFormatException (Status)));
1061     }
1062
1063     /* Cleanup */
1064
1065     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1066
1067     if (InternalPath)
1068     {
1069         ACPI_MEM_FREE (InternalPath);
1070     }
1071     return_ACPI_STATUS (Status);
1072 }
1073
1074
1075 /*******************************************************************************
1076  *
1077  * FUNCTION:    AcpiNsFindParentName
1078  *
1079  * PARAMETERS:  *ChildNode             - Named Obj whose name is to be found
1080  *
1081  * RETURN:      The ACPI name
1082  *
1083  * DESCRIPTION: Search for the given obj in its parent scope and return the
1084  *              name segment, or "????" if the parent name can't be found
1085  *              (which "should not happen").
1086  *
1087  ******************************************************************************/
1088
1089 ACPI_NAME
1090 AcpiNsFindParentName (
1091     ACPI_NAMESPACE_NODE     *ChildNode)
1092 {
1093     ACPI_NAMESPACE_NODE     *ParentNode;
1094
1095
1096     ACPI_FUNCTION_TRACE ("NsFindParentName");
1097
1098
1099     if (ChildNode)
1100     {
1101         /* Valid entry.  Get the parent Node */
1102
1103         ParentNode = AcpiNsGetParentNode (ChildNode);
1104         if (ParentNode)
1105         {
1106             ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Parent of %p [%4.4s] is %p [%4.4s]\n",
1107                 ChildNode,  ChildNode->Name.Ascii,
1108                 ParentNode, ParentNode->Name.Ascii));
1109
1110             if (ParentNode->Name.Integer)
1111             {
1112                 return_VALUE ((ACPI_NAME) ParentNode->Name.Integer);
1113             }
1114         }
1115
1116         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "unable to find parent of %p (%4.4s)\n",
1117             ChildNode, ChildNode->Name.Ascii));
1118     }
1119
1120     return_VALUE (ACPI_UNKNOWN_NAME);
1121 }
1122
1123
1124 /*******************************************************************************
1125  *
1126  * FUNCTION:    AcpiNsGetParentNode
1127  *
1128  * PARAMETERS:  Node       - Current table entry
1129  *
1130  * RETURN:      Parent entry of the given entry
1131  *
1132  * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
1133  *
1134  ******************************************************************************/
1135
1136
1137 ACPI_NAMESPACE_NODE *
1138 AcpiNsGetParentNode (
1139     ACPI_NAMESPACE_NODE     *Node)
1140 {
1141     ACPI_FUNCTION_ENTRY ();
1142
1143
1144     if (!Node)
1145     {
1146         return (NULL);
1147     }
1148
1149     /*
1150      * Walk to the end of this peer list.
1151      * The last entry is marked with a flag and the peer
1152      * pointer is really a pointer back to the parent.
1153      * This saves putting a parent back pointer in each and
1154      * every named object!
1155      */
1156     while (!(Node->Flags & ANOBJ_END_OF_PEER_LIST))
1157     {
1158         Node = Node->Peer;
1159     }
1160
1161
1162     return (Node->Peer);
1163 }
1164
1165
1166 /*******************************************************************************
1167  *
1168  * FUNCTION:    AcpiNsGetNextValidNode
1169  *
1170  * PARAMETERS:  Node       - Current table entry
1171  *
1172  * RETURN:      Next valid Node in the linked node list.  NULL if no more valid
1173  *              nodess
1174  *
1175  * DESCRIPTION: Find the next valid node within a name table.
1176  *              Useful for implementing NULL-end-of-list loops.
1177  *
1178  ******************************************************************************/
1179
1180
1181 ACPI_NAMESPACE_NODE *
1182 AcpiNsGetNextValidNode (
1183     ACPI_NAMESPACE_NODE     *Node)
1184 {
1185
1186     /* If we are at the end of this peer list, return NULL */
1187
1188     if (Node->Flags & ANOBJ_END_OF_PEER_LIST)
1189     {
1190         return NULL;
1191     }
1192
1193     /* Otherwise just return the next peer */
1194
1195     return (Node->Peer);
1196 }
1197
1198