167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
467754Smsmith *                        parents and siblings and Scope manipulation
567754Smsmith *
667754Smsmith *****************************************************************************/
767754Smsmith
8217365Sjkim/*
9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
1070243Smsmith * All rights reserved.
1167754Smsmith *
12217365Sjkim * Redistribution and use in source and binary forms, with or without
13217365Sjkim * modification, are permitted provided that the following conditions
14217365Sjkim * are met:
15217365Sjkim * 1. Redistributions of source code must retain the above copyright
16217365Sjkim *    notice, this list of conditions, and the following disclaimer,
17217365Sjkim *    without modification.
18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
20217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
21217365Sjkim *    including a substantially similar Disclaimer requirement for further
22217365Sjkim *    binary redistribution.
23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
24217365Sjkim *    of any contributors may be used to endorse or promote products derived
25217365Sjkim *    from this software without specific prior written permission.
2667754Smsmith *
27217365Sjkim * Alternatively, this software may be distributed under the terms of the
28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
29217365Sjkim * Software Foundation.
3067754Smsmith *
31217365Sjkim * NO WARRANTY
32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
43217365Sjkim */
4467754Smsmith
4567754Smsmith#define __NSUTILS_C__
4667754Smsmith
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50193341Sjkim#include <contrib/dev/acpica/include/amlcode.h>
5167754Smsmith
5277424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5391116Smsmith        ACPI_MODULE_NAME    ("nsutils")
5467754Smsmith
55151937Sjkim/* Local prototypes */
5667754Smsmith
57151937Sjkimstatic BOOLEAN
58151937SjkimAcpiNsValidPathSeparator (
59151937Sjkim    char                    Sep);
60151937Sjkim
61151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS
62151937SjkimACPI_NAME
63151937SjkimAcpiNsFindParentName (
64151937Sjkim    ACPI_NAMESPACE_NODE     *NodeToSearch);
65151937Sjkim#endif
66151937Sjkim
67151937Sjkim
6877424Smsmith/*******************************************************************************
6967754Smsmith *
70114237Snjl * FUNCTION:    AcpiNsPrintNodePathname
71114237Snjl *
72151937Sjkim * PARAMETERS:  Node            - Object
73151937Sjkim *              Message         - Prefix message
74114237Snjl *
75114237Snjl * DESCRIPTION: Print an object's full namespace pathname
76114237Snjl *              Manages allocation/freeing of a pathname buffer
77114237Snjl *
78114237Snjl ******************************************************************************/
79114237Snjl
80114237Snjlvoid
81114237SnjlAcpiNsPrintNodePathname (
82114237Snjl    ACPI_NAMESPACE_NODE     *Node,
83193267Sjkim    const char              *Message)
84114237Snjl{
85114237Snjl    ACPI_BUFFER             Buffer;
86114237Snjl    ACPI_STATUS             Status;
87114237Snjl
88114237Snjl
89123315Snjl    if (!Node)
90123315Snjl    {
91123315Snjl        AcpiOsPrintf ("[NULL NAME]");
92123315Snjl        return;
93123315Snjl    }
94123315Snjl
95138287Smarks    /* Convert handle to full pathname and print it (with supplied message) */
96114237Snjl
97114237Snjl    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
98114237Snjl
99114237Snjl    Status = AcpiNsHandleToPathname (Node, &Buffer);
100114237Snjl    if (ACPI_SUCCESS (Status))
101114237Snjl    {
102151937Sjkim        if (Message)
103117521Snjl        {
104151937Sjkim            AcpiOsPrintf ("%s ", Message);
105117521Snjl        }
106117521Snjl
107117521Snjl        AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
108167802Sjkim        ACPI_FREE (Buffer.Pointer);
109114237Snjl    }
110114237Snjl}
111114237Snjl
112114237Snjl
113114237Snjl/*******************************************************************************
114114237Snjl *
11567754Smsmith * FUNCTION:    AcpiNsValidRootPrefix
11667754Smsmith *
11767754Smsmith * PARAMETERS:  Prefix          - Character to be checked
11867754Smsmith *
11967754Smsmith * RETURN:      TRUE if a valid prefix
12067754Smsmith *
12167754Smsmith * DESCRIPTION: Check if a character is a valid ACPI Root prefix
12267754Smsmith *
12377424Smsmith ******************************************************************************/
12467754Smsmith
12567754SmsmithBOOLEAN
12667754SmsmithAcpiNsValidRootPrefix (
127114237Snjl    char                    Prefix)
12867754Smsmith{
12967754Smsmith
13067754Smsmith    return ((BOOLEAN) (Prefix == '\\'));
13167754Smsmith}
13267754Smsmith
13367754Smsmith
13477424Smsmith/*******************************************************************************
13567754Smsmith *
13667754Smsmith * FUNCTION:    AcpiNsValidPathSeparator
13767754Smsmith *
138151937Sjkim * PARAMETERS:  Sep         - Character to be checked
13967754Smsmith *
14067754Smsmith * RETURN:      TRUE if a valid path separator
14167754Smsmith *
14267754Smsmith * DESCRIPTION: Check if a character is a valid ACPI path separator
14367754Smsmith *
14477424Smsmith ******************************************************************************/
14567754Smsmith
146151937Sjkimstatic BOOLEAN
14767754SmsmithAcpiNsValidPathSeparator (
148114237Snjl    char                    Sep)
14967754Smsmith{
15067754Smsmith
15167754Smsmith    return ((BOOLEAN) (Sep == '.'));
15267754Smsmith}
15367754Smsmith
15467754Smsmith
15577424Smsmith/*******************************************************************************
15667754Smsmith *
15767754Smsmith * FUNCTION:    AcpiNsGetType
15867754Smsmith *
159151937Sjkim * PARAMETERS:  Node        - Parent Node to be examined
16067754Smsmith *
16167754Smsmith * RETURN:      Type field from Node whose handle is passed
16267754Smsmith *
163151937Sjkim * DESCRIPTION: Return the type of a Namespace node
164151937Sjkim *
16577424Smsmith ******************************************************************************/
16667754Smsmith
16791116SmsmithACPI_OBJECT_TYPE
16867754SmsmithAcpiNsGetType (
16977424Smsmith    ACPI_NAMESPACE_NODE     *Node)
17067754Smsmith{
171167802Sjkim    ACPI_FUNCTION_TRACE (NsGetType);
17267754Smsmith
17367754Smsmith
17477424Smsmith    if (!Node)
17567754Smsmith    {
176167802Sjkim        ACPI_WARNING ((AE_INFO, "Null Node parameter"));
177151937Sjkim        return_UINT32 (ACPI_TYPE_ANY);
17867754Smsmith    }
17967754Smsmith
180151937Sjkim    return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type);
18167754Smsmith}
18267754Smsmith
18367754Smsmith
18477424Smsmith/*******************************************************************************
18567754Smsmith *
18667754Smsmith * FUNCTION:    AcpiNsLocal
18767754Smsmith *
188151937Sjkim * PARAMETERS:  Type        - A namespace object type
18967754Smsmith *
19067754Smsmith * RETURN:      LOCAL if names must be found locally in objects of the
19167754Smsmith *              passed type, 0 if enclosing scopes should be searched
19267754Smsmith *
193151937Sjkim * DESCRIPTION: Returns scope rule for the given object type.
194151937Sjkim *
19577424Smsmith ******************************************************************************/
19667754Smsmith
19767754SmsmithUINT32
19867754SmsmithAcpiNsLocal (
19991116Smsmith    ACPI_OBJECT_TYPE        Type)
20067754Smsmith{
201167802Sjkim    ACPI_FUNCTION_TRACE (NsLocal);
20267754Smsmith
20367754Smsmith
20477424Smsmith    if (!AcpiUtValidObjectType (Type))
20567754Smsmith    {
20667754Smsmith        /* Type code out of range  */
20767754Smsmith
208204773Sjkim        ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
209151937Sjkim        return_UINT32 (ACPI_NS_NORMAL);
21067754Smsmith    }
21167754Smsmith
212151937Sjkim    return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
21367754Smsmith}
21467754Smsmith
21567754Smsmith
21677424Smsmith/*******************************************************************************
21767754Smsmith *
21877424Smsmith * FUNCTION:    AcpiNsGetInternalNameLength
21967754Smsmith *
22083174Smsmith * PARAMETERS:  Info            - Info struct initialized with the
22177424Smsmith *                                external name pointer.
22267754Smsmith *
223151937Sjkim * RETURN:      None
22467754Smsmith *
22583174Smsmith * DESCRIPTION: Calculate the length of the internal (AML) namestring
22677424Smsmith *              corresponding to the external (ASL) namestring.
22767754Smsmith *
22877424Smsmith ******************************************************************************/
22967754Smsmith
23099679Siwasakivoid
23177424SmsmithAcpiNsGetInternalNameLength (
23277424Smsmith    ACPI_NAMESTRING_INFO    *Info)
23367754Smsmith{
234193267Sjkim    const char              *NextExternalChar;
23567754Smsmith    UINT32                  i;
23667754Smsmith
23767754Smsmith
23891116Smsmith    ACPI_FUNCTION_ENTRY ();
23983174Smsmith
24083174Smsmith
24177424Smsmith    NextExternalChar = Info->ExternalName;
24277424Smsmith    Info->NumCarats = 0;
24377424Smsmith    Info->NumSegments = 0;
24477424Smsmith    Info->FullyQualified = FALSE;
24583174Smsmith
24667754Smsmith    /*
247138287Smarks     * For the internal name, the required length is 4 bytes per segment, plus
248138287Smarks     * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null
249138287Smarks     * (which is not really needed, but no there's harm in putting it there)
25067754Smsmith     *
251138287Smarks     * strlen() + 1 covers the first NameSeg, which has no path separator
25267754Smsmith     */
253193267Sjkim    if (AcpiNsValidRootPrefix (*NextExternalChar))
25467754Smsmith    {
25577424Smsmith        Info->FullyQualified = TRUE;
25677424Smsmith        NextExternalChar++;
257193267Sjkim
258193267Sjkim        /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
259193267Sjkim
260193267Sjkim        while (AcpiNsValidRootPrefix (*NextExternalChar))
261193267Sjkim        {
262193267Sjkim            NextExternalChar++;
263193267Sjkim        }
26467754Smsmith    }
26569450Smsmith    else
26669450Smsmith    {
267193267Sjkim        /* Handle Carat prefixes */
268193267Sjkim
26977424Smsmith        while (*NextExternalChar == '^')
27069450Smsmith        {
27177424Smsmith            Info->NumCarats++;
27277424Smsmith            NextExternalChar++;
27369450Smsmith        }
27469450Smsmith    }
27569450Smsmith
27667754Smsmith    /*
277138287Smarks     * Determine the number of ACPI name "segments" by counting the number of
278138287Smarks     * path separators within the string. Start with one segment since the
279138287Smarks     * segment count is [(# separators) + 1], and zero separators is ok.
28067754Smsmith     */
28177424Smsmith    if (*NextExternalChar)
28267754Smsmith    {
28377424Smsmith        Info->NumSegments = 1;
28477424Smsmith        for (i = 0; NextExternalChar[i]; i++)
28567754Smsmith        {
28677424Smsmith            if (AcpiNsValidPathSeparator (NextExternalChar[i]))
28769450Smsmith            {
28877424Smsmith                Info->NumSegments++;
28969450Smsmith            }
29067754Smsmith        }
29167754Smsmith    }
29267754Smsmith
29383174Smsmith    Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
29477424Smsmith                    4 + Info->NumCarats;
29567754Smsmith
29677424Smsmith    Info->NextExternalChar = NextExternalChar;
29777424Smsmith}
29867754Smsmith
29967754Smsmith
30077424Smsmith/*******************************************************************************
30177424Smsmith *
30277424Smsmith * FUNCTION:    AcpiNsBuildInternalName
30377424Smsmith *
30477424Smsmith * PARAMETERS:  Info            - Info struct fully initialized
30577424Smsmith *
30677424Smsmith * RETURN:      Status
30777424Smsmith *
30883174Smsmith * DESCRIPTION: Construct the internal (AML) namestring
30977424Smsmith *              corresponding to the external (ASL) namestring.
31077424Smsmith *
31177424Smsmith ******************************************************************************/
31277424Smsmith
31377424SmsmithACPI_STATUS
31477424SmsmithAcpiNsBuildInternalName (
31577424Smsmith    ACPI_NAMESTRING_INFO    *Info)
31677424Smsmith{
31777424Smsmith    UINT32                  NumSegments = Info->NumSegments;
318114237Snjl    char                    *InternalName = Info->InternalName;
319193267Sjkim    const char              *ExternalName = Info->NextExternalChar;
320114237Snjl    char                    *Result = NULL;
321193267Sjkim    UINT32                  i;
32277424Smsmith
32377424Smsmith
324167802Sjkim    ACPI_FUNCTION_TRACE (NsBuildInternalName);
32577424Smsmith
32683174Smsmith
32767754Smsmith    /* Setup the correct prefixes, counts, and pointers */
32867754Smsmith
32977424Smsmith    if (Info->FullyQualified)
33067754Smsmith    {
33167754Smsmith        InternalName[0] = '\\';
33269450Smsmith
33369450Smsmith        if (NumSegments <= 1)
33469450Smsmith        {
33569450Smsmith            Result = &InternalName[1];
33669450Smsmith        }
33769450Smsmith        else if (NumSegments == 2)
33869450Smsmith        {
33969450Smsmith            InternalName[1] = AML_DUAL_NAME_PREFIX;
34069450Smsmith            Result = &InternalName[2];
34169450Smsmith        }
34269450Smsmith        else
34369450Smsmith        {
34469450Smsmith            InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
34569450Smsmith            InternalName[2] = (char) NumSegments;
34669450Smsmith            Result = &InternalName[3];
34769450Smsmith        }
34867754Smsmith    }
34967754Smsmith    else
35067754Smsmith    {
35169450Smsmith        /*
35269450Smsmith         * Not fully qualified.
35369450Smsmith         * Handle Carats first, then append the name segments
35469450Smsmith         */
35569450Smsmith        i = 0;
35677424Smsmith        if (Info->NumCarats)
35769450Smsmith        {
35877424Smsmith            for (i = 0; i < Info->NumCarats; i++)
35969450Smsmith            {
36069450Smsmith                InternalName[i] = '^';
36169450Smsmith            }
36269450Smsmith        }
36369450Smsmith
36491116Smsmith        if (NumSegments <= 1)
36569450Smsmith        {
36669450Smsmith            Result = &InternalName[i];
36769450Smsmith        }
36869450Smsmith        else if (NumSegments == 2)
36969450Smsmith        {
37069450Smsmith            InternalName[i] = AML_DUAL_NAME_PREFIX;
371193267Sjkim            Result = &InternalName[(ACPI_SIZE) i+1];
37269450Smsmith        }
37369450Smsmith        else
37469450Smsmith        {
37569450Smsmith            InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
376193267Sjkim            InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
377193267Sjkim            Result = &InternalName[(ACPI_SIZE) i+2];
37869450Smsmith        }
37967754Smsmith    }
38067754Smsmith
38167754Smsmith    /* Build the name (minus path separators) */
38267754Smsmith
38367754Smsmith    for (; NumSegments; NumSegments--)
38467754Smsmith    {
38567754Smsmith        for (i = 0; i < ACPI_NAME_SIZE; i++)
38667754Smsmith        {
38767754Smsmith            if (AcpiNsValidPathSeparator (*ExternalName) ||
38867754Smsmith               (*ExternalName == 0))
38967754Smsmith            {
39077424Smsmith                /* Pad the segment with underscore(s) if segment is short */
39167754Smsmith
39267754Smsmith                Result[i] = '_';
39367754Smsmith            }
39467754Smsmith            else
39567754Smsmith            {
39677424Smsmith                /* Convert the character to uppercase and save it */
39767754Smsmith
39899679Siwasaki                Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
39967754Smsmith                ExternalName++;
40067754Smsmith            }
40167754Smsmith        }
40267754Smsmith
40367754Smsmith        /* Now we must have a path separator, or the pathname is bad */
40467754Smsmith
40567754Smsmith        if (!AcpiNsValidPathSeparator (*ExternalName) &&
40667754Smsmith            (*ExternalName != 0))
40767754Smsmith        {
40867754Smsmith            return_ACPI_STATUS (AE_BAD_PARAMETER);
40967754Smsmith        }
41067754Smsmith
41167754Smsmith        /* Move on the next segment */
41267754Smsmith
41367754Smsmith        ExternalName++;
41467754Smsmith        Result += ACPI_NAME_SIZE;
41567754Smsmith    }
41667754Smsmith
41777424Smsmith    /* Terminate the string */
41867754Smsmith
41967754Smsmith    *Result = 0;
42067754Smsmith
42177424Smsmith    if (Info->FullyQualified)
42267754Smsmith    {
423123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
42499146Siwasaki            InternalName, InternalName));
42567754Smsmith    }
42667754Smsmith    else
42767754Smsmith    {
428123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
42999146Siwasaki            InternalName, InternalName));
43067754Smsmith    }
43167754Smsmith
43267754Smsmith    return_ACPI_STATUS (AE_OK);
43367754Smsmith}
43467754Smsmith
43567754Smsmith
43677424Smsmith/*******************************************************************************
43767754Smsmith *
43877424Smsmith * FUNCTION:    AcpiNsInternalizeName
43977424Smsmith *
44077424Smsmith * PARAMETERS:  *ExternalName           - External representation of name
44177424Smsmith *              **Converted Name        - Where to return the resulting
44277424Smsmith *                                        internal represention of the name
44377424Smsmith *
44477424Smsmith * RETURN:      Status
44577424Smsmith *
44677424Smsmith * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
44777424Smsmith *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
44877424Smsmith *
44977424Smsmith *******************************************************************************/
45077424Smsmith
45177424SmsmithACPI_STATUS
45277424SmsmithAcpiNsInternalizeName (
453193267Sjkim    const char              *ExternalName,
454114237Snjl    char                    **ConvertedName)
45577424Smsmith{
456114237Snjl    char                    *InternalName;
45777424Smsmith    ACPI_NAMESTRING_INFO    Info;
45877424Smsmith    ACPI_STATUS             Status;
45977424Smsmith
46077424Smsmith
461167802Sjkim    ACPI_FUNCTION_TRACE (NsInternalizeName);
46277424Smsmith
46377424Smsmith
46477424Smsmith    if ((!ExternalName)      ||
46577424Smsmith        (*ExternalName == 0) ||
46677424Smsmith        (!ConvertedName))
46777424Smsmith    {
46877424Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
46977424Smsmith    }
47077424Smsmith
47177424Smsmith    /* Get the length of the new internal name */
47277424Smsmith
47377424Smsmith    Info.ExternalName = ExternalName;
47477424Smsmith    AcpiNsGetInternalNameLength (&Info);
47577424Smsmith
47677424Smsmith    /* We need a segment to store the internal  name */
47777424Smsmith
478167802Sjkim    InternalName = ACPI_ALLOCATE_ZEROED (Info.Length);
47977424Smsmith    if (!InternalName)
48077424Smsmith    {
48177424Smsmith        return_ACPI_STATUS (AE_NO_MEMORY);
48277424Smsmith    }
48377424Smsmith
48477424Smsmith    /* Build the name */
48577424Smsmith
48677424Smsmith    Info.InternalName = InternalName;
48777424Smsmith    Status = AcpiNsBuildInternalName (&Info);
48877424Smsmith    if (ACPI_FAILURE (Status))
48977424Smsmith    {
490167802Sjkim        ACPI_FREE (InternalName);
49177424Smsmith        return_ACPI_STATUS (Status);
49277424Smsmith    }
49377424Smsmith
49477424Smsmith    *ConvertedName = InternalName;
49577424Smsmith    return_ACPI_STATUS (AE_OK);
49677424Smsmith}
49777424Smsmith
49877424Smsmith
49977424Smsmith/*******************************************************************************
50077424Smsmith *
50167754Smsmith * FUNCTION:    AcpiNsExternalizeName
50267754Smsmith *
503151937Sjkim * PARAMETERS:  InternalNameLength  - Lenth of the internal name below
504151937Sjkim *              InternalName        - Internal representation of name
505151937Sjkim *              ConvertedNameLength - Where the length is returned
506151937Sjkim *              ConvertedName       - Where the resulting external name
507151937Sjkim *                                    is returned
50867754Smsmith *
50967754Smsmith * RETURN:      Status
51067754Smsmith *
51167754Smsmith * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
512151937Sjkim *              to its external (printable) form (e.g. "\_PR_.CPU0")
51367754Smsmith *
51477424Smsmith ******************************************************************************/
51567754Smsmith
51667754SmsmithACPI_STATUS
51767754SmsmithAcpiNsExternalizeName (
51867754Smsmith    UINT32                  InternalNameLength,
519193267Sjkim    const char              *InternalName,
52067754Smsmith    UINT32                  *ConvertedNameLength,
52167754Smsmith    char                    **ConvertedName)
52267754Smsmith{
523193267Sjkim    UINT32                  NamesIndex = 0;
524193267Sjkim    UINT32                  NumSegments = 0;
525193267Sjkim    UINT32                  RequiredLength;
526193267Sjkim    UINT32                  PrefixLength = 0;
527193267Sjkim    UINT32                  i = 0;
528193267Sjkim    UINT32                  j = 0;
52967754Smsmith
53067754Smsmith
531167802Sjkim    ACPI_FUNCTION_TRACE (NsExternalizeName);
53267754Smsmith
53367754Smsmith
53467754Smsmith    if (!InternalNameLength     ||
53567754Smsmith        !InternalName           ||
53667754Smsmith        !ConvertedName)
53767754Smsmith    {
53867754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
53967754Smsmith    }
54067754Smsmith
541193267Sjkim    /* Check for a prefix (one '\' | one or more '^') */
542193267Sjkim
54367754Smsmith    switch (InternalName[0])
54467754Smsmith    {
54567754Smsmith    case '\\':
54667754Smsmith        PrefixLength = 1;
54767754Smsmith        break;
54867754Smsmith
54967754Smsmith    case '^':
55067754Smsmith        for (i = 0; i < InternalNameLength; i++)
55167754Smsmith        {
552102550Siwasaki            if (InternalName[i] == '^')
55367754Smsmith            {
55467754Smsmith                PrefixLength = i + 1;
55567754Smsmith            }
556102550Siwasaki            else
557102550Siwasaki            {
558102550Siwasaki                break;
559102550Siwasaki            }
56067754Smsmith        }
56167754Smsmith
56267754Smsmith        if (i == InternalNameLength)
56367754Smsmith        {
56467754Smsmith            PrefixLength = i;
56567754Smsmith        }
56667754Smsmith
56767754Smsmith        break;
56899679Siwasaki
56999679Siwasaki    default:
57099679Siwasaki        break;
57167754Smsmith    }
57267754Smsmith
57367754Smsmith    /*
574193267Sjkim     * Check for object names. Note that there could be 0-255 of these
57567754Smsmith     * 4-byte elements.
57667754Smsmith     */
57767754Smsmith    if (PrefixLength < InternalNameLength)
57867754Smsmith    {
57967754Smsmith        switch (InternalName[PrefixLength])
58067754Smsmith        {
58191116Smsmith        case AML_MULTI_NAME_PREFIX_OP:
58267754Smsmith
58391116Smsmith            /* <count> 4-byte names */
58467754Smsmith
58567754Smsmith            NamesIndex = PrefixLength + 2;
586193267Sjkim            NumSegments = (UINT8)
587193267Sjkim                InternalName[(ACPI_SIZE) PrefixLength + 1];
58867754Smsmith            break;
58967754Smsmith
59091116Smsmith        case AML_DUAL_NAME_PREFIX:
59167754Smsmith
59291116Smsmith            /* Two 4-byte names */
59367754Smsmith
59467754Smsmith            NamesIndex = PrefixLength + 1;
59591116Smsmith            NumSegments = 2;
59667754Smsmith            break;
59767754Smsmith
59891116Smsmith        case 0:
59967754Smsmith
60091116Smsmith            /* NullName */
60167754Smsmith
60267754Smsmith            NamesIndex = 0;
60391116Smsmith            NumSegments = 0;
60467754Smsmith            break;
60567754Smsmith
60691116Smsmith        default:
60767754Smsmith
60891116Smsmith            /* one 4-byte name */
60967754Smsmith
61067754Smsmith            NamesIndex = PrefixLength;
61191116Smsmith            NumSegments = 1;
61267754Smsmith            break;
61367754Smsmith        }
61467754Smsmith    }
61567754Smsmith
61667754Smsmith    /*
61767754Smsmith     * Calculate the length of ConvertedName, which equals the length
61867754Smsmith     * of the prefix, length of all object names, length of any required
61967754Smsmith     * punctuation ('.') between object names, plus the NULL terminator.
62067754Smsmith     */
62191116Smsmith    RequiredLength = PrefixLength + (4 * NumSegments) +
62291116Smsmith                        ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
62367754Smsmith
62467754Smsmith    /*
62567754Smsmith     * Check to see if we're still in bounds.  If not, there's a problem
62667754Smsmith     * with InternalName (invalid format).
62767754Smsmith     */
62891116Smsmith    if (RequiredLength > InternalNameLength)
62967754Smsmith    {
630167802Sjkim        ACPI_ERROR ((AE_INFO, "Invalid internal name"));
63167754Smsmith        return_ACPI_STATUS (AE_BAD_PATHNAME);
63267754Smsmith    }
63367754Smsmith
634193267Sjkim    /* Build the ConvertedName */
635193267Sjkim
636167802Sjkim    *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength);
63767754Smsmith    if (!(*ConvertedName))
63867754Smsmith    {
63967754Smsmith        return_ACPI_STATUS (AE_NO_MEMORY);
64067754Smsmith    }
64167754Smsmith
64267754Smsmith    j = 0;
64367754Smsmith
64467754Smsmith    for (i = 0; i < PrefixLength; i++)
64567754Smsmith    {
64667754Smsmith        (*ConvertedName)[j++] = InternalName[i];
64767754Smsmith    }
64867754Smsmith
64991116Smsmith    if (NumSegments > 0)
65067754Smsmith    {
65191116Smsmith        for (i = 0; i < NumSegments; i++)
65267754Smsmith        {
65367754Smsmith            if (i > 0)
65467754Smsmith            {
65567754Smsmith                (*ConvertedName)[j++] = '.';
65667754Smsmith            }
65767754Smsmith
65867754Smsmith            (*ConvertedName)[j++] = InternalName[NamesIndex++];
65967754Smsmith            (*ConvertedName)[j++] = InternalName[NamesIndex++];
66067754Smsmith            (*ConvertedName)[j++] = InternalName[NamesIndex++];
66167754Smsmith            (*ConvertedName)[j++] = InternalName[NamesIndex++];
66267754Smsmith        }
66367754Smsmith    }
66467754Smsmith
66591116Smsmith    if (ConvertedNameLength)
66691116Smsmith    {
66799679Siwasaki        *ConvertedNameLength = (UINT32) RequiredLength;
66891116Smsmith    }
66991116Smsmith
67067754Smsmith    return_ACPI_STATUS (AE_OK);
67167754Smsmith}
67267754Smsmith
67367754Smsmith
67477424Smsmith/*******************************************************************************
67567754Smsmith *
676200553Sjkim * FUNCTION:    AcpiNsValidateHandle
67767754Smsmith *
678200553Sjkim * PARAMETERS:  Handle          - Handle to be validated and typecast to a
679200553Sjkim *                                namespace node.
68067754Smsmith *
681200553Sjkim * RETURN:      A pointer to a namespace node
68267754Smsmith *
683200553Sjkim * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
684200553Sjkim *              cases for the root node.
68567754Smsmith *
686200553Sjkim * NOTE: Real integer handles would allow for more verification
687151937Sjkim *       and keep all pointers within this subsystem - however this introduces
688200553Sjkim *       more overhead and has not been necessary to this point. Drivers
689200553Sjkim *       holding handles are typically notified before a node becomes invalid
690200553Sjkim *       due to a table unload.
69187031Smsmith *
69277424Smsmith ******************************************************************************/
69367754Smsmith
69467754SmsmithACPI_NAMESPACE_NODE *
695200553SjkimAcpiNsValidateHandle (
69667754Smsmith    ACPI_HANDLE             Handle)
69767754Smsmith{
69867754Smsmith
69991116Smsmith    ACPI_FUNCTION_ENTRY ();
70083174Smsmith
70183174Smsmith
702193267Sjkim    /* Parameter validation */
703193267Sjkim
704167802Sjkim    if ((!Handle) || (Handle == ACPI_ROOT_OBJECT))
70567754Smsmith    {
70667754Smsmith        return (AcpiGbl_RootNode);
70767754Smsmith    }
70867754Smsmith
70967754Smsmith    /* We can at least attempt to verify the handle */
71067754Smsmith
71191116Smsmith    if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
71267754Smsmith    {
71367754Smsmith        return (NULL);
71467754Smsmith    }
71567754Smsmith
716167802Sjkim    return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
71767754Smsmith}
71867754Smsmith
71967754Smsmith
72077424Smsmith/*******************************************************************************
72167754Smsmith *
72267754Smsmith * FUNCTION:    AcpiNsTerminate
72367754Smsmith *
72467754Smsmith * PARAMETERS:  none
72567754Smsmith *
72667754Smsmith * RETURN:      none
72767754Smsmith *
728151937Sjkim * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
72967754Smsmith *
73067754Smsmith ******************************************************************************/
73167754Smsmith
73267754Smsmithvoid
733151937SjkimAcpiNsTerminate (
734151937Sjkim    void)
73567754Smsmith{
73667754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
73767754Smsmith
73867754Smsmith
739167802Sjkim    ACPI_FUNCTION_TRACE (NsTerminate);
74067754Smsmith
74167754Smsmith
74267754Smsmith    /*
743117521Snjl     * 1) Free the entire namespace -- all nodes and objects
74477424Smsmith     *
745117521Snjl     * Delete all object descriptors attached to namepsace nodes
74667754Smsmith     */
747117521Snjl    AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
74867754Smsmith
749117521Snjl    /* Detach any objects attached to the root */
75067754Smsmith
751117521Snjl    ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode);
75267754Smsmith    if (ObjDesc)
75367754Smsmith    {
754117521Snjl        AcpiNsDetachObject (AcpiGbl_RootNode);
75567754Smsmith    }
75667754Smsmith
75782367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
75867754Smsmith    return_VOID;
75967754Smsmith}
76067754Smsmith
76167754Smsmith
76277424Smsmith/*******************************************************************************
76367754Smsmith *
76467754Smsmith * FUNCTION:    AcpiNsOpensScope
76567754Smsmith *
76667754Smsmith * PARAMETERS:  Type        - A valid namespace type
76767754Smsmith *
76867754Smsmith * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
76967754Smsmith *              to the ACPI specification, else 0
77067754Smsmith *
77177424Smsmith ******************************************************************************/
77267754Smsmith
77367754SmsmithUINT32
77467754SmsmithAcpiNsOpensScope (
77591116Smsmith    ACPI_OBJECT_TYPE        Type)
77667754Smsmith{
777167802Sjkim    ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type));
77867754Smsmith
77967754Smsmith
78077424Smsmith    if (!AcpiUtValidObjectType (Type))
78167754Smsmith    {
78267754Smsmith        /* type code out of range  */
78367754Smsmith
784204773Sjkim        ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
785151937Sjkim        return_UINT32 (ACPI_NS_NORMAL);
78667754Smsmith    }
78767754Smsmith
788151937Sjkim    return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
78967754Smsmith}
79067754Smsmith
79167754Smsmith
79277424Smsmith/*******************************************************************************
79367754Smsmith *
794167802Sjkim * FUNCTION:    AcpiNsGetNode
79567754Smsmith *
79667754Smsmith * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
79767754Smsmith *                            \ (backslash) and ^ (carat) prefixes, and the
79867754Smsmith *                            . (period) to separate segments are supported.
799167802Sjkim *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
80067754Smsmith *                            root of the name space.  If Name is fully
80167754Smsmith *                            qualified (first INT8 is '\'), the passed value
80267754Smsmith *                            of Scope will not be accessed.
80391116Smsmith *              Flags       - Used to indicate whether to perform upsearch or
80491116Smsmith *                            not.
80567754Smsmith *              ReturnNode  - Where the Node is returned
80667754Smsmith *
80767754Smsmith * DESCRIPTION: Look up a name relative to a given scope and return the
80867754Smsmith *              corresponding Node.  NOTE: Scope can be null.
80967754Smsmith *
81067754Smsmith * MUTEX:       Locks namespace
81167754Smsmith *
81277424Smsmith ******************************************************************************/
81367754Smsmith
81467754SmsmithACPI_STATUS
815167802SjkimAcpiNsGetNode (
816167802Sjkim    ACPI_NAMESPACE_NODE     *PrefixNode,
817193267Sjkim    const char              *Pathname,
81891116Smsmith    UINT32                  Flags,
81967754Smsmith    ACPI_NAMESPACE_NODE     **ReturnNode)
82067754Smsmith{
82167754Smsmith    ACPI_GENERIC_STATE      ScopeInfo;
82267754Smsmith    ACPI_STATUS             Status;
823167802Sjkim    char                    *InternalPath;
82467754Smsmith
82567754Smsmith
826193267Sjkim    ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
82767754Smsmith
82867754Smsmith
829167802Sjkim    if (!Pathname)
83067754Smsmith    {
831167802Sjkim        *ReturnNode = PrefixNode;
832167802Sjkim        if (!PrefixNode)
833114237Snjl        {
834167802Sjkim            *ReturnNode = AcpiGbl_RootNode;
835114237Snjl        }
836167802Sjkim        return_ACPI_STATUS (AE_OK);
83767754Smsmith    }
83867754Smsmith
839167802Sjkim    /* Convert path to internal representation */
840167802Sjkim
841167802Sjkim    Status = AcpiNsInternalizeName (Pathname, &InternalPath);
842167802Sjkim    if (ACPI_FAILURE (Status))
843167802Sjkim    {
844167802Sjkim        return_ACPI_STATUS (Status);
845167802Sjkim    }
846167802Sjkim
84791116Smsmith    /* Must lock namespace during lookup */
84867754Smsmith
84991116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
85091116Smsmith    if (ACPI_FAILURE (Status))
85191116Smsmith    {
852126372Snjl        goto Cleanup;
85391116Smsmith    }
85467754Smsmith
85569746Smsmith    /* Setup lookup scope (search starting point) */
85667754Smsmith
857167802Sjkim    ScopeInfo.Scope.Node = PrefixNode;
85867754Smsmith
85967754Smsmith    /* Lookup the name in the namespace */
86067754Smsmith
861167802Sjkim    Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
862167802Sjkim                ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
863167802Sjkim                NULL, ReturnNode);
86467754Smsmith    if (ACPI_FAILURE (Status))
86567754Smsmith    {
866193267Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
867167802Sjkim                Pathname, AcpiFormatException (Status)));
86867754Smsmith    }
86967754Smsmith
87091116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
871114237Snjl
872126372SnjlCleanup:
873167802Sjkim    ACPI_FREE (InternalPath);
87467754Smsmith    return_ACPI_STATUS (Status);
87567754Smsmith}
876