nsaccess.c revision 129684
165793Smsmith/*******************************************************************************
265793Smsmith *
381150Sscottl * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
465793Smsmith *              $Revision: 182 $
581082Sscottl *
665793Smsmith ******************************************************************************/
765793Smsmith
865793Smsmith/******************************************************************************
965793Smsmith *
1065793Smsmith * 1. Copyright Notice
1165793Smsmith *
1265793Smsmith * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp.
1365793Smsmith * All rights reserved.
1465793Smsmith *
1565793Smsmith * 2. License
1665793Smsmith *
1765793Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property
1865793Smsmith * rights.  You may have additional license terms from the party that provided
1965793Smsmith * you this software, covering your right to use that party's intellectual
2065793Smsmith * property rights.
2165793Smsmith *
2265793Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2365793Smsmith * copy of the source code appearing in this file ("Covered Code") an
2465793Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2565793Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy,
2665793Smsmith * make derivatives, distribute, use and display any portion of the Covered
2765793Smsmith * Code in any form, with the right to sublicense such rights; and
2865793Smsmith *
2965793Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3065793Smsmith * license (with the right to sublicense), under only those claims of Intel
3165793Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell,
3265793Smsmith * offer to sell, and import the Covered Code and derivative works thereof
3365793Smsmith * solely to the minimum extent necessary to exercise the above copyright
3465793Smsmith * license, and in no event shall the patent license extend to any additions
3565793Smsmith * to or modifications of the Original Intel Code.  No other license or right
3665793Smsmith * is granted directly or by implication, estoppel or otherwise;
3765793Smsmith *
3865793Smsmith * The above copyright and patent license is granted only if the following
3983114Sscottl * conditions are met:
4065793Smsmith *
4165793Smsmith * 3. Conditions
4265793Smsmith *
4365793Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4465793Smsmith * Redistribution of source code of any substantial portion of the Covered
4583114Sscottl * Code or modification with rights to further distribute source must include
4665793Smsmith * the above Copyright Notice, the above License, this list of Conditions,
4765793Smsmith * and the following Disclaimer and Export Compliance provision.  In addition,
4865793Smsmith * Licensee must cause all Covered Code to which Licensee contributes to
4965793Smsmith * contain a file documenting the changes Licensee made to create that Covered
5065793Smsmith * Code and the date of any change.  Licensee must include in that file the
5165793Smsmith * documentation of any changes made by any predecessor Licensee.  Licensee
5265793Smsmith * must include a prominent statement that the modification is derived,
5365793Smsmith * directly or indirectly, from Original Intel Code.
5465793Smsmith *
5565793Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5681082Sscottl * Redistribution of source code of any substantial portion of the Covered
5781082Sscottl * Code or modification without rights to further distribute source must
5881082Sscottl * include the following Disclaimer and Export Compliance provision in the
5981082Sscottl * documentation and/or other materials provided with distribution.  In
6081082Sscottl * addition, Licensee may not authorize further sublicense of source of any
6181082Sscottl * portion of the Covered Code, and must include terms to the effect that the
6281082Sscottl * license from Licensee to its licensee is limited to the intellectual
6381082Sscottl * property embodied in the software Licensee provides to its licensee, and
6481082Sscottl * not to intellectual property embodied in modifications its licensee may
6581082Sscottl * make.
6681082Sscottl *
6781082Sscottl * 3.3. Redistribution of Executable. Redistribution in executable form of any
6881082Sscottl * substantial portion of the Covered Code or modification must reproduce the
6981082Sscottl * above Copyright Notice, and the following Disclaimer and Export Compliance
7081082Sscottl * provision in the documentation and/or other materials provided with the
7181082Sscottl * distribution.
7265793Smsmith *
7365793Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original
7465793Smsmith * Intel Code.
7565793Smsmith *
7665793Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7765793Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or
7865793Smsmith * other dealings in products derived from or relating to the Covered Code
7965793Smsmith * without prior written authorization from Intel.
8065793Smsmith *
8165793Smsmith * 4. Disclaimer and Export Compliance
8265793Smsmith *
8365793Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8465793Smsmith * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8583114Sscottl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8683114Sscottl * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87103870Salfred * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8865793Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8965793Smsmith * PARTICULAR PURPOSE.
9065793Smsmith *
9165793Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9265793Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9365793Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9465793Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9565793Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9665793Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9783114Sscottl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9883114Sscottl * LIMITED REMEDY.
9965793Smsmith *
10083114Sscottl * 4.3. Licensee shall not export, either directly or indirectly, any of this
10183114Sscottl * software or system incorporating such software without first obtaining any
10283114Sscottl * required license or other approval from the U. S. Department of Commerce or
10383114Sscottl * any other agency or department of the United States Government.  In the
10483114Sscottl * event Licensee exports any such software from the United States or
10583114Sscottl * re-exports any such software from a foreign destination, Licensee shall
10683114Sscottl * ensure that the distribution and export/re-export of the software is in
10783114Sscottl * compliance with all laws, regulations, orders, or other restrictions of the
10883114Sscottl * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109103870Salfred * any of its subsidiaries will export/re-export any technical data, process,
11065793Smsmith * software, or service, directly or indirectly, to any country for which the
11165793Smsmith * United States government or any agency thereof requires an export license,
11265793Smsmith * other governmental approval, or letter of assurance, without first obtaining
11365793Smsmith * such license, approval or letter.
11465793Smsmith *
11565793Smsmith *****************************************************************************/
11665793Smsmith
11765793Smsmith#define __NSACCESS_C__
11865793Smsmith
11965793Smsmith#include "acpi.h"
12065793Smsmith#include "amlcode.h"
12165793Smsmith#include "acnamesp.h"
12265793Smsmith#include "acdispat.h"
12365793Smsmith
12465793Smsmith
12565793Smsmith#define _COMPONENT          ACPI_NAMESPACE
12665793Smsmith        ACPI_MODULE_NAME    ("nsaccess")
12765793Smsmith
12865793Smsmith
12965793Smsmith/*******************************************************************************
13065793Smsmith *
131109088Sscottl * FUNCTION:    AcpiNsRootInitialize
132109088Sscottl *
133103870Salfred * PARAMETERS:  None
13465793Smsmith *
13565793Smsmith * RETURN:      Status
13665793Smsmith *
13765793Smsmith * DESCRIPTION: Allocate and initialize the default root named objects
13865793Smsmith *
13965793Smsmith * MUTEX:       Locks namespace for entire execution
14083114Sscottl *
14183114Sscottl ******************************************************************************/
14283114Sscottl
14383114SscottlACPI_STATUS
14483114SscottlAcpiNsRootInitialize (void)
14583114Sscottl{
14683114Sscottl    ACPI_STATUS                 Status;
14783114Sscottl    const ACPI_PREDEFINED_NAMES *InitVal = NULL;
14883114Sscottl    ACPI_NAMESPACE_NODE         *NewNode;
14983114Sscottl    ACPI_OPERAND_OBJECT         *ObjDesc;
15083114Sscottl    ACPI_STRING                 Val = NULL;
15183114Sscottl
15283114Sscottl
15383114Sscottl    ACPI_FUNCTION_TRACE ("NsRootInitialize");
15483114Sscottl
15583114Sscottl
156103870Salfred    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
15765793Smsmith    if (ACPI_FAILURE (Status))
15865793Smsmith    {
15965793Smsmith        return_ACPI_STATUS (Status);
16065793Smsmith    }
16183114Sscottl
16283114Sscottl    /*
163103870Salfred     * The global root ptr is initially NULL, so a non-NULL value indicates
16465793Smsmith     * that AcpiNsRootInitialize() has already been called; just return.
16565793Smsmith     */
16665793Smsmith    if (AcpiGbl_RootNode)
16765793Smsmith    {
16865793Smsmith        Status = AE_OK;
16983114Sscottl        goto UnlockAndExit;
17083114Sscottl    }
17165793Smsmith
17283114Sscottl    /*
17383114Sscottl     * Tell the rest of the subsystem that the root is initialized
17483114Sscottl     * (This is OK because the namespace is locked)
17583114Sscottl     */
17683114Sscottl    AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct;
17783114Sscottl
17883114Sscottl    /* Enter the pre-defined names in the name table */
17983114Sscottl
18083114Sscottl    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
18183114Sscottl        "Entering predefined entries into namespace\n"));
18283114Sscottl
18383114Sscottl    for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++)
18483114Sscottl    {
18583114Sscottl        /* _OSI is optional for now, will be permanent later */
18683114Sscottl
18783114Sscottl        if (!ACPI_STRCMP (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod)
18883114Sscottl        {
18983114Sscottl            continue;
19083114Sscottl        }
19183114Sscottl
19283114Sscottl        Status = AcpiNsLookup (NULL, InitVal->Name, InitVal->Type,
19365793Smsmith                        ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
19483114Sscottl                        NULL, &NewNode);
19583114Sscottl
19683114Sscottl        if (ACPI_FAILURE (Status) || (!NewNode)) /* Must be on same line for code converter */
19783114Sscottl        {
19883114Sscottl            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
19965793Smsmith                "Could not create predefined name %s, %s\n",
20083114Sscottl                InitVal->Name, AcpiFormatException (Status)));
20183114Sscottl        }
20283114Sscottl
203151086Sscottl        /*
20465793Smsmith         * Name entered successfully.
20583114Sscottl         * If entry in PreDefinedNames[] specifies an
20683114Sscottl         * initial value, create the initial value.
20765793Smsmith         */
20883114Sscottl        if (InitVal->Val)
20983114Sscottl        {
210151086Sscottl            Status = AcpiOsPredefinedOverride (InitVal, &Val);
211151086Sscottl            if (ACPI_FAILURE (Status))
212151086Sscottl            {
213151086Sscottl                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
21465793Smsmith                    "Could not override predefined %s\n",
21583114Sscottl                    InitVal->Name));
21683114Sscottl            }
21783114Sscottl
21883114Sscottl            if (!Val)
21983114Sscottl            {
22083114Sscottl                Val = InitVal->Val;
22183114Sscottl            }
222151086Sscottl
223206534Semaste            /*
224151086Sscottl             * Entry requests an initial value, allocate a
225151086Sscottl             * descriptor for it.
226206534Semaste             */
227206534Semaste            ObjDesc = AcpiUtCreateInternalObject (InitVal->Type);
228206534Semaste            if (!ObjDesc)
229151086Sscottl            {
230151086Sscottl                Status = AE_NO_MEMORY;
231151086Sscottl                goto UnlockAndExit;
232151086Sscottl            }
233151086Sscottl
234151086Sscottl            /*
235206534Semaste             * Convert value string from table entry to
236206534Semaste             * internal representation. Only types actually
23765793Smsmith             * used for initial values are implemented here.
23865793Smsmith             */
23965793Smsmith            switch (InitVal->Type)
24065793Smsmith            {
24165793Smsmith            case ACPI_TYPE_METHOD:
24265793Smsmith                ObjDesc->Method.ParamCount = (UINT8) ACPI_STRTOUL
24365793Smsmith                                                        (Val, NULL, 10);
24465793Smsmith                ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
24565793Smsmith
24665793Smsmith#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_APP)
24765793Smsmith
24865793Smsmith                /* iASL Compiler cheats by putting parameter count in the OwnerID */
24981082Sscottl
25081082Sscottl                NewNode->OwnerId = ObjDesc->Method.ParamCount;
25181082Sscottl#else
25281082Sscottl                /* Mark this as a very SPECIAL method */
25381082Sscottl
25481082Sscottl                ObjDesc->Method.MethodFlags = AML_METHOD_INTERNAL_ONLY;
25581082Sscottl                ObjDesc->Method.Implementation = AcpiUtOsiImplementation;
25681082Sscottl#endif
25781082Sscottl                break;
25881082Sscottl
25981082Sscottl            case ACPI_TYPE_INTEGER:
26081082Sscottl
26181082Sscottl                ObjDesc->Integer.Value =
26281082Sscottl                        (ACPI_INTEGER) ACPI_STRTOUL (Val, NULL, 10);
26381082Sscottl                break;
26481082Sscottl
26581082Sscottl
26681082Sscottl            case ACPI_TYPE_STRING:
26781082Sscottl
26881082Sscottl                /*
26981082Sscottl                 * Build an object around the static string
27081082Sscottl                 */
27165793Smsmith                ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Val);
27265793Smsmith                ObjDesc->String.Pointer = Val;
27365793Smsmith                ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
27465793Smsmith                break;
27565793Smsmith
27665793Smsmith
27765793Smsmith            case ACPI_TYPE_MUTEX:
27865793Smsmith
27965793Smsmith                ObjDesc->Mutex.Node = NewNode;
28065793Smsmith                ObjDesc->Mutex.SyncLevel = (UINT8) ACPI_STRTOUL
28165793Smsmith                                                        (Val, NULL, 10);
28265793Smsmith
28365793Smsmith                if (ACPI_STRCMP (InitVal->Name, "_GL_") == 0)
28465793Smsmith                {
28565793Smsmith                    /*
286206534Semaste                     * Create a counting semaphore for the
28765793Smsmith                     * global lock
28865793Smsmith                     */
28965793Smsmith                    Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT,
29083114Sscottl                                            1, &ObjDesc->Mutex.Semaphore);
291109088Sscottl                    if (ACPI_FAILURE (Status))
292151086Sscottl                    {
29383114Sscottl                        goto UnlockAndExit;
294109088Sscottl                    }
29583114Sscottl
29683114Sscottl                    /*
29783114Sscottl                     * We just created the mutex for the
29883114Sscottl                     * global lock, save it
299109088Sscottl                     */
30083114Sscottl                    AcpiGbl_GlobalLockSemaphore = ObjDesc->Mutex.Semaphore;
30183114Sscottl                }
30283114Sscottl                else
30383114Sscottl                {
304109088Sscottl                    /* Create a mutex */
30583114Sscottl
30683114Sscottl                    Status = AcpiOsCreateSemaphore (1, 1,
307151086Sscottl                                        &ObjDesc->Mutex.Semaphore);
308151086Sscottl                    if (ACPI_FAILURE (Status))
309212628Semaste                    {
310212628Semaste                        goto UnlockAndExit;
311212628Semaste                    }
312151086Sscottl                }
313151086Sscottl                break;
314151086Sscottl
315103870Salfred
31665793Smsmith            default:
31783114Sscottl
31865793Smsmith                ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
31965793Smsmith                    InitVal->Type));
32065793Smsmith                AcpiUtRemoveReference (ObjDesc);
32165793Smsmith                ObjDesc = NULL;
32265793Smsmith                continue;
32365793Smsmith            }
32483114Sscottl
32583114Sscottl            /* Store pointer to value descriptor in the Node */
32683114Sscottl
32783114Sscottl            Status = AcpiNsAttachObject (NewNode, ObjDesc, ACPI_GET_OBJECT_TYPE (ObjDesc));
32883114Sscottl
32983114Sscottl            /* Remove local reference to the object */
33083114Sscottl
33183114Sscottl            AcpiUtRemoveReference (ObjDesc);
33283114Sscottl        }
33383114Sscottl    }
334206534Semaste
335206534Semaste
336206534SemasteUnlockAndExit:
337206534Semaste    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
338206534Semaste
339206534Semaste    /* Save a handle to "_GPE", it is always present */
340151086Sscottl
341206534Semaste    if (ACPI_SUCCESS (Status))
342151086Sscottl    {
343151086Sscottl        Status = AcpiNsGetNodeByPath ("\\_GPE", NULL, ACPI_NS_NO_UPSEARCH,
34465793Smsmith                        &AcpiGbl_FadtGpeDevice);
34565793Smsmith    }
34665793Smsmith
34765793Smsmith    return_ACPI_STATUS (Status);
34865793Smsmith}
34965793Smsmith
350206534Semaste
351206534Semaste/*******************************************************************************
352206534Semaste *
353206534Semaste * FUNCTION:    AcpiNsLookup
354206534Semaste *
355206534Semaste * PARAMETERS:  PrefixNode      - Search scope if name is not fully qualified
356206534Semaste *              Pathname        - Search pathname, in internal format
357206534Semaste *                                (as represented in the AML stream)
358206534Semaste *              Type            - Type associated with name
359206534Semaste *              InterpreterMode - IMODE_LOAD_PASS2 => add name if not found
360206534Semaste *              Flags           - Flags describing the search restrictions
36183114Sscottl *              WalkState       - Current state of the walk
362206534Semaste *              ReturnNode      - Where the Node is placed (if found
363206534Semaste *                                or created successfully)
364206534Semaste *
365206534Semaste * RETURN:      Status
366206534Semaste *
36765793Smsmith * DESCRIPTION: Find or enter the passed name in the name space.
36865793Smsmith *              Log an error if name not found in Exec mode.
36965793Smsmith *
37065793Smsmith * MUTEX:       Assumes namespace is locked.
37165793Smsmith *
37265793Smsmith ******************************************************************************/
37383114Sscottl
37483114SscottlACPI_STATUS
375103870SalfredAcpiNsLookup (
37665793Smsmith    ACPI_GENERIC_STATE      *ScopeInfo,
377112679Sscottl    char                    *Pathname,
378112679Sscottl    ACPI_OBJECT_TYPE        Type,
379112679Sscottl    ACPI_INTERPRETER_MODE   InterpreterMode,
380112679Sscottl    UINT32                  Flags,
381112679Sscottl    ACPI_WALK_STATE         *WalkState,
382151086Sscottl    ACPI_NAMESPACE_NODE     **ReturnNode)
383151086Sscottl{
384151086Sscottl    ACPI_STATUS             Status;
385151086Sscottl    char                    *Path = Pathname;
386151086Sscottl    ACPI_NAMESPACE_NODE     *PrefixNode;
387151086Sscottl    ACPI_NAMESPACE_NODE     *CurrentNode = NULL;
388151086Sscottl    ACPI_NAMESPACE_NODE     *ThisNode = NULL;
389151086Sscottl    UINT32                  NumSegments;
39065793Smsmith    UINT32                  NumCarats;
39183114Sscottl    ACPI_NAME               SimpleName;
39283114Sscottl    ACPI_OBJECT_TYPE        TypeToCheckFor;
393103870Salfred    ACPI_OBJECT_TYPE        ThisSearchType;
39465793Smsmith    UINT32                  SearchParentFlag = ACPI_NS_SEARCH_PARENT;
39565793Smsmith    UINT32                  LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND |
39665793Smsmith                                                   ACPI_NS_SEARCH_PARENT);
39765793Smsmith
39865793Smsmith
399112679Sscottl    ACPI_FUNCTION_TRACE ("NsLookup");
400112679Sscottl
401103870Salfred
40265793Smsmith    if (!ReturnNode)
40365793Smsmith    {
404151086Sscottl        return_ACPI_STATUS (AE_BAD_PARAMETER);
405151086Sscottl    }
406151086Sscottl
407151086Sscottl    AcpiGbl_NsLookupCount++;
408151086Sscottl    *ReturnNode = ACPI_ENTRY_NOT_FOUND;
409151086Sscottl
410151086Sscottl    if (!AcpiGbl_RootNode)
411151086Sscottl    {
41265793Smsmith        return_ACPI_STATUS (AE_NO_NAMESPACE);
41365793Smsmith    }
41465793Smsmith
41583114Sscottl    /*
41683114Sscottl     * Get the prefix scope.
41783114Sscottl     * A null scope means use the root scope
41883114Sscottl     */
41983114Sscottl    if ((!ScopeInfo) ||
42083114Sscottl        (!ScopeInfo->Scope.Node))
42183114Sscottl    {
42283114Sscottl        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
42383114Sscottl            "Null scope prefix, using root node (%p)\n",
42483114Sscottl            AcpiGbl_RootNode));
425103870Salfred
42665793Smsmith        PrefixNode = AcpiGbl_RootNode;
42783114Sscottl    }
42865793Smsmith    else
42965793Smsmith    {
43065793Smsmith        PrefixNode = ScopeInfo->Scope.Node;
43165793Smsmith        if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED)
43283114Sscottl        {
43383114Sscottl            ACPI_REPORT_ERROR (("NsLookup: %p is not a namespace node [%s]\n",
43483114Sscottl                    PrefixNode, AcpiUtGetDescriptorName (PrefixNode)));
43583114Sscottl            return_ACPI_STATUS (AE_AML_INTERNAL);
43683114Sscottl        }
43783114Sscottl
43883114Sscottl        /*
43983114Sscottl         * This node might not be a actual "scope" node (such as a
44083114Sscottl         * Device/Method, etc.)  It could be a Package or other object node.
44165793Smsmith         * Backup up the tree to find the containing scope node.
44265793Smsmith         */
44365793Smsmith        while (!AcpiNsOpensScope (PrefixNode->Type) &&
44483114Sscottl                PrefixNode->Type != ACPI_TYPE_ANY)
44583114Sscottl        {
44683114Sscottl            PrefixNode = AcpiNsGetParentNode (PrefixNode);
44783114Sscottl        }
44883114Sscottl    }
44983114Sscottl
45083114Sscottl    /* Save type   TBD: may be no longer necessary */
45183114Sscottl
45283114Sscottl    TypeToCheckFor = Type;
45383114Sscottl
454103870Salfred    /*
45565793Smsmith     * Begin examination of the actual pathname
45683114Sscottl     */
45765793Smsmith    if (!Pathname)
45865793Smsmith    {
45965793Smsmith        /* A Null NamePath is allowed and refers to the root */
46065793Smsmith
46183114Sscottl        NumSegments  = 0;
46283114Sscottl        ThisNode     = AcpiGbl_RootNode;
46383114Sscottl        Path     = "";
46483114Sscottl
46583114Sscottl        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
46683114Sscottl            "Null Pathname (Zero segments), Flags=%X\n", Flags));
46783114Sscottl    }
46883114Sscottl    else
469151086Sscottl    {
470151086Sscottl        /*
47183114Sscottl         * Name pointer is valid (and must be in internal name format)
472206534Semaste         *
47365793Smsmith         * Check for scope prefixes:
47465793Smsmith         *
47583114Sscottl         * As represented in the AML stream, a namepath consists of an
47683114Sscottl         * optional scope prefix followed by a name segment part.
47783114Sscottl         *
47883114Sscottl         * If present, the scope prefix is either a Root Prefix (in
47983114Sscottl         * which case the name is fully qualified), or one or more
48083114Sscottl         * Parent Prefixes (in which case the name's scope is relative
481151086Sscottl         * to the current scope).
48283114Sscottl         */
483151086Sscottl        if (*Path == (UINT8) AML_ROOT_PREFIX)
484151086Sscottl        {
485151086Sscottl            /* Pathname is fully qualified, start from the root */
486151086Sscottl
48783114Sscottl            ThisNode = AcpiGbl_RootNode;
48865793Smsmith            SearchParentFlag = ACPI_NS_NO_UPSEARCH;
48965793Smsmith
49065793Smsmith            /* Point to name segment part */
49183114Sscottl
49283114Sscottl            Path++;
49383114Sscottl
49483114Sscottl            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
49583114Sscottl                "Path is absolute from root [%p]\n", ThisNode));
49683114Sscottl        }
49783114Sscottl        else
49883114Sscottl        {
49983114Sscottl            /* Pathname is relative to current scope, start there */
50083114Sscottl
50183114Sscottl            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
50283114Sscottl                "Searching relative to prefix scope [%4.4s] (%p)\n",
50383114Sscottl                AcpiUtGetNodeName (PrefixNode), PrefixNode));
50483114Sscottl
50583114Sscottl            /*
50683114Sscottl             * Handle multiple Parent Prefixes (carat) by just getting
50783114Sscottl             * the parent node for each prefix instance.
50883114Sscottl             */
50983114Sscottl            ThisNode = PrefixNode;
51083114Sscottl            NumCarats = 0;
511151086Sscottl            while (*Path == (UINT8) AML_PARENT_PREFIX)
512151086Sscottl            {
513151086Sscottl                /* Name is fully qualified, no search rules apply */
514151086Sscottl
515151086Sscottl                SearchParentFlag = ACPI_NS_NO_UPSEARCH;
516151086Sscottl                /*
517151086Sscottl                 * Point past this prefix to the name segment
518151086Sscottl                 * part or the next Parent Prefix
519151086Sscottl                 */
520151086Sscottl                Path++;
521151086Sscottl
522151086Sscottl                /* Backup to the parent node */
523151086Sscottl
524151086Sscottl                NumCarats++;
52583114Sscottl                ThisNode = AcpiNsGetParentNode (ThisNode);
52665793Smsmith                if (!ThisNode)
52765793Smsmith                {
52865793Smsmith                    /* Current scope has no parent scope */
52983114Sscottl
53083114Sscottl                    ACPI_REPORT_ERROR (
53183114Sscottl                        ("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
53283114Sscottl                    return_ACPI_STATUS (AE_NOT_FOUND);
53383114Sscottl                }
534151086Sscottl            }
535151086Sscottl
53683114Sscottl            if (SearchParentFlag == ACPI_NS_NO_UPSEARCH)
537151086Sscottl            {
538151086Sscottl                ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
539151086Sscottl                    "Search scope is [%4.4s], path has %d carat(s)\n",
540151086Sscottl                    AcpiUtGetNodeName (ThisNode), NumCarats));
541151086Sscottl            }
54283114Sscottl        }
54365793Smsmith
54465793Smsmith        /*
54565793Smsmith         * Determine the number of ACPI name segments in this pathname.
54665793Smsmith         *
54765793Smsmith         * The segment part consists of either:
54865793Smsmith         *  - A Null name segment (0)
549206534Semaste         *  - A DualNamePrefix followed by two 4-byte name segments
55083114Sscottl         *  - A MultiNamePrefix followed by a byte indicating the
55183114Sscottl         *      number of segments and the segments themselves.
55283114Sscottl         *  - A single 4-byte name segment
55383114Sscottl         *
55483114Sscottl         * Examine the name prefix opcode, if any, to determine the number of
55565793Smsmith         * segments.
55665793Smsmith         */
557206534Semaste        switch (*Path)
55865793Smsmith        {
559206534Semaste        case 0:
56065793Smsmith            /*
56165793Smsmith             * Null name after a root or parent prefixes. We already
56265793Smsmith             * have the correct target node and there are no name segments.
56365793Smsmith             */
56465793Smsmith            NumSegments  = 0;
56565793Smsmith            Type = ThisNode->Type;
56665793Smsmith
56765793Smsmith            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
568112679Sscottl                "Prefix-only Pathname (Zero name segments), Flags=%X\n", Flags));
569112679Sscottl            break;
570112679Sscottl
571112679Sscottl        case AML_DUAL_NAME_PREFIX:
572112679Sscottl
573112679Sscottl            /* More than one NameSeg, search rules do not apply */
574112679Sscottl
575151086Sscottl            SearchParentFlag = ACPI_NS_NO_UPSEARCH;
576151086Sscottl
577151086Sscottl            /* Two segments, point to first name segment */
578151086Sscottl
579151086Sscottl            NumSegments = 2;
580151086Sscottl            Path++;
58165793Smsmith
582206534Semaste            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
58365793Smsmith                "Dual Pathname (2 segments, Flags=%X)\n", Flags));
58465793Smsmith            break;
58565793Smsmith
586206534Semaste        case AML_MULTI_NAME_PREFIX_OP:
58783114Sscottl
588206534Semaste            /* More than one NameSeg, search rules do not apply */
589206534Semaste
590206534Semaste            SearchParentFlag = ACPI_NS_NO_UPSEARCH;
59183114Sscottl
592206534Semaste            /* Extract segment count, point to first name segment */
593206534Semaste
59483114Sscottl            Path++;
59583114Sscottl            NumSegments = (UINT32) (UINT8) *Path;
59683114Sscottl            Path++;
59783114Sscottl
59883114Sscottl            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
599206534Semaste                "Multi Pathname (%d Segments, Flags=%X) \n",
60083114Sscottl                NumSegments, Flags));
60183114Sscottl            break;
60283114Sscottl
60383114Sscottl        default:
60483114Sscottl            /*
60583114Sscottl             * Not a Null name, no Dual or Multi prefix, hence there is
60683114Sscottl             * only one name segment and Pathname is already pointing to it.
607103870Salfred             */
60865793Smsmith            NumSegments = 1;
609206534Semaste
610174412Semaste            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
611174412Semaste                "Simple Pathname (1 segment, Flags=%X)\n", Flags));
612174412Semaste            break;
613174412Semaste        }
614174412Semaste
615174412Semaste        ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path));
616174412Semaste    }
617174412Semaste
618174412Semaste
619174412Semaste    /*
620174412Semaste     * Search namespace for each segment of the name.  Loop through and
621174412Semaste     * verify (or add to the namespace) each name segment.
622174412Semaste     *
623174412Semaste     * The object type is significant only at the last name
624174412Semaste     * segment.  (We don't care about the types along the path, only
625174412Semaste     * the type of the final target object.)
626174412Semaste     */
627174412Semaste    ThisSearchType = ACPI_TYPE_ANY;
628174412Semaste    CurrentNode = ThisNode;
629174412Semaste    while (NumSegments && CurrentNode)
630174412Semaste    {
631174412Semaste        NumSegments--;
632174412Semaste        if (!NumSegments)
633174412Semaste        {
634174412Semaste            /*
635174412Semaste             * This is the last segment, enable typechecking
636174412Semaste             */
637174412Semaste            ThisSearchType = Type;
638174412Semaste
639174412Semaste            /*
640174412Semaste             * Only allow automatic parent search (search rules) if the caller
641174412Semaste             * requested it AND we have a single, non-fully-qualified NameSeg
642174412Semaste             */
643174412Semaste            if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) &&
644174412Semaste                (Flags & ACPI_NS_SEARCH_PARENT))
645174412Semaste            {
646174412Semaste                LocalFlags |= ACPI_NS_SEARCH_PARENT;
647174412Semaste            }
648174412Semaste
649174412Semaste            /* Set error flag according to caller */
650174412Semaste
651174412Semaste            if (Flags & ACPI_NS_ERROR_IF_FOUND)
652174412Semaste            {
653174412Semaste                LocalFlags |= ACPI_NS_ERROR_IF_FOUND;
654174412Semaste            }
655174412Semaste        }
656174412Semaste
657174412Semaste        /* Extract one ACPI name from the front of the pathname */
658174412Semaste
659174412Semaste        ACPI_MOVE_32_TO_32 (&SimpleName, Path);
660174412Semaste
66183114Sscottl        /* Try to find the single (4 character) ACPI name */
66265793Smsmith
66365793Smsmith        Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode,
66465793Smsmith                        InterpreterMode, ThisSearchType, LocalFlags, &ThisNode);
66565793Smsmith        if (ACPI_FAILURE (Status))
66665793Smsmith        {
66765793Smsmith            if (Status == AE_NOT_FOUND)
668151086Sscottl            {
66965793Smsmith                /* Name not found in ACPI namespace */
67065793Smsmith
67190275Sscottl                ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
672151086Sscottl                    "Name [%4.4s] not found in scope [%4.4s] %p\n",
673112679Sscottl                    (char *) &SimpleName, (char *) &CurrentNode->Name,
674151086Sscottl                    CurrentNode));
675151086Sscottl            }
676151086Sscottl
677151086Sscottl            *ReturnNode = ThisNode;
67865793Smsmith            return_ACPI_STATUS (Status);
67965793Smsmith        }
68065793Smsmith
68165793Smsmith        /*
68265793Smsmith         * Sanity typecheck of the target object:
68365793Smsmith         *
68465793Smsmith         * If 1) This is the last segment (NumSegments == 0)
68565793Smsmith         *    2) And we are looking for a specific type
68665793Smsmith         *       (Not checking for TYPE_ANY)
68765793Smsmith         *    3) Which is not an alias
68865793Smsmith         *    4) Which is not a local type (TYPE_SCOPE)
68965793Smsmith         *    5) And the type of target object is known (not TYPE_ANY)
69065793Smsmith         *    6) And target object does not match what we are looking for
69165793Smsmith         *
692140669Sscottl         * Then we have a type mismatch.  Just warn and ignore it.
69365793Smsmith         */
69465793Smsmith        if ((NumSegments        == 0)                               &&
69565793Smsmith            (TypeToCheckFor     != ACPI_TYPE_ANY)                   &&
69683114Sscottl            (TypeToCheckFor     != ACPI_TYPE_LOCAL_ALIAS)           &&
697206534Semaste            (TypeToCheckFor     != ACPI_TYPE_LOCAL_METHOD_ALIAS)    &&
69865793Smsmith            (TypeToCheckFor     != ACPI_TYPE_LOCAL_SCOPE)           &&
69965793Smsmith            (ThisNode->Type     != ACPI_TYPE_ANY)                   &&
70065793Smsmith            (ThisNode->Type     != TypeToCheckFor))
70165793Smsmith        {
70265793Smsmith            /* Complain about a type mismatch */
70365793Smsmith
70465793Smsmith            ACPI_REPORT_WARNING (
70565793Smsmith                ("NsLookup: Type mismatch on %4.4s (%s), searching for (%s)\n",
70665793Smsmith                (char *) &SimpleName, AcpiUtGetTypeName (ThisNode->Type),
70783114Sscottl                AcpiUtGetTypeName (TypeToCheckFor)));
70883114Sscottl        }
70983114Sscottl
71083114Sscottl        /*
71183114Sscottl         * If this is the last name segment and we are not looking for a
71283114Sscottl         * specific type, but the type of found object is known, use that type
71365793Smsmith         * to see if it opens a scope.
71465793Smsmith         */
71565793Smsmith        if ((NumSegments == 0) && (Type == ACPI_TYPE_ANY))
71665793Smsmith        {
71765793Smsmith            Type = ThisNode->Type;
71865793Smsmith        }
71965793Smsmith
72083114Sscottl        /* Point to next name segment and make this node current */
72183114Sscottl
72283114Sscottl        Path += ACPI_NAME_SIZE;
72383114Sscottl        CurrentNode = ThisNode;
72483114Sscottl    }
72583114Sscottl
72665793Smsmith    /*
72765793Smsmith     * Always check if we need to open a new scope
72865793Smsmith     */
72965793Smsmith    if (!(Flags & ACPI_NS_DONT_OPEN_SCOPE) && (WalkState))
73065793Smsmith    {
73165793Smsmith        /*
73283114Sscottl         * If entry is a type which opens a scope, push the new scope on the
73383114Sscottl         * scope stack.
73483114Sscottl         */
73583114Sscottl        if (AcpiNsOpensScope (Type))
73683114Sscottl        {
73783114Sscottl            Status = AcpiDsScopeStackPush (ThisNode, Type, WalkState);
73865793Smsmith            if (ACPI_FAILURE (Status))
73965793Smsmith            {
74065793Smsmith                return_ACPI_STATUS (Status);
74165793Smsmith            }
74265793Smsmith        }
74365793Smsmith    }
74483114Sscottl
74583114Sscottl    *ReturnNode = ThisNode;
74683114Sscottl    return_ACPI_STATUS (AE_OK);
74783114Sscottl}
74883114Sscottl
749103870Salfred