167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
467754Smsmith *                        parents and siblings and Scope manipulation
567754Smsmith *
667754Smsmith *****************************************************************************/
767754Smsmith
8217365Sjkim/*
9306536Sjkim * Copyright (C) 2000 - 2016, 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
45193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
46193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
47193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48193341Sjkim#include <contrib/dev/acpica/include/amlcode.h>
4967754Smsmith
5077424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5191116Smsmith        ACPI_MODULE_NAME    ("nsutils")
5267754Smsmith
53151937Sjkim/* Local prototypes */
5467754Smsmith
55151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS
56151937SjkimACPI_NAME
57151937SjkimAcpiNsFindParentName (
58151937Sjkim    ACPI_NAMESPACE_NODE     *NodeToSearch);
59151937Sjkim#endif
60151937Sjkim
61151937Sjkim
6277424Smsmith/*******************************************************************************
6367754Smsmith *
64114237Snjl * FUNCTION:    AcpiNsPrintNodePathname
65114237Snjl *
66151937Sjkim * PARAMETERS:  Node            - Object
67151937Sjkim *              Message         - Prefix message
68114237Snjl *
69114237Snjl * DESCRIPTION: Print an object's full namespace pathname
70114237Snjl *              Manages allocation/freeing of a pathname buffer
71114237Snjl *
72114237Snjl ******************************************************************************/
73114237Snjl
74114237Snjlvoid
75114237SnjlAcpiNsPrintNodePathname (
76114237Snjl    ACPI_NAMESPACE_NODE     *Node,
77193267Sjkim    const char              *Message)
78114237Snjl{
79114237Snjl    ACPI_BUFFER             Buffer;
80114237Snjl    ACPI_STATUS             Status;
81114237Snjl
82114237Snjl
83123315Snjl    if (!Node)
84123315Snjl    {
85123315Snjl        AcpiOsPrintf ("[NULL NAME]");
86123315Snjl        return;
87123315Snjl    }
88123315Snjl
89138287Smarks    /* Convert handle to full pathname and print it (with supplied message) */
90114237Snjl
91114237Snjl    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
92114237Snjl
93306536Sjkim    Status = AcpiNsHandleToPathname (Node, &Buffer, TRUE);
94114237Snjl    if (ACPI_SUCCESS (Status))
95114237Snjl    {
96151937Sjkim        if (Message)
97117521Snjl        {
98151937Sjkim            AcpiOsPrintf ("%s ", Message);
99117521Snjl        }
100117521Snjl
101117521Snjl        AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
102167802Sjkim        ACPI_FREE (Buffer.Pointer);
103114237Snjl    }
104114237Snjl}
105114237Snjl
106114237Snjl
107114237Snjl/*******************************************************************************
108114237Snjl *
10967754Smsmith * FUNCTION:    AcpiNsGetType
11067754Smsmith *
111151937Sjkim * PARAMETERS:  Node        - Parent Node to be examined
11267754Smsmith *
11367754Smsmith * RETURN:      Type field from Node whose handle is passed
11467754Smsmith *
115151937Sjkim * DESCRIPTION: Return the type of a Namespace node
116151937Sjkim *
11777424Smsmith ******************************************************************************/
11867754Smsmith
11991116SmsmithACPI_OBJECT_TYPE
12067754SmsmithAcpiNsGetType (
12177424Smsmith    ACPI_NAMESPACE_NODE     *Node)
12267754Smsmith{
123167802Sjkim    ACPI_FUNCTION_TRACE (NsGetType);
12467754Smsmith
12567754Smsmith
12677424Smsmith    if (!Node)
12767754Smsmith    {
128167802Sjkim        ACPI_WARNING ((AE_INFO, "Null Node parameter"));
129246849Sjkim        return_UINT8 (ACPI_TYPE_ANY);
13067754Smsmith    }
13167754Smsmith
132246849Sjkim    return_UINT8 (Node->Type);
13367754Smsmith}
13467754Smsmith
13567754Smsmith
13677424Smsmith/*******************************************************************************
13767754Smsmith *
13867754Smsmith * FUNCTION:    AcpiNsLocal
13967754Smsmith *
140151937Sjkim * PARAMETERS:  Type        - A namespace object type
14167754Smsmith *
14267754Smsmith * RETURN:      LOCAL if names must be found locally in objects of the
14367754Smsmith *              passed type, 0 if enclosing scopes should be searched
14467754Smsmith *
145151937Sjkim * DESCRIPTION: Returns scope rule for the given object type.
146151937Sjkim *
14777424Smsmith ******************************************************************************/
14867754Smsmith
14967754SmsmithUINT32
15067754SmsmithAcpiNsLocal (
15191116Smsmith    ACPI_OBJECT_TYPE        Type)
15267754Smsmith{
153167802Sjkim    ACPI_FUNCTION_TRACE (NsLocal);
15467754Smsmith
15567754Smsmith
15677424Smsmith    if (!AcpiUtValidObjectType (Type))
15767754Smsmith    {
15867754Smsmith        /* Type code out of range  */
15967754Smsmith
160204773Sjkim        ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
161246849Sjkim        return_UINT32 (ACPI_NS_NORMAL);
16267754Smsmith    }
16367754Smsmith
164246849Sjkim    return_UINT32 (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
16567754Smsmith}
16667754Smsmith
16767754Smsmith
16877424Smsmith/*******************************************************************************
16967754Smsmith *
17077424Smsmith * FUNCTION:    AcpiNsGetInternalNameLength
17167754Smsmith *
17283174Smsmith * PARAMETERS:  Info            - Info struct initialized with the
17377424Smsmith *                                external name pointer.
17467754Smsmith *
175151937Sjkim * RETURN:      None
17667754Smsmith *
17783174Smsmith * DESCRIPTION: Calculate the length of the internal (AML) namestring
17877424Smsmith *              corresponding to the external (ASL) namestring.
17967754Smsmith *
18077424Smsmith ******************************************************************************/
18167754Smsmith
18299679Siwasakivoid
18377424SmsmithAcpiNsGetInternalNameLength (
18477424Smsmith    ACPI_NAMESTRING_INFO    *Info)
18567754Smsmith{
186193267Sjkim    const char              *NextExternalChar;
18767754Smsmith    UINT32                  i;
18867754Smsmith
18967754Smsmith
19091116Smsmith    ACPI_FUNCTION_ENTRY ();
19183174Smsmith
19283174Smsmith
19377424Smsmith    NextExternalChar = Info->ExternalName;
19477424Smsmith    Info->NumCarats = 0;
19577424Smsmith    Info->NumSegments = 0;
19677424Smsmith    Info->FullyQualified = FALSE;
19783174Smsmith
19867754Smsmith    /*
199306536Sjkim     * For the internal name, the required length is 4 bytes per segment,
200306536Sjkim     * plus 1 each for RootPrefix, MultiNamePrefixOp, segment count,
201306536Sjkim     * trailing null (which is not really needed, but no there's harm in
202306536Sjkim     * putting it there)
20367754Smsmith     *
204138287Smarks     * strlen() + 1 covers the first NameSeg, which has no path separator
20567754Smsmith     */
206245582Sjkim    if (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
20767754Smsmith    {
20877424Smsmith        Info->FullyQualified = TRUE;
20977424Smsmith        NextExternalChar++;
210193267Sjkim
211193267Sjkim        /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
212193267Sjkim
213245582Sjkim        while (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
214193267Sjkim        {
215193267Sjkim            NextExternalChar++;
216193267Sjkim        }
21767754Smsmith    }
21869450Smsmith    else
21969450Smsmith    {
220193267Sjkim        /* Handle Carat prefixes */
221193267Sjkim
222245582Sjkim        while (ACPI_IS_PARENT_PREFIX (*NextExternalChar))
22369450Smsmith        {
22477424Smsmith            Info->NumCarats++;
22577424Smsmith            NextExternalChar++;
22669450Smsmith        }
22769450Smsmith    }
22869450Smsmith
22967754Smsmith    /*
230138287Smarks     * Determine the number of ACPI name "segments" by counting the number of
231138287Smarks     * path separators within the string. Start with one segment since the
232138287Smarks     * segment count is [(# separators) + 1], and zero separators is ok.
23367754Smsmith     */
23477424Smsmith    if (*NextExternalChar)
23567754Smsmith    {
23677424Smsmith        Info->NumSegments = 1;
23777424Smsmith        for (i = 0; NextExternalChar[i]; i++)
23867754Smsmith        {
239245582Sjkim            if (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i]))
24069450Smsmith            {
24177424Smsmith                Info->NumSegments++;
24269450Smsmith            }
24367754Smsmith        }
24467754Smsmith    }
24567754Smsmith
24683174Smsmith    Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
247306536Sjkim        4 + Info->NumCarats;
24867754Smsmith
24977424Smsmith    Info->NextExternalChar = NextExternalChar;
25077424Smsmith}
25167754Smsmith
25267754Smsmith
25377424Smsmith/*******************************************************************************
25477424Smsmith *
25577424Smsmith * FUNCTION:    AcpiNsBuildInternalName
25677424Smsmith *
25777424Smsmith * PARAMETERS:  Info            - Info struct fully initialized
25877424Smsmith *
25977424Smsmith * RETURN:      Status
26077424Smsmith *
26183174Smsmith * DESCRIPTION: Construct the internal (AML) namestring
26277424Smsmith *              corresponding to the external (ASL) namestring.
26377424Smsmith *
26477424Smsmith ******************************************************************************/
26577424Smsmith
26677424SmsmithACPI_STATUS
26777424SmsmithAcpiNsBuildInternalName (
26877424Smsmith    ACPI_NAMESTRING_INFO    *Info)
26977424Smsmith{
27077424Smsmith    UINT32                  NumSegments = Info->NumSegments;
271114237Snjl    char                    *InternalName = Info->InternalName;
272193267Sjkim    const char              *ExternalName = Info->NextExternalChar;
273114237Snjl    char                    *Result = NULL;
274193267Sjkim    UINT32                  i;
27577424Smsmith
27677424Smsmith
277167802Sjkim    ACPI_FUNCTION_TRACE (NsBuildInternalName);
27877424Smsmith
27983174Smsmith
28067754Smsmith    /* Setup the correct prefixes, counts, and pointers */
28167754Smsmith
28277424Smsmith    if (Info->FullyQualified)
28367754Smsmith    {
284245582Sjkim        InternalName[0] = AML_ROOT_PREFIX;
28569450Smsmith
28669450Smsmith        if (NumSegments <= 1)
28769450Smsmith        {
28869450Smsmith            Result = &InternalName[1];
28969450Smsmith        }
29069450Smsmith        else if (NumSegments == 2)
29169450Smsmith        {
29269450Smsmith            InternalName[1] = AML_DUAL_NAME_PREFIX;
29369450Smsmith            Result = &InternalName[2];
29469450Smsmith        }
29569450Smsmith        else
29669450Smsmith        {
29769450Smsmith            InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
29869450Smsmith            InternalName[2] = (char) NumSegments;
29969450Smsmith            Result = &InternalName[3];
30069450Smsmith        }
30167754Smsmith    }
30267754Smsmith    else
30367754Smsmith    {
30469450Smsmith        /*
30569450Smsmith         * Not fully qualified.
30669450Smsmith         * Handle Carats first, then append the name segments
30769450Smsmith         */
30869450Smsmith        i = 0;
30977424Smsmith        if (Info->NumCarats)
31069450Smsmith        {
31177424Smsmith            for (i = 0; i < Info->NumCarats; i++)
31269450Smsmith            {
313245582Sjkim                InternalName[i] = AML_PARENT_PREFIX;
31469450Smsmith            }
31569450Smsmith        }
31669450Smsmith
31791116Smsmith        if (NumSegments <= 1)
31869450Smsmith        {
31969450Smsmith            Result = &InternalName[i];
32069450Smsmith        }
32169450Smsmith        else if (NumSegments == 2)
32269450Smsmith        {
32369450Smsmith            InternalName[i] = AML_DUAL_NAME_PREFIX;
324193267Sjkim            Result = &InternalName[(ACPI_SIZE) i+1];
32569450Smsmith        }
32669450Smsmith        else
32769450Smsmith        {
32869450Smsmith            InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
329193267Sjkim            InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
330193267Sjkim            Result = &InternalName[(ACPI_SIZE) i+2];
33169450Smsmith        }
33267754Smsmith    }
33367754Smsmith
33467754Smsmith    /* Build the name (minus path separators) */
33567754Smsmith
33667754Smsmith    for (; NumSegments; NumSegments--)
33767754Smsmith    {
33867754Smsmith        for (i = 0; i < ACPI_NAME_SIZE; i++)
33967754Smsmith        {
340245582Sjkim            if (ACPI_IS_PATH_SEPARATOR (*ExternalName) ||
34167754Smsmith               (*ExternalName == 0))
34267754Smsmith            {
34377424Smsmith                /* Pad the segment with underscore(s) if segment is short */
34467754Smsmith
34567754Smsmith                Result[i] = '_';
34667754Smsmith            }
34767754Smsmith            else
34867754Smsmith            {
34977424Smsmith                /* Convert the character to uppercase and save it */
35067754Smsmith
351306536Sjkim                Result[i] = (char) toupper ((int) *ExternalName);
35267754Smsmith                ExternalName++;
35367754Smsmith            }
35467754Smsmith        }
35567754Smsmith
35667754Smsmith        /* Now we must have a path separator, or the pathname is bad */
35767754Smsmith
358245582Sjkim        if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) &&
35967754Smsmith            (*ExternalName != 0))
36067754Smsmith        {
361233250Sjkim            return_ACPI_STATUS (AE_BAD_PATHNAME);
36267754Smsmith        }
36367754Smsmith
36467754Smsmith        /* Move on the next segment */
36567754Smsmith
36667754Smsmith        ExternalName++;
36767754Smsmith        Result += ACPI_NAME_SIZE;
36867754Smsmith    }
36967754Smsmith
37077424Smsmith    /* Terminate the string */
37167754Smsmith
37267754Smsmith    *Result = 0;
37367754Smsmith
37477424Smsmith    if (Info->FullyQualified)
37567754Smsmith    {
376123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
37799146Siwasaki            InternalName, InternalName));
37867754Smsmith    }
37967754Smsmith    else
38067754Smsmith    {
381123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
38299146Siwasaki            InternalName, InternalName));
38367754Smsmith    }
38467754Smsmith
38567754Smsmith    return_ACPI_STATUS (AE_OK);
38667754Smsmith}
38767754Smsmith
38867754Smsmith
38977424Smsmith/*******************************************************************************
39067754Smsmith *
39177424Smsmith * FUNCTION:    AcpiNsInternalizeName
39277424Smsmith *
39377424Smsmith * PARAMETERS:  *ExternalName           - External representation of name
39477424Smsmith *              **Converted Name        - Where to return the resulting
39577424Smsmith *                                        internal represention of the name
39677424Smsmith *
39777424Smsmith * RETURN:      Status
39877424Smsmith *
39977424Smsmith * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
40077424Smsmith *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
40177424Smsmith *
40277424Smsmith *******************************************************************************/
40377424Smsmith
40477424SmsmithACPI_STATUS
40577424SmsmithAcpiNsInternalizeName (
406193267Sjkim    const char              *ExternalName,
407114237Snjl    char                    **ConvertedName)
40877424Smsmith{
409114237Snjl    char                    *InternalName;
41077424Smsmith    ACPI_NAMESTRING_INFO    Info;
41177424Smsmith    ACPI_STATUS             Status;
41277424Smsmith
41377424Smsmith
414167802Sjkim    ACPI_FUNCTION_TRACE (NsInternalizeName);
41577424Smsmith
41677424Smsmith
41777424Smsmith    if ((!ExternalName)      ||
41877424Smsmith        (*ExternalName == 0) ||
41977424Smsmith        (!ConvertedName))
42077424Smsmith    {
42177424Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
42277424Smsmith    }
42377424Smsmith
42477424Smsmith    /* Get the length of the new internal name */
42577424Smsmith
42677424Smsmith    Info.ExternalName = ExternalName;
42777424Smsmith    AcpiNsGetInternalNameLength (&Info);
42877424Smsmith
42977424Smsmith    /* We need a segment to store the internal  name */
43077424Smsmith
431167802Sjkim    InternalName = ACPI_ALLOCATE_ZEROED (Info.Length);
43277424Smsmith    if (!InternalName)
43377424Smsmith    {
43477424Smsmith        return_ACPI_STATUS (AE_NO_MEMORY);
43577424Smsmith    }
43677424Smsmith
43777424Smsmith    /* Build the name */
43877424Smsmith
43977424Smsmith    Info.InternalName = InternalName;
44077424Smsmith    Status = AcpiNsBuildInternalName (&Info);
44177424Smsmith    if (ACPI_FAILURE (Status))
44277424Smsmith    {
443167802Sjkim        ACPI_FREE (InternalName);
44477424Smsmith        return_ACPI_STATUS (Status);
44577424Smsmith    }
44677424Smsmith
44777424Smsmith    *ConvertedName = InternalName;
44877424Smsmith    return_ACPI_STATUS (AE_OK);
44977424Smsmith}
45077424Smsmith
45177424Smsmith
45277424Smsmith/*******************************************************************************
45377424Smsmith *
45467754Smsmith * FUNCTION:    AcpiNsExternalizeName
45567754Smsmith *
456151937Sjkim * PARAMETERS:  InternalNameLength  - Lenth of the internal name below
457151937Sjkim *              InternalName        - Internal representation of name
458151937Sjkim *              ConvertedNameLength - Where the length is returned
459151937Sjkim *              ConvertedName       - Where the resulting external name
460151937Sjkim *                                    is returned
46167754Smsmith *
46267754Smsmith * RETURN:      Status
46367754Smsmith *
46467754Smsmith * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
465151937Sjkim *              to its external (printable) form (e.g. "\_PR_.CPU0")
46667754Smsmith *
46777424Smsmith ******************************************************************************/
46867754Smsmith
46967754SmsmithACPI_STATUS
47067754SmsmithAcpiNsExternalizeName (
47167754Smsmith    UINT32                  InternalNameLength,
472193267Sjkim    const char              *InternalName,
47367754Smsmith    UINT32                  *ConvertedNameLength,
47467754Smsmith    char                    **ConvertedName)
47567754Smsmith{
476193267Sjkim    UINT32                  NamesIndex = 0;
477193267Sjkim    UINT32                  NumSegments = 0;
478193267Sjkim    UINT32                  RequiredLength;
479193267Sjkim    UINT32                  PrefixLength = 0;
480193267Sjkim    UINT32                  i = 0;
481193267Sjkim    UINT32                  j = 0;
48267754Smsmith
48367754Smsmith
484167802Sjkim    ACPI_FUNCTION_TRACE (NsExternalizeName);
48567754Smsmith
48667754Smsmith
48767754Smsmith    if (!InternalNameLength     ||
48867754Smsmith        !InternalName           ||
48967754Smsmith        !ConvertedName)
49067754Smsmith    {
49167754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
49267754Smsmith    }
49367754Smsmith
494193267Sjkim    /* Check for a prefix (one '\' | one or more '^') */
495193267Sjkim
49667754Smsmith    switch (InternalName[0])
49767754Smsmith    {
498245582Sjkim    case AML_ROOT_PREFIX:
499250838Sjkim
50067754Smsmith        PrefixLength = 1;
50167754Smsmith        break;
50267754Smsmith
503245582Sjkim    case AML_PARENT_PREFIX:
504250838Sjkim
50567754Smsmith        for (i = 0; i < InternalNameLength; i++)
50667754Smsmith        {
507245582Sjkim            if (ACPI_IS_PARENT_PREFIX (InternalName[i]))
50867754Smsmith            {
50967754Smsmith                PrefixLength = i + 1;
51067754Smsmith            }
511102550Siwasaki            else
512102550Siwasaki            {
513102550Siwasaki                break;
514102550Siwasaki            }
51567754Smsmith        }
51667754Smsmith
51767754Smsmith        if (i == InternalNameLength)
51867754Smsmith        {
51967754Smsmith            PrefixLength = i;
52067754Smsmith        }
52167754Smsmith
52267754Smsmith        break;
52399679Siwasaki
52499679Siwasaki    default:
525250838Sjkim
52699679Siwasaki        break;
52767754Smsmith    }
52867754Smsmith
52967754Smsmith    /*
530193267Sjkim     * Check for object names. Note that there could be 0-255 of these
53167754Smsmith     * 4-byte elements.
53267754Smsmith     */
53367754Smsmith    if (PrefixLength < InternalNameLength)
53467754Smsmith    {
53567754Smsmith        switch (InternalName[PrefixLength])
53667754Smsmith        {
53791116Smsmith        case AML_MULTI_NAME_PREFIX_OP:
53867754Smsmith
53991116Smsmith            /* <count> 4-byte names */
54067754Smsmith
54167754Smsmith            NamesIndex = PrefixLength + 2;
542193267Sjkim            NumSegments = (UINT8)
543193267Sjkim                InternalName[(ACPI_SIZE) PrefixLength + 1];
54467754Smsmith            break;
54567754Smsmith
54691116Smsmith        case AML_DUAL_NAME_PREFIX:
54767754Smsmith
54891116Smsmith            /* Two 4-byte names */
54967754Smsmith
55067754Smsmith            NamesIndex = PrefixLength + 1;
55191116Smsmith            NumSegments = 2;
55267754Smsmith            break;
55367754Smsmith
55491116Smsmith        case 0:
55567754Smsmith
55691116Smsmith            /* NullName */
55767754Smsmith
55867754Smsmith            NamesIndex = 0;
55991116Smsmith            NumSegments = 0;
56067754Smsmith            break;
56167754Smsmith
56291116Smsmith        default:
56367754Smsmith
56491116Smsmith            /* one 4-byte name */
56567754Smsmith
56667754Smsmith            NamesIndex = PrefixLength;
56791116Smsmith            NumSegments = 1;
56867754Smsmith            break;
56967754Smsmith        }
57067754Smsmith    }
57167754Smsmith
57267754Smsmith    /*
57367754Smsmith     * Calculate the length of ConvertedName, which equals the length
57467754Smsmith     * of the prefix, length of all object names, length of any required
57567754Smsmith     * punctuation ('.') between object names, plus the NULL terminator.
57667754Smsmith     */
57791116Smsmith    RequiredLength = PrefixLength + (4 * NumSegments) +
578306536Sjkim        ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
57967754Smsmith
58067754Smsmith    /*
581241973Sjkim     * Check to see if we're still in bounds. If not, there's a problem
58267754Smsmith     * with InternalName (invalid format).
58367754Smsmith     */
58491116Smsmith    if (RequiredLength > InternalNameLength)
58567754Smsmith    {
586167802Sjkim        ACPI_ERROR ((AE_INFO, "Invalid internal name"));
58767754Smsmith        return_ACPI_STATUS (AE_BAD_PATHNAME);
58867754Smsmith    }
58967754Smsmith
590193267Sjkim    /* Build the ConvertedName */
591193267Sjkim
592167802Sjkim    *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength);
59367754Smsmith    if (!(*ConvertedName))
59467754Smsmith    {
59567754Smsmith        return_ACPI_STATUS (AE_NO_MEMORY);
59667754Smsmith    }
59767754Smsmith
59867754Smsmith    j = 0;
59967754Smsmith
60067754Smsmith    for (i = 0; i < PrefixLength; i++)
60167754Smsmith    {
60267754Smsmith        (*ConvertedName)[j++] = InternalName[i];
60367754Smsmith    }
60467754Smsmith
60591116Smsmith    if (NumSegments > 0)
60667754Smsmith    {
60791116Smsmith        for (i = 0; i < NumSegments; i++)
60867754Smsmith        {
60967754Smsmith            if (i > 0)
61067754Smsmith            {
61167754Smsmith                (*ConvertedName)[j++] = '.';
61267754Smsmith            }
61367754Smsmith
614241973Sjkim            /* Copy and validate the 4-char name segment */
615241973Sjkim
616306536Sjkim            ACPI_MOVE_NAME (&(*ConvertedName)[j],
617306536Sjkim                &InternalName[NamesIndex]);
618241973Sjkim            AcpiUtRepairName (&(*ConvertedName)[j]);
619241973Sjkim
620241973Sjkim            j += ACPI_NAME_SIZE;
621241973Sjkim            NamesIndex += ACPI_NAME_SIZE;
62267754Smsmith        }
62367754Smsmith    }
62467754Smsmith
62591116Smsmith    if (ConvertedNameLength)
62691116Smsmith    {
62799679Siwasaki        *ConvertedNameLength = (UINT32) RequiredLength;
62891116Smsmith    }
62991116Smsmith
63067754Smsmith    return_ACPI_STATUS (AE_OK);
63167754Smsmith}
63267754Smsmith
63367754Smsmith
63477424Smsmith/*******************************************************************************
63567754Smsmith *
636200553Sjkim * FUNCTION:    AcpiNsValidateHandle
63767754Smsmith *
638200553Sjkim * PARAMETERS:  Handle          - Handle to be validated and typecast to a
639200553Sjkim *                                namespace node.
64067754Smsmith *
641200553Sjkim * RETURN:      A pointer to a namespace node
64267754Smsmith *
643200553Sjkim * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
644200553Sjkim *              cases for the root node.
64567754Smsmith *
646200553Sjkim * NOTE: Real integer handles would allow for more verification
647151937Sjkim *       and keep all pointers within this subsystem - however this introduces
648200553Sjkim *       more overhead and has not been necessary to this point. Drivers
649200553Sjkim *       holding handles are typically notified before a node becomes invalid
650200553Sjkim *       due to a table unload.
65187031Smsmith *
65277424Smsmith ******************************************************************************/
65367754Smsmith
65467754SmsmithACPI_NAMESPACE_NODE *
655200553SjkimAcpiNsValidateHandle (
65667754Smsmith    ACPI_HANDLE             Handle)
65767754Smsmith{
65867754Smsmith
65991116Smsmith    ACPI_FUNCTION_ENTRY ();
66083174Smsmith
66183174Smsmith
662193267Sjkim    /* Parameter validation */
663193267Sjkim
664167802Sjkim    if ((!Handle) || (Handle == ACPI_ROOT_OBJECT))
66567754Smsmith    {
66667754Smsmith        return (AcpiGbl_RootNode);
66767754Smsmith    }
66867754Smsmith
66967754Smsmith    /* We can at least attempt to verify the handle */
67067754Smsmith
67191116Smsmith    if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED)
67267754Smsmith    {
67367754Smsmith        return (NULL);
67467754Smsmith    }
67567754Smsmith
676167802Sjkim    return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle));
67767754Smsmith}
67867754Smsmith
67967754Smsmith
68077424Smsmith/*******************************************************************************
68167754Smsmith *
68267754Smsmith * FUNCTION:    AcpiNsTerminate
68367754Smsmith *
68467754Smsmith * PARAMETERS:  none
68567754Smsmith *
68667754Smsmith * RETURN:      none
68767754Smsmith *
688151937Sjkim * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
68967754Smsmith *
69067754Smsmith ******************************************************************************/
69167754Smsmith
69267754Smsmithvoid
693151937SjkimAcpiNsTerminate (
694151937Sjkim    void)
69567754Smsmith{
696281075Sdim    ACPI_STATUS             Status;
69767754Smsmith
69867754Smsmith
699167802Sjkim    ACPI_FUNCTION_TRACE (NsTerminate);
70067754Smsmith
70167754Smsmith
702306536Sjkim#ifdef ACPI_EXEC_APP
703306536Sjkim    {
704306536Sjkim        ACPI_OPERAND_OBJECT     *Prev;
705306536Sjkim        ACPI_OPERAND_OBJECT     *Next;
706306536Sjkim
707306536Sjkim        /* Delete any module-level code blocks */
708306536Sjkim
709306536Sjkim        Next = AcpiGbl_ModuleCodeList;
710306536Sjkim        while (Next)
711306536Sjkim        {
712306536Sjkim            Prev = Next;
713306536Sjkim            Next = Next->Method.Mutex;
714306536Sjkim            Prev->Method.Mutex = NULL; /* Clear the Mutex (cheated) field */
715306536Sjkim            AcpiUtRemoveReference (Prev);
716306536Sjkim        }
717306536Sjkim    }
718306536Sjkim#endif
719306536Sjkim
72067754Smsmith    /*
721281075Sdim     * Free the entire namespace -- all nodes and all objects
722281075Sdim     * attached to the nodes
72367754Smsmith     */
724117521Snjl    AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
72567754Smsmith
726281075Sdim    /* Delete any objects attached to the root node */
72767754Smsmith
728281075Sdim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
729281075Sdim    if (ACPI_FAILURE (Status))
73067754Smsmith    {
731281075Sdim        return_VOID;
73267754Smsmith    }
73367754Smsmith
734281075Sdim    AcpiNsDeleteNode (AcpiGbl_RootNode);
735281075Sdim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
736281075Sdim
73782367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
73867754Smsmith    return_VOID;
73967754Smsmith}
74067754Smsmith
74167754Smsmith
74277424Smsmith/*******************************************************************************
74367754Smsmith *
74467754Smsmith * FUNCTION:    AcpiNsOpensScope
74567754Smsmith *
74667754Smsmith * PARAMETERS:  Type        - A valid namespace type
74767754Smsmith *
74867754Smsmith * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
74967754Smsmith *              to the ACPI specification, else 0
75067754Smsmith *
75177424Smsmith ******************************************************************************/
75267754Smsmith
75367754SmsmithUINT32
75467754SmsmithAcpiNsOpensScope (
75591116Smsmith    ACPI_OBJECT_TYPE        Type)
75667754Smsmith{
757243347Sjkim    ACPI_FUNCTION_ENTRY ();
75867754Smsmith
75967754Smsmith
760243347Sjkim    if (Type > ACPI_TYPE_LOCAL_MAX)
76167754Smsmith    {
76267754Smsmith        /* type code out of range  */
76367754Smsmith
764204773Sjkim        ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
765243347Sjkim        return (ACPI_NS_NORMAL);
76667754Smsmith    }
76767754Smsmith
768243347Sjkim    return (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
76967754Smsmith}
77067754Smsmith
77167754Smsmith
77277424Smsmith/*******************************************************************************
77367754Smsmith *
774167802Sjkim * FUNCTION:    AcpiNsGetNode
77567754Smsmith *
77667754Smsmith * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
77767754Smsmith *                            \ (backslash) and ^ (carat) prefixes, and the
77867754Smsmith *                            . (period) to separate segments are supported.
779167802Sjkim *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
780241973Sjkim *                            root of the name space. If Name is fully
78167754Smsmith *                            qualified (first INT8 is '\'), the passed value
78267754Smsmith *                            of Scope will not be accessed.
78391116Smsmith *              Flags       - Used to indicate whether to perform upsearch or
78491116Smsmith *                            not.
78567754Smsmith *              ReturnNode  - Where the Node is returned
78667754Smsmith *
78767754Smsmith * DESCRIPTION: Look up a name relative to a given scope and return the
788241973Sjkim *              corresponding Node. NOTE: Scope can be null.
78967754Smsmith *
79067754Smsmith * MUTEX:       Locks namespace
79167754Smsmith *
79277424Smsmith ******************************************************************************/
79367754Smsmith
79467754SmsmithACPI_STATUS
795167802SjkimAcpiNsGetNode (
796167802Sjkim    ACPI_NAMESPACE_NODE     *PrefixNode,
797193267Sjkim    const char              *Pathname,
79891116Smsmith    UINT32                  Flags,
79967754Smsmith    ACPI_NAMESPACE_NODE     **ReturnNode)
80067754Smsmith{
80167754Smsmith    ACPI_GENERIC_STATE      ScopeInfo;
80267754Smsmith    ACPI_STATUS             Status;
803167802Sjkim    char                    *InternalPath;
80467754Smsmith
80567754Smsmith
806193267Sjkim    ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
80767754Smsmith
80867754Smsmith
809245582Sjkim    /* Simplest case is a null pathname */
810245582Sjkim
811167802Sjkim    if (!Pathname)
81267754Smsmith    {
813167802Sjkim        *ReturnNode = PrefixNode;
814167802Sjkim        if (!PrefixNode)
815114237Snjl        {
816167802Sjkim            *ReturnNode = AcpiGbl_RootNode;
817114237Snjl        }
818306536Sjkim
819167802Sjkim        return_ACPI_STATUS (AE_OK);
82067754Smsmith    }
82167754Smsmith
822245582Sjkim    /* Quick check for a reference to the root */
823245582Sjkim
824245582Sjkim    if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1]))
825245582Sjkim    {
826245582Sjkim        *ReturnNode = AcpiGbl_RootNode;
827245582Sjkim        return_ACPI_STATUS (AE_OK);
828245582Sjkim    }
829245582Sjkim
830167802Sjkim    /* Convert path to internal representation */
831167802Sjkim
832167802Sjkim    Status = AcpiNsInternalizeName (Pathname, &InternalPath);
833167802Sjkim    if (ACPI_FAILURE (Status))
834167802Sjkim    {
835167802Sjkim        return_ACPI_STATUS (Status);
836167802Sjkim    }
837167802Sjkim
83891116Smsmith    /* Must lock namespace during lookup */
83967754Smsmith
84091116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
84191116Smsmith    if (ACPI_FAILURE (Status))
84291116Smsmith    {
843126372Snjl        goto Cleanup;
84491116Smsmith    }
84567754Smsmith
84669746Smsmith    /* Setup lookup scope (search starting point) */
84767754Smsmith
848167802Sjkim    ScopeInfo.Scope.Node = PrefixNode;
84967754Smsmith
85067754Smsmith    /* Lookup the name in the namespace */
85167754Smsmith
852167802Sjkim    Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
853306536Sjkim        ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
854306536Sjkim        NULL, ReturnNode);
85567754Smsmith    if (ACPI_FAILURE (Status))
85667754Smsmith    {
857193267Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
858306536Sjkim            Pathname, AcpiFormatException (Status)));
85967754Smsmith    }
86067754Smsmith
86191116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
862114237Snjl
863126372SnjlCleanup:
864167802Sjkim    ACPI_FREE (InternalPath);
86567754Smsmith    return_ACPI_STATUS (Status);
86667754Smsmith}
867