nsutils.c revision 11225:eb6056029d84
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
129static BOOLEAN
130AcpiNsValidPathSeparator (
131    char                    Sep);
132
133#ifdef ACPI_OBSOLETE_FUNCTIONS
134ACPI_NAME
135AcpiNsFindParentName (
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
155void
156AcpiNsReportError (
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
222void
223AcpiNsReportMethodError (
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
264void
265AcpiNsPrintNodePathname (
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
309BOOLEAN
310AcpiNsValidRootPrefix (
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
330static BOOLEAN
331AcpiNsValidPathSeparator (
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
351ACPI_OBJECT_TYPE
352AcpiNsGetType (
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
381UINT32
382AcpiNsLocal (
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
414void
415AcpiNsGetInternalNameLength (
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
497ACPI_STATUS
498AcpiNsBuildInternalName (
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
635ACPI_STATUS
636AcpiNsInternalizeName (
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
700ACPI_STATUS
701AcpiNsExternalizeName (
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
877ACPI_NAMESPACE_NODE *
878AcpiNsMapHandleToNode (
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
915ACPI_HANDLE
916AcpiNsConvertEntryToHandle (
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
957void
958AcpiNsTerminate (
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
998UINT32
999AcpiNsOpensScope (
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
1039ACPI_STATUS
1040AcpiNsGetNode (
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, ACPI_CAST_PTR (char, 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
1097Cleanup:
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
1115ACPI_NAMESPACE_NODE *
1116AcpiNsGetParentNode (
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
1155ACPI_NAMESPACE_NODE *
1156AcpiNsGetNextValidNode (
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
1188ACPI_NAME
1189AcpiNsFindParentName (
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