nsutils.c revision 250838
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
467754Smsmith *                        parents and siblings and Scope manipulation
567754Smsmith *
667754Smsmith *****************************************************************************/
767754Smsmith
8217365Sjkim/*
9245582Sjkim * Copyright (C) 2000 - 2013, 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
57151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS
58151937SjkimACPI_NAME
59151937SjkimAcpiNsFindParentName (
60151937Sjkim    ACPI_NAMESPACE_NODE     *NodeToSearch);
61151937Sjkim#endif
62151937Sjkim
63151937Sjkim
6477424Smsmith/*******************************************************************************
6567754Smsmith *
66114237Snjl * FUNCTION:    AcpiNsPrintNodePathname
67114237Snjl *
68151937Sjkim * PARAMETERS:  Node            - Object
69151937Sjkim *              Message         - Prefix message
70114237Snjl *
71114237Snjl * DESCRIPTION: Print an object's full namespace pathname
72114237Snjl *              Manages allocation/freeing of a pathname buffer
73114237Snjl *
74114237Snjl ******************************************************************************/
75114237Snjl
76114237Snjlvoid
77114237SnjlAcpiNsPrintNodePathname (
78114237Snjl    ACPI_NAMESPACE_NODE     *Node,
79193267Sjkim    const char              *Message)
80114237Snjl{
81114237Snjl    ACPI_BUFFER             Buffer;
82114237Snjl    ACPI_STATUS             Status;
83114237Snjl
84114237Snjl
85123315Snjl    if (!Node)
86123315Snjl    {
87123315Snjl        AcpiOsPrintf ("[NULL NAME]");
88123315Snjl        return;
89123315Snjl    }
90123315Snjl
91138287Smarks    /* Convert handle to full pathname and print it (with supplied message) */
92114237Snjl
93114237Snjl    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
94114237Snjl
95114237Snjl    Status = AcpiNsHandleToPathname (Node, &Buffer);
96114237Snjl    if (ACPI_SUCCESS (Status))
97114237Snjl    {
98151937Sjkim        if (Message)
99117521Snjl        {
100151937Sjkim            AcpiOsPrintf ("%s ", Message);
101117521Snjl        }
102117521Snjl
103117521Snjl        AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node);
104167802Sjkim        ACPI_FREE (Buffer.Pointer);
105114237Snjl    }
106114237Snjl}
107114237Snjl
108114237Snjl
109114237Snjl/*******************************************************************************
110114237Snjl *
11167754Smsmith * FUNCTION:    AcpiNsGetType
11267754Smsmith *
113151937Sjkim * PARAMETERS:  Node        - Parent Node to be examined
11467754Smsmith *
11567754Smsmith * RETURN:      Type field from Node whose handle is passed
11667754Smsmith *
117151937Sjkim * DESCRIPTION: Return the type of a Namespace node
118151937Sjkim *
11977424Smsmith ******************************************************************************/
12067754Smsmith
12191116SmsmithACPI_OBJECT_TYPE
12267754SmsmithAcpiNsGetType (
12377424Smsmith    ACPI_NAMESPACE_NODE     *Node)
12467754Smsmith{
125167802Sjkim    ACPI_FUNCTION_TRACE (NsGetType);
12667754Smsmith
12767754Smsmith
12877424Smsmith    if (!Node)
12967754Smsmith    {
130167802Sjkim        ACPI_WARNING ((AE_INFO, "Null Node parameter"));
131246849Sjkim        return_UINT8 (ACPI_TYPE_ANY);
13267754Smsmith    }
13367754Smsmith
134246849Sjkim    return_UINT8 (Node->Type);
13567754Smsmith}
13667754Smsmith
13767754Smsmith
13877424Smsmith/*******************************************************************************
13967754Smsmith *
14067754Smsmith * FUNCTION:    AcpiNsLocal
14167754Smsmith *
142151937Sjkim * PARAMETERS:  Type        - A namespace object type
14367754Smsmith *
14467754Smsmith * RETURN:      LOCAL if names must be found locally in objects of the
14567754Smsmith *              passed type, 0 if enclosing scopes should be searched
14667754Smsmith *
147151937Sjkim * DESCRIPTION: Returns scope rule for the given object type.
148151937Sjkim *
14977424Smsmith ******************************************************************************/
15067754Smsmith
15167754SmsmithUINT32
15267754SmsmithAcpiNsLocal (
15391116Smsmith    ACPI_OBJECT_TYPE        Type)
15467754Smsmith{
155167802Sjkim    ACPI_FUNCTION_TRACE (NsLocal);
15667754Smsmith
15767754Smsmith
15877424Smsmith    if (!AcpiUtValidObjectType (Type))
15967754Smsmith    {
16067754Smsmith        /* Type code out of range  */
16167754Smsmith
162204773Sjkim        ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
163246849Sjkim        return_UINT32 (ACPI_NS_NORMAL);
16467754Smsmith    }
16567754Smsmith
166246849Sjkim    return_UINT32 (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
16767754Smsmith}
16867754Smsmith
16967754Smsmith
17077424Smsmith/*******************************************************************************
17167754Smsmith *
17277424Smsmith * FUNCTION:    AcpiNsGetInternalNameLength
17367754Smsmith *
17483174Smsmith * PARAMETERS:  Info            - Info struct initialized with the
17577424Smsmith *                                external name pointer.
17667754Smsmith *
177151937Sjkim * RETURN:      None
17867754Smsmith *
17983174Smsmith * DESCRIPTION: Calculate the length of the internal (AML) namestring
18077424Smsmith *              corresponding to the external (ASL) namestring.
18167754Smsmith *
18277424Smsmith ******************************************************************************/
18367754Smsmith
18499679Siwasakivoid
18577424SmsmithAcpiNsGetInternalNameLength (
18677424Smsmith    ACPI_NAMESTRING_INFO    *Info)
18767754Smsmith{
188193267Sjkim    const char              *NextExternalChar;
18967754Smsmith    UINT32                  i;
19067754Smsmith
19167754Smsmith
19291116Smsmith    ACPI_FUNCTION_ENTRY ();
19383174Smsmith
19483174Smsmith
19577424Smsmith    NextExternalChar = Info->ExternalName;
19677424Smsmith    Info->NumCarats = 0;
19777424Smsmith    Info->NumSegments = 0;
19877424Smsmith    Info->FullyQualified = FALSE;
19983174Smsmith
20067754Smsmith    /*
201138287Smarks     * For the internal name, the required length is 4 bytes per segment, plus
202138287Smarks     * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null
203138287Smarks     * (which is not really needed, but no there's harm in putting it there)
20467754Smsmith     *
205138287Smarks     * strlen() + 1 covers the first NameSeg, which has no path separator
20667754Smsmith     */
207245582Sjkim    if (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
20867754Smsmith    {
20977424Smsmith        Info->FullyQualified = TRUE;
21077424Smsmith        NextExternalChar++;
211193267Sjkim
212193267Sjkim        /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
213193267Sjkim
214245582Sjkim        while (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
215193267Sjkim        {
216193267Sjkim            NextExternalChar++;
217193267Sjkim        }
21867754Smsmith    }
21969450Smsmith    else
22069450Smsmith    {
221193267Sjkim        /* Handle Carat prefixes */
222193267Sjkim
223245582Sjkim        while (ACPI_IS_PARENT_PREFIX (*NextExternalChar))
22469450Smsmith        {
22577424Smsmith            Info->NumCarats++;
22677424Smsmith            NextExternalChar++;
22769450Smsmith        }
22869450Smsmith    }
22969450Smsmith
23067754Smsmith    /*
231138287Smarks     * Determine the number of ACPI name "segments" by counting the number of
232138287Smarks     * path separators within the string. Start with one segment since the
233138287Smarks     * segment count is [(# separators) + 1], and zero separators is ok.
23467754Smsmith     */
23577424Smsmith    if (*NextExternalChar)
23667754Smsmith    {
23777424Smsmith        Info->NumSegments = 1;
23877424Smsmith        for (i = 0; NextExternalChar[i]; i++)
23967754Smsmith        {
240245582Sjkim            if (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i]))
24169450Smsmith            {
24277424Smsmith                Info->NumSegments++;
24369450Smsmith            }
24467754Smsmith        }
24567754Smsmith    }
24667754Smsmith
24783174Smsmith    Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) +
24877424Smsmith                    4 + Info->NumCarats;
24967754Smsmith
25077424Smsmith    Info->NextExternalChar = NextExternalChar;
25177424Smsmith}
25267754Smsmith
25367754Smsmith
25477424Smsmith/*******************************************************************************
25577424Smsmith *
25677424Smsmith * FUNCTION:    AcpiNsBuildInternalName
25777424Smsmith *
25877424Smsmith * PARAMETERS:  Info            - Info struct fully initialized
25977424Smsmith *
26077424Smsmith * RETURN:      Status
26177424Smsmith *
26283174Smsmith * DESCRIPTION: Construct the internal (AML) namestring
26377424Smsmith *              corresponding to the external (ASL) namestring.
26477424Smsmith *
26577424Smsmith ******************************************************************************/
26677424Smsmith
26777424SmsmithACPI_STATUS
26877424SmsmithAcpiNsBuildInternalName (
26977424Smsmith    ACPI_NAMESTRING_INFO    *Info)
27077424Smsmith{
27177424Smsmith    UINT32                  NumSegments = Info->NumSegments;
272114237Snjl    char                    *InternalName = Info->InternalName;
273193267Sjkim    const char              *ExternalName = Info->NextExternalChar;
274114237Snjl    char                    *Result = NULL;
275193267Sjkim    UINT32                  i;
27677424Smsmith
27777424Smsmith
278167802Sjkim    ACPI_FUNCTION_TRACE (NsBuildInternalName);
27977424Smsmith
28083174Smsmith
28167754Smsmith    /* Setup the correct prefixes, counts, and pointers */
28267754Smsmith
28377424Smsmith    if (Info->FullyQualified)
28467754Smsmith    {
285245582Sjkim        InternalName[0] = AML_ROOT_PREFIX;
28669450Smsmith
28769450Smsmith        if (NumSegments <= 1)
28869450Smsmith        {
28969450Smsmith            Result = &InternalName[1];
29069450Smsmith        }
29169450Smsmith        else if (NumSegments == 2)
29269450Smsmith        {
29369450Smsmith            InternalName[1] = AML_DUAL_NAME_PREFIX;
29469450Smsmith            Result = &InternalName[2];
29569450Smsmith        }
29669450Smsmith        else
29769450Smsmith        {
29869450Smsmith            InternalName[1] = AML_MULTI_NAME_PREFIX_OP;
29969450Smsmith            InternalName[2] = (char) NumSegments;
30069450Smsmith            Result = &InternalName[3];
30169450Smsmith        }
30267754Smsmith    }
30367754Smsmith    else
30467754Smsmith    {
30569450Smsmith        /*
30669450Smsmith         * Not fully qualified.
30769450Smsmith         * Handle Carats first, then append the name segments
30869450Smsmith         */
30969450Smsmith        i = 0;
31077424Smsmith        if (Info->NumCarats)
31169450Smsmith        {
31277424Smsmith            for (i = 0; i < Info->NumCarats; i++)
31369450Smsmith            {
314245582Sjkim                InternalName[i] = AML_PARENT_PREFIX;
31569450Smsmith            }
31669450Smsmith        }
31769450Smsmith
31891116Smsmith        if (NumSegments <= 1)
31969450Smsmith        {
32069450Smsmith            Result = &InternalName[i];
32169450Smsmith        }
32269450Smsmith        else if (NumSegments == 2)
32369450Smsmith        {
32469450Smsmith            InternalName[i] = AML_DUAL_NAME_PREFIX;
325193267Sjkim            Result = &InternalName[(ACPI_SIZE) i+1];
32669450Smsmith        }
32769450Smsmith        else
32869450Smsmith        {
32969450Smsmith            InternalName[i] = AML_MULTI_NAME_PREFIX_OP;
330193267Sjkim            InternalName[(ACPI_SIZE) i+1] = (char) NumSegments;
331193267Sjkim            Result = &InternalName[(ACPI_SIZE) i+2];
33269450Smsmith        }
33367754Smsmith    }
33467754Smsmith
33567754Smsmith    /* Build the name (minus path separators) */
33667754Smsmith
33767754Smsmith    for (; NumSegments; NumSegments--)
33867754Smsmith    {
33967754Smsmith        for (i = 0; i < ACPI_NAME_SIZE; i++)
34067754Smsmith        {
341245582Sjkim            if (ACPI_IS_PATH_SEPARATOR (*ExternalName) ||
34267754Smsmith               (*ExternalName == 0))
34367754Smsmith            {
34477424Smsmith                /* Pad the segment with underscore(s) if segment is short */
34567754Smsmith
34667754Smsmith                Result[i] = '_';
34767754Smsmith            }
34867754Smsmith            else
34967754Smsmith            {
35077424Smsmith                /* Convert the character to uppercase and save it */
35167754Smsmith
35299679Siwasaki                Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName);
35367754Smsmith                ExternalName++;
35467754Smsmith            }
35567754Smsmith        }
35667754Smsmith
35767754Smsmith        /* Now we must have a path separator, or the pathname is bad */
35867754Smsmith
359245582Sjkim        if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) &&
36067754Smsmith            (*ExternalName != 0))
36167754Smsmith        {
362233250Sjkim            return_ACPI_STATUS (AE_BAD_PATHNAME);
36367754Smsmith        }
36467754Smsmith
36567754Smsmith        /* Move on the next segment */
36667754Smsmith
36767754Smsmith        ExternalName++;
36867754Smsmith        Result += ACPI_NAME_SIZE;
36967754Smsmith    }
37067754Smsmith
37177424Smsmith    /* Terminate the string */
37267754Smsmith
37367754Smsmith    *Result = 0;
37467754Smsmith
37577424Smsmith    if (Info->FullyQualified)
37667754Smsmith    {
377123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
37899146Siwasaki            InternalName, InternalName));
37967754Smsmith    }
38067754Smsmith    else
38167754Smsmith    {
382123315Snjl        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
38399146Siwasaki            InternalName, InternalName));
38467754Smsmith    }
38567754Smsmith
38667754Smsmith    return_ACPI_STATUS (AE_OK);
38767754Smsmith}
38867754Smsmith
38967754Smsmith
39077424Smsmith/*******************************************************************************
39167754Smsmith *
39277424Smsmith * FUNCTION:    AcpiNsInternalizeName
39377424Smsmith *
39477424Smsmith * PARAMETERS:  *ExternalName           - External representation of name
39577424Smsmith *              **Converted Name        - Where to return the resulting
39677424Smsmith *                                        internal represention of the name
39777424Smsmith *
39877424Smsmith * RETURN:      Status
39977424Smsmith *
40077424Smsmith * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
40177424Smsmith *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
40277424Smsmith *
40377424Smsmith *******************************************************************************/
40477424Smsmith
40577424SmsmithACPI_STATUS
40677424SmsmithAcpiNsInternalizeName (
407193267Sjkim    const char              *ExternalName,
408114237Snjl    char                    **ConvertedName)
40977424Smsmith{
410114237Snjl    char                    *InternalName;
41177424Smsmith    ACPI_NAMESTRING_INFO    Info;
41277424Smsmith    ACPI_STATUS             Status;
41377424Smsmith
41477424Smsmith
415167802Sjkim    ACPI_FUNCTION_TRACE (NsInternalizeName);
41677424Smsmith
41777424Smsmith
41877424Smsmith    if ((!ExternalName)      ||
41977424Smsmith        (*ExternalName == 0) ||
42077424Smsmith        (!ConvertedName))
42177424Smsmith    {
42277424Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
42377424Smsmith    }
42477424Smsmith
42577424Smsmith    /* Get the length of the new internal name */
42677424Smsmith
42777424Smsmith    Info.ExternalName = ExternalName;
42877424Smsmith    AcpiNsGetInternalNameLength (&Info);
42977424Smsmith
43077424Smsmith    /* We need a segment to store the internal  name */
43177424Smsmith
432167802Sjkim    InternalName = ACPI_ALLOCATE_ZEROED (Info.Length);
43377424Smsmith    if (!InternalName)
43477424Smsmith    {
43577424Smsmith        return_ACPI_STATUS (AE_NO_MEMORY);
43677424Smsmith    }
43777424Smsmith
43877424Smsmith    /* Build the name */
43977424Smsmith
44077424Smsmith    Info.InternalName = InternalName;
44177424Smsmith    Status = AcpiNsBuildInternalName (&Info);
44277424Smsmith    if (ACPI_FAILURE (Status))
44377424Smsmith    {
444167802Sjkim        ACPI_FREE (InternalName);
44577424Smsmith        return_ACPI_STATUS (Status);
44677424Smsmith    }
44777424Smsmith
44877424Smsmith    *ConvertedName = InternalName;
44977424Smsmith    return_ACPI_STATUS (AE_OK);
45077424Smsmith}
45177424Smsmith
45277424Smsmith
45377424Smsmith/*******************************************************************************
45477424Smsmith *
45567754Smsmith * FUNCTION:    AcpiNsExternalizeName
45667754Smsmith *
457151937Sjkim * PARAMETERS:  InternalNameLength  - Lenth of the internal name below
458151937Sjkim *              InternalName        - Internal representation of name
459151937Sjkim *              ConvertedNameLength - Where the length is returned
460151937Sjkim *              ConvertedName       - Where the resulting external name
461151937Sjkim *                                    is returned
46267754Smsmith *
46367754Smsmith * RETURN:      Status
46467754Smsmith *
46567754Smsmith * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
466151937Sjkim *              to its external (printable) form (e.g. "\_PR_.CPU0")
46767754Smsmith *
46877424Smsmith ******************************************************************************/
46967754Smsmith
47067754SmsmithACPI_STATUS
47167754SmsmithAcpiNsExternalizeName (
47267754Smsmith    UINT32                  InternalNameLength,
473193267Sjkim    const char              *InternalName,
47467754Smsmith    UINT32                  *ConvertedNameLength,
47567754Smsmith    char                    **ConvertedName)
47667754Smsmith{
477193267Sjkim    UINT32                  NamesIndex = 0;
478193267Sjkim    UINT32                  NumSegments = 0;
479193267Sjkim    UINT32                  RequiredLength;
480193267Sjkim    UINT32                  PrefixLength = 0;
481193267Sjkim    UINT32                  i = 0;
482193267Sjkim    UINT32                  j = 0;
48367754Smsmith
48467754Smsmith
485167802Sjkim    ACPI_FUNCTION_TRACE (NsExternalizeName);
48667754Smsmith
48767754Smsmith
48867754Smsmith    if (!InternalNameLength     ||
48967754Smsmith        !InternalName           ||
49067754Smsmith        !ConvertedName)
49167754Smsmith    {
49267754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
49367754Smsmith    }
49467754Smsmith
495193267Sjkim    /* Check for a prefix (one '\' | one or more '^') */
496193267Sjkim
49767754Smsmith    switch (InternalName[0])
49867754Smsmith    {
499245582Sjkim    case AML_ROOT_PREFIX:
500250838Sjkim
50167754Smsmith        PrefixLength = 1;
50267754Smsmith        break;
50367754Smsmith
504245582Sjkim    case AML_PARENT_PREFIX:
505250838Sjkim
50667754Smsmith        for (i = 0; i < InternalNameLength; i++)
50767754Smsmith        {
508245582Sjkim            if (ACPI_IS_PARENT_PREFIX (InternalName[i]))
50967754Smsmith            {
51067754Smsmith                PrefixLength = i + 1;
51167754Smsmith            }
512102550Siwasaki            else
513102550Siwasaki            {
514102550Siwasaki                break;
515102550Siwasaki            }
51667754Smsmith        }
51767754Smsmith
51867754Smsmith        if (i == InternalNameLength)
51967754Smsmith        {
52067754Smsmith            PrefixLength = i;
52167754Smsmith        }
52267754Smsmith
52367754Smsmith        break;
52499679Siwasaki
52599679Siwasaki    default:
526250838Sjkim
52799679Siwasaki        break;
52867754Smsmith    }
52967754Smsmith
53067754Smsmith    /*
531193267Sjkim     * Check for object names. Note that there could be 0-255 of these
53267754Smsmith     * 4-byte elements.
53367754Smsmith     */
53467754Smsmith    if (PrefixLength < InternalNameLength)
53567754Smsmith    {
53667754Smsmith        switch (InternalName[PrefixLength])
53767754Smsmith        {
53891116Smsmith        case AML_MULTI_NAME_PREFIX_OP:
53967754Smsmith
54091116Smsmith            /* <count> 4-byte names */
54167754Smsmith
54267754Smsmith            NamesIndex = PrefixLength + 2;
543193267Sjkim            NumSegments = (UINT8)
544193267Sjkim                InternalName[(ACPI_SIZE) PrefixLength + 1];
54567754Smsmith            break;
54667754Smsmith
54791116Smsmith        case AML_DUAL_NAME_PREFIX:
54867754Smsmith
54991116Smsmith            /* Two 4-byte names */
55067754Smsmith
55167754Smsmith            NamesIndex = PrefixLength + 1;
55291116Smsmith            NumSegments = 2;
55367754Smsmith            break;
55467754Smsmith
55591116Smsmith        case 0:
55667754Smsmith
55791116Smsmith            /* NullName */
55867754Smsmith
55967754Smsmith            NamesIndex = 0;
56091116Smsmith            NumSegments = 0;
56167754Smsmith            break;
56267754Smsmith
56391116Smsmith        default:
56467754Smsmith
56591116Smsmith            /* one 4-byte name */
56667754Smsmith
56767754Smsmith            NamesIndex = PrefixLength;
56891116Smsmith            NumSegments = 1;
56967754Smsmith            break;
57067754Smsmith        }
57167754Smsmith    }
57267754Smsmith
57367754Smsmith    /*
57467754Smsmith     * Calculate the length of ConvertedName, which equals the length
57567754Smsmith     * of the prefix, length of all object names, length of any required
57667754Smsmith     * punctuation ('.') between object names, plus the NULL terminator.
57767754Smsmith     */
57891116Smsmith    RequiredLength = PrefixLength + (4 * NumSegments) +
57991116Smsmith                        ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1;
58067754Smsmith
58167754Smsmith    /*
582241973Sjkim     * Check to see if we're still in bounds. If not, there's a problem
58367754Smsmith     * with InternalName (invalid format).
58467754Smsmith     */
58591116Smsmith    if (RequiredLength > InternalNameLength)
58667754Smsmith    {
587167802Sjkim        ACPI_ERROR ((AE_INFO, "Invalid internal name"));
58867754Smsmith        return_ACPI_STATUS (AE_BAD_PATHNAME);
58967754Smsmith    }
59067754Smsmith
591193267Sjkim    /* Build the ConvertedName */
592193267Sjkim
593167802Sjkim    *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength);
59467754Smsmith    if (!(*ConvertedName))
59567754Smsmith    {
59667754Smsmith        return_ACPI_STATUS (AE_NO_MEMORY);
59767754Smsmith    }
59867754Smsmith
59967754Smsmith    j = 0;
60067754Smsmith
60167754Smsmith    for (i = 0; i < PrefixLength; i++)
60267754Smsmith    {
60367754Smsmith        (*ConvertedName)[j++] = InternalName[i];
60467754Smsmith    }
60567754Smsmith
60691116Smsmith    if (NumSegments > 0)
60767754Smsmith    {
60891116Smsmith        for (i = 0; i < NumSegments; i++)
60967754Smsmith        {
61067754Smsmith            if (i > 0)
61167754Smsmith            {
61267754Smsmith                (*ConvertedName)[j++] = '.';
61367754Smsmith            }
61467754Smsmith
615241973Sjkim            /* Copy and validate the 4-char name segment */
616241973Sjkim
617241973Sjkim            ACPI_MOVE_NAME (&(*ConvertedName)[j], &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{
69667754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
69767754Smsmith
69867754Smsmith
699167802Sjkim    ACPI_FUNCTION_TRACE (NsTerminate);
70067754Smsmith
70167754Smsmith
70267754Smsmith    /*
703117521Snjl     * 1) Free the entire namespace -- all nodes and objects
70477424Smsmith     *
705117521Snjl     * Delete all object descriptors attached to namepsace nodes
70667754Smsmith     */
707117521Snjl    AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
70867754Smsmith
709117521Snjl    /* Detach any objects attached to the root */
71067754Smsmith
711117521Snjl    ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode);
71267754Smsmith    if (ObjDesc)
71367754Smsmith    {
714117521Snjl        AcpiNsDetachObject (AcpiGbl_RootNode);
71567754Smsmith    }
71667754Smsmith
71782367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
71867754Smsmith    return_VOID;
71967754Smsmith}
72067754Smsmith
72167754Smsmith
72277424Smsmith/*******************************************************************************
72367754Smsmith *
72467754Smsmith * FUNCTION:    AcpiNsOpensScope
72567754Smsmith *
72667754Smsmith * PARAMETERS:  Type        - A valid namespace type
72767754Smsmith *
72867754Smsmith * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
72967754Smsmith *              to the ACPI specification, else 0
73067754Smsmith *
73177424Smsmith ******************************************************************************/
73267754Smsmith
73367754SmsmithUINT32
73467754SmsmithAcpiNsOpensScope (
73591116Smsmith    ACPI_OBJECT_TYPE        Type)
73667754Smsmith{
737243347Sjkim    ACPI_FUNCTION_ENTRY ();
73867754Smsmith
73967754Smsmith
740243347Sjkim    if (Type > ACPI_TYPE_LOCAL_MAX)
74167754Smsmith    {
74267754Smsmith        /* type code out of range  */
74367754Smsmith
744204773Sjkim        ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
745243347Sjkim        return (ACPI_NS_NORMAL);
74667754Smsmith    }
74767754Smsmith
748243347Sjkim    return (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE);
74967754Smsmith}
75067754Smsmith
75167754Smsmith
75277424Smsmith/*******************************************************************************
75367754Smsmith *
754167802Sjkim * FUNCTION:    AcpiNsGetNode
75567754Smsmith *
75667754Smsmith * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
75767754Smsmith *                            \ (backslash) and ^ (carat) prefixes, and the
75867754Smsmith *                            . (period) to separate segments are supported.
759167802Sjkim *              PrefixNode   - Root of subtree to be searched, or NS_ALL for the
760241973Sjkim *                            root of the name space. If Name is fully
76167754Smsmith *                            qualified (first INT8 is '\'), the passed value
76267754Smsmith *                            of Scope will not be accessed.
76391116Smsmith *              Flags       - Used to indicate whether to perform upsearch or
76491116Smsmith *                            not.
76567754Smsmith *              ReturnNode  - Where the Node is returned
76667754Smsmith *
76767754Smsmith * DESCRIPTION: Look up a name relative to a given scope and return the
768241973Sjkim *              corresponding Node. NOTE: Scope can be null.
76967754Smsmith *
77067754Smsmith * MUTEX:       Locks namespace
77167754Smsmith *
77277424Smsmith ******************************************************************************/
77367754Smsmith
77467754SmsmithACPI_STATUS
775167802SjkimAcpiNsGetNode (
776167802Sjkim    ACPI_NAMESPACE_NODE     *PrefixNode,
777193267Sjkim    const char              *Pathname,
77891116Smsmith    UINT32                  Flags,
77967754Smsmith    ACPI_NAMESPACE_NODE     **ReturnNode)
78067754Smsmith{
78167754Smsmith    ACPI_GENERIC_STATE      ScopeInfo;
78267754Smsmith    ACPI_STATUS             Status;
783167802Sjkim    char                    *InternalPath;
78467754Smsmith
78567754Smsmith
786193267Sjkim    ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
78767754Smsmith
78867754Smsmith
789245582Sjkim    /* Simplest case is a null pathname */
790245582Sjkim
791167802Sjkim    if (!Pathname)
79267754Smsmith    {
793167802Sjkim        *ReturnNode = PrefixNode;
794167802Sjkim        if (!PrefixNode)
795114237Snjl        {
796167802Sjkim            *ReturnNode = AcpiGbl_RootNode;
797114237Snjl        }
798167802Sjkim        return_ACPI_STATUS (AE_OK);
79967754Smsmith    }
80067754Smsmith
801245582Sjkim    /* Quick check for a reference to the root */
802245582Sjkim
803245582Sjkim    if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1]))
804245582Sjkim    {
805245582Sjkim        *ReturnNode = AcpiGbl_RootNode;
806245582Sjkim        return_ACPI_STATUS (AE_OK);
807245582Sjkim    }
808245582Sjkim
809167802Sjkim    /* Convert path to internal representation */
810167802Sjkim
811167802Sjkim    Status = AcpiNsInternalizeName (Pathname, &InternalPath);
812167802Sjkim    if (ACPI_FAILURE (Status))
813167802Sjkim    {
814167802Sjkim        return_ACPI_STATUS (Status);
815167802Sjkim    }
816167802Sjkim
81791116Smsmith    /* Must lock namespace during lookup */
81867754Smsmith
81991116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
82091116Smsmith    if (ACPI_FAILURE (Status))
82191116Smsmith    {
822126372Snjl        goto Cleanup;
82391116Smsmith    }
82467754Smsmith
82569746Smsmith    /* Setup lookup scope (search starting point) */
82667754Smsmith
827167802Sjkim    ScopeInfo.Scope.Node = PrefixNode;
82867754Smsmith
82967754Smsmith    /* Lookup the name in the namespace */
83067754Smsmith
831167802Sjkim    Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
832167802Sjkim                ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
833167802Sjkim                NULL, ReturnNode);
83467754Smsmith    if (ACPI_FAILURE (Status))
83567754Smsmith    {
836193267Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
837167802Sjkim                Pathname, AcpiFormatException (Status)));
83867754Smsmith    }
83967754Smsmith
84091116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
841114237Snjl
842126372SnjlCleanup:
843167802Sjkim    ACPI_FREE (InternalPath);
84467754Smsmith    return_ACPI_STATUS (Status);
84567754Smsmith}
846