167754Smsmith/******************************************************************************
267754Smsmith *
377424Smsmith * Module Name: exnames - interpreter/scanner name load/execute
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
47193341Sjkim#include <contrib/dev/acpica/include/amlcode.h>
4867754Smsmith
4977424Smsmith#define _COMPONENT          ACPI_EXECUTER
5091116Smsmith        ACPI_MODULE_NAME    ("exnames")
5167754Smsmith
52151937Sjkim/* Local prototypes */
5367754Smsmith
54151937Sjkimstatic char *
55151937SjkimAcpiExAllocateNameString (
56151937Sjkim    UINT32                  PrefixCount,
57151937Sjkim    UINT32                  NumNameSegs);
5867754Smsmith
59151937Sjkimstatic ACPI_STATUS
60151937SjkimAcpiExNameSegment (
61151937Sjkim    UINT8                   **InAmlAddress,
62151937Sjkim    char                    *NameString);
6367754Smsmith
6467754Smsmith
6567754Smsmith/*******************************************************************************
6667754Smsmith *
6777424Smsmith * FUNCTION:    AcpiExAllocateNameString
6867754Smsmith *
6967754Smsmith * PARAMETERS:  PrefixCount         - Count of parent levels. Special cases:
70151937Sjkim *                                    (-1)==root,  0==none
7167754Smsmith *              NumNameSegs         - count of 4-character name segments
7267754Smsmith *
73241973Sjkim * RETURN:      A pointer to the allocated string segment. This segment must
7467754Smsmith *              be deleted by the caller.
7567754Smsmith *
7667754Smsmith * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
7767754Smsmith *              string is long enough, and set up prefix if any.
7867754Smsmith *
7967754Smsmith ******************************************************************************/
8067754Smsmith
81151937Sjkimstatic char *
8277424SmsmithAcpiExAllocateNameString (
8367754Smsmith    UINT32                  PrefixCount,
8467754Smsmith    UINT32                  NumNameSegs)
8567754Smsmith{
86114237Snjl    char                    *TempPtr;
87114237Snjl    char                    *NameString;
8867754Smsmith    UINT32                   SizeNeeded;
8967754Smsmith
90167802Sjkim    ACPI_FUNCTION_TRACE (ExAllocateNameString);
9167754Smsmith
9267754Smsmith
9367754Smsmith    /*
94151937Sjkim     * Allow room for all \ and ^ prefixes, all segments and a MultiNamePrefix.
9567754Smsmith     * Also, one byte for the null terminator.
9667754Smsmith     * This may actually be somewhat longer than needed.
9767754Smsmith     */
9891116Smsmith    if (PrefixCount == ACPI_UINT32_MAX)
9967754Smsmith    {
10067754Smsmith        /* Special case for root */
10167754Smsmith
10267754Smsmith        SizeNeeded = 1 + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
10367754Smsmith    }
10467754Smsmith    else
10567754Smsmith    {
10667754Smsmith        SizeNeeded = PrefixCount + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
10767754Smsmith    }
10867754Smsmith
10967754Smsmith    /*
11067754Smsmith     * Allocate a buffer for the name.
11167754Smsmith     * This buffer must be deleted by the caller!
11267754Smsmith     */
113167802Sjkim    NameString = ACPI_ALLOCATE (SizeNeeded);
11467754Smsmith    if (!NameString)
11567754Smsmith    {
116167802Sjkim        ACPI_ERROR ((AE_INFO,
117204773Sjkim            "Could not allocate size %u", SizeNeeded));
11867754Smsmith        return_PTR (NULL);
11967754Smsmith    }
12067754Smsmith
12167754Smsmith    TempPtr = NameString;
12267754Smsmith
12367754Smsmith    /* Set up Root or Parent prefixes if needed */
12467754Smsmith
12591116Smsmith    if (PrefixCount == ACPI_UINT32_MAX)
12667754Smsmith    {
12767754Smsmith        *TempPtr++ = AML_ROOT_PREFIX;
12867754Smsmith    }
12967754Smsmith    else
13067754Smsmith    {
13167754Smsmith        while (PrefixCount--)
13267754Smsmith        {
13367754Smsmith            *TempPtr++ = AML_PARENT_PREFIX;
13467754Smsmith        }
13567754Smsmith    }
13667754Smsmith
13767754Smsmith
13867754Smsmith    /* Set up Dual or Multi prefixes if needed */
13967754Smsmith
14067754Smsmith    if (NumNameSegs > 2)
14167754Smsmith    {
14267754Smsmith        /* Set up multi prefixes   */
14367754Smsmith
14467754Smsmith        *TempPtr++ = AML_MULTI_NAME_PREFIX_OP;
14567754Smsmith        *TempPtr++ = (char) NumNameSegs;
14667754Smsmith    }
14767754Smsmith    else if (2 == NumNameSegs)
14867754Smsmith    {
14967754Smsmith        /* Set up dual prefixes */
15067754Smsmith
15167754Smsmith        *TempPtr++ = AML_DUAL_NAME_PREFIX;
15267754Smsmith    }
15367754Smsmith
15467754Smsmith    /*
15577424Smsmith     * Terminate string following prefixes. AcpiExNameSegment() will
15667754Smsmith     * append the segment(s)
15767754Smsmith     */
15867754Smsmith    *TempPtr = 0;
15967754Smsmith
16067754Smsmith    return_PTR (NameString);
16167754Smsmith}
16267754Smsmith
163306536Sjkim
16467754Smsmith/*******************************************************************************
16567754Smsmith *
16677424Smsmith * FUNCTION:    AcpiExNameSegment
16767754Smsmith *
168151937Sjkim * PARAMETERS:  InAmlAddress    - Pointer to the name in the AML code
169151937Sjkim *              NameString      - Where to return the name. The name is appended
170151937Sjkim *                                to any existing string to form a namepath
17167754Smsmith *
17267754Smsmith * RETURN:      Status
17367754Smsmith *
174151937Sjkim * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
17567754Smsmith *
17667754Smsmith ******************************************************************************/
17767754Smsmith
178151937Sjkimstatic ACPI_STATUS
17977424SmsmithAcpiExNameSegment (
18067754Smsmith    UINT8                   **InAmlAddress,
181114237Snjl    char                    *NameString)
18267754Smsmith{
18399679Siwasaki    char                    *AmlAddress = (void *) *InAmlAddress;
18467754Smsmith    ACPI_STATUS             Status = AE_OK;
18567754Smsmith    UINT32                  Index;
18699679Siwasaki    char                    CharBuf[5];
18767754Smsmith
18867754Smsmith
189167802Sjkim    ACPI_FUNCTION_TRACE (ExNameSegment);
19067754Smsmith
19167754Smsmith
19267754Smsmith    /*
193306536Sjkim     * If first character is a digit, then we know that we aren't looking
194306536Sjkim     * at a valid name segment
19567754Smsmith     */
19667754Smsmith    CharBuf[0] = *AmlAddress;
19767754Smsmith
19867754Smsmith    if ('0' <= CharBuf[0] && CharBuf[0] <= '9')
19967754Smsmith    {
200167802Sjkim        ACPI_ERROR ((AE_INFO, "Invalid leading digit: %c", CharBuf[0]));
20167754Smsmith        return_ACPI_STATUS (AE_CTRL_PENDING);
20267754Smsmith    }
20367754Smsmith
20482367Smsmith    ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
20567754Smsmith
20699679Siwasaki    for (Index = 0;
207306536Sjkim        (Index < ACPI_NAME_SIZE) && (AcpiUtValidNameChar (*AmlAddress, 0));
20899679Siwasaki        Index++)
20967754Smsmith    {
21099679Siwasaki        CharBuf[Index] = *AmlAddress++;
21199679Siwasaki        ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", CharBuf[Index]));
21267754Smsmith    }
21367754Smsmith
21467754Smsmith
21567754Smsmith    /* Valid name segment  */
21667754Smsmith
21799679Siwasaki    if (Index == 4)
21867754Smsmith    {
21967754Smsmith        /* Found 4 valid characters */
22067754Smsmith
22167754Smsmith        CharBuf[4] = '\0';
22267754Smsmith
22367754Smsmith        if (NameString)
22467754Smsmith        {
225306536Sjkim            strcat (NameString, CharBuf);
22682367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
227151937Sjkim                "Appended to - %s\n", NameString));
22867754Smsmith        }
22967754Smsmith        else
23067754Smsmith        {
23182367Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
232151937Sjkim                "No Name string - %s\n", CharBuf));
23367754Smsmith        }
23467754Smsmith    }
23599679Siwasaki    else if (Index == 0)
23667754Smsmith    {
23767754Smsmith        /*
23867754Smsmith         * First character was not a valid name character,
23967754Smsmith         * so we are looking at something other than a name.
24067754Smsmith         */
24182367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
24282367Smsmith            "Leading character is not alpha: %02Xh (not a name)\n",
24367754Smsmith            CharBuf[0]));
24467754Smsmith        Status = AE_CTRL_PENDING;
24567754Smsmith    }
24667754Smsmith    else
24767754Smsmith    {
248151937Sjkim        /*
249151937Sjkim         * Segment started with one or more valid characters, but fewer than
250151937Sjkim         * the required 4
251151937Sjkim         */
25267754Smsmith        Status = AE_AML_BAD_NAME;
253167802Sjkim        ACPI_ERROR ((AE_INFO,
254204773Sjkim            "Bad character 0x%02x in name, at %p",
25567754Smsmith            *AmlAddress, AmlAddress));
25667754Smsmith    }
25767754Smsmith
258167802Sjkim    *InAmlAddress = ACPI_CAST_PTR (UINT8, AmlAddress);
25967754Smsmith    return_ACPI_STATUS (Status);
26067754Smsmith}
26167754Smsmith
26267754Smsmith
26367754Smsmith/*******************************************************************************
26467754Smsmith *
26577424Smsmith * FUNCTION:    AcpiExGetNameString
26667754Smsmith *
267151937Sjkim * PARAMETERS:  DataType            - Object type to be associated with this
268151937Sjkim *                                    name
269151937Sjkim *              InAmlAddress        - Pointer to the namestring in the AML code
270151937Sjkim *              OutNameString       - Where the namestring is returned
271151937Sjkim *              OutNameLength       - Length of the returned string
27267754Smsmith *
273151937Sjkim * RETURN:      Status, namestring and length
27467754Smsmith *
275151937Sjkim * DESCRIPTION: Extract a full namepath from the AML byte stream,
276151937Sjkim *              including any prefixes.
27767754Smsmith *
27867754Smsmith ******************************************************************************/
27967754Smsmith
28067754SmsmithACPI_STATUS
28177424SmsmithAcpiExGetNameString (
28291116Smsmith    ACPI_OBJECT_TYPE        DataType,
28367754Smsmith    UINT8                   *InAmlAddress,
284114237Snjl    char                    **OutNameString,
28567754Smsmith    UINT32                  *OutNameLength)
28667754Smsmith{
28767754Smsmith    ACPI_STATUS             Status = AE_OK;
28867754Smsmith    UINT8                   *AmlAddress = InAmlAddress;
289114237Snjl    char                    *NameString = NULL;
29067754Smsmith    UINT32                  NumSegments;
29167754Smsmith    UINT32                  PrefixCount = 0;
29267754Smsmith    BOOLEAN                 HasPrefix = FALSE;
29367754Smsmith
29467754Smsmith
295167802Sjkim    ACPI_FUNCTION_TRACE_PTR (ExGetNameString, AmlAddress);
29667754Smsmith
29767754Smsmith
298107325Siwasaki    if (ACPI_TYPE_LOCAL_REGION_FIELD == DataType   ||
299107325Siwasaki        ACPI_TYPE_LOCAL_BANK_FIELD == DataType     ||
300107325Siwasaki        ACPI_TYPE_LOCAL_INDEX_FIELD == DataType)
30167754Smsmith    {
30277424Smsmith        /* Disallow prefixes for types associated with FieldUnit names */
30367754Smsmith
30477424Smsmith        NameString = AcpiExAllocateNameString (0, 1);
30567754Smsmith        if (!NameString)
30667754Smsmith        {
30767754Smsmith            Status = AE_NO_MEMORY;
30867754Smsmith        }
30967754Smsmith        else
31067754Smsmith        {
31177424Smsmith            Status = AcpiExNameSegment (&AmlAddress, NameString);
31267754Smsmith        }
31367754Smsmith    }
31467754Smsmith    else
31567754Smsmith    {
31667754Smsmith        /*
31767754Smsmith         * DataType is not a field name.
31867754Smsmith         * Examine first character of name for root or parent prefix operators
31967754Smsmith         */
32067754Smsmith        switch (*AmlAddress)
32167754Smsmith        {
32267754Smsmith        case AML_ROOT_PREFIX:
32367754Smsmith
324151937Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "RootPrefix(\\) at %p\n",
325151937Sjkim                AmlAddress));
32667754Smsmith
32767754Smsmith            /*
32867754Smsmith             * Remember that we have a RootPrefix --
32977424Smsmith             * see comment in AcpiExAllocateNameString()
33067754Smsmith             */
33191116Smsmith            AmlAddress++;
33291116Smsmith            PrefixCount = ACPI_UINT32_MAX;
33367754Smsmith            HasPrefix = TRUE;
33467754Smsmith            break;
33567754Smsmith
33667754Smsmith        case AML_PARENT_PREFIX:
33767754Smsmith
33867754Smsmith            /* Increment past possibly multiple parent prefixes */
33967754Smsmith
34067754Smsmith            do
34167754Smsmith            {
342151937Sjkim                ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n",
343151937Sjkim                    AmlAddress));
34467754Smsmith
34591116Smsmith                AmlAddress++;
34691116Smsmith                PrefixCount++;
34767754Smsmith
34867754Smsmith            } while (*AmlAddress == AML_PARENT_PREFIX);
34991116Smsmith
35067754Smsmith            HasPrefix = TRUE;
35167754Smsmith            break;
35267754Smsmith
35367754Smsmith        default:
35467754Smsmith
35591116Smsmith            /* Not a prefix character */
35691116Smsmith
35767754Smsmith            break;
35867754Smsmith        }
35967754Smsmith
36067754Smsmith        /* Examine first character of name for name segment prefix operator */
36167754Smsmith
36267754Smsmith        switch (*AmlAddress)
36367754Smsmith        {
36467754Smsmith        case AML_DUAL_NAME_PREFIX:
36567754Smsmith
366151937Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n",
367151937Sjkim                AmlAddress));
36867754Smsmith
36991116Smsmith            AmlAddress++;
37077424Smsmith            NameString = AcpiExAllocateNameString (PrefixCount, 2);
37167754Smsmith            if (!NameString)
37267754Smsmith            {
37367754Smsmith                Status = AE_NO_MEMORY;
37467754Smsmith                break;
37567754Smsmith            }
37667754Smsmith
37767754Smsmith            /* Indicate that we processed a prefix */
37883174Smsmith
37967754Smsmith            HasPrefix = TRUE;
38067754Smsmith
38177424Smsmith            Status = AcpiExNameSegment (&AmlAddress, NameString);
38267754Smsmith            if (ACPI_SUCCESS (Status))
38367754Smsmith            {
38477424Smsmith                Status = AcpiExNameSegment (&AmlAddress, NameString);
38567754Smsmith            }
38667754Smsmith            break;
38767754Smsmith
38867754Smsmith        case AML_MULTI_NAME_PREFIX_OP:
38967754Smsmith
390151937Sjkim            ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n",
391151937Sjkim                AmlAddress));
39267754Smsmith
39367754Smsmith            /* Fetch count of segments remaining in name path */
39467754Smsmith
39591116Smsmith            AmlAddress++;
39691116Smsmith            NumSegments = *AmlAddress;
39767754Smsmith
398306536Sjkim            NameString = AcpiExAllocateNameString (
399306536Sjkim                PrefixCount, NumSegments);
40067754Smsmith            if (!NameString)
40167754Smsmith            {
40267754Smsmith                Status = AE_NO_MEMORY;
40367754Smsmith                break;
40467754Smsmith            }
40567754Smsmith
40667754Smsmith            /* Indicate that we processed a prefix */
40783174Smsmith
40891116Smsmith            AmlAddress++;
40967754Smsmith            HasPrefix = TRUE;
41067754Smsmith
41167754Smsmith            while (NumSegments &&
412151937Sjkim                    (Status = AcpiExNameSegment (&AmlAddress, NameString)) ==
413151937Sjkim                        AE_OK)
41467754Smsmith            {
41591116Smsmith                NumSegments--;
41667754Smsmith            }
41767754Smsmith
41867754Smsmith            break;
41967754Smsmith
42067754Smsmith        case 0:
42167754Smsmith
42267754Smsmith            /* NullName valid as of 8-12-98 ASL/AML Grammar Update */
42367754Smsmith
42491116Smsmith            if (PrefixCount == ACPI_UINT32_MAX)
42567754Smsmith            {
426151937Sjkim                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
427151937Sjkim                    "NameSeg is \"\\\" followed by NULL\n"));
42867754Smsmith            }
42967754Smsmith
43067754Smsmith            /* Consume the NULL byte */
43167754Smsmith
43267754Smsmith            AmlAddress++;
43377424Smsmith            NameString = AcpiExAllocateNameString (PrefixCount, 0);
43467754Smsmith            if (!NameString)
43567754Smsmith            {
43667754Smsmith                Status = AE_NO_MEMORY;
43767754Smsmith                break;
43867754Smsmith            }
43967754Smsmith
44067754Smsmith            break;
44167754Smsmith
44267754Smsmith        default:
44367754Smsmith
44467754Smsmith            /* Name segment string */
44567754Smsmith
44677424Smsmith            NameString = AcpiExAllocateNameString (PrefixCount, 1);
44767754Smsmith            if (!NameString)
44867754Smsmith            {
44967754Smsmith                Status = AE_NO_MEMORY;
45067754Smsmith                break;
45167754Smsmith            }
45267754Smsmith
45377424Smsmith            Status = AcpiExNameSegment (&AmlAddress, NameString);
45467754Smsmith            break;
45591116Smsmith        }
45667754Smsmith    }
45767754Smsmith
45867754Smsmith    if (AE_CTRL_PENDING == Status && HasPrefix)
45967754Smsmith    {
46067754Smsmith        /* Ran out of segments after processing a prefix */
46167754Smsmith
462167802Sjkim        ACPI_ERROR ((AE_INFO,
463167802Sjkim            "Malformed Name at %p", NameString));
46467754Smsmith        Status = AE_AML_BAD_NAME;
46567754Smsmith    }
46667754Smsmith
467151937Sjkim    if (ACPI_FAILURE (Status))
468151937Sjkim    {
469151937Sjkim        if (NameString)
470151937Sjkim        {
471167802Sjkim            ACPI_FREE (NameString);
472151937Sjkim        }
473151937Sjkim        return_ACPI_STATUS (Status);
474151937Sjkim    }
475151937Sjkim
47667754Smsmith    *OutNameString = NameString;
47767754Smsmith    *OutNameLength = (UINT32) (AmlAddress - InAmlAddress);
47867754Smsmith
47967754Smsmith    return_ACPI_STATUS (Status);
48067754Smsmith}
481