195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /*******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
595b482a8SLen Brown *
695b482a8SLen Brown ******************************************************************************/
795b482a8SLen Brown
895b482a8SLen Brown #include <acpi/acpi.h>
9e2f7a777SLen Brown #include "accommon.h"
10e2f7a777SLen Brown #include "amlcode.h"
11e2f7a777SLen Brown #include "acnamesp.h"
12e2f7a777SLen Brown #include "acdispat.h"
1395b482a8SLen Brown
14a9d8ea79SErik Schmauss #ifdef ACPI_ASL_COMPILER
15a9d8ea79SErik Schmauss #include "acdisasm.h"
16a9d8ea79SErik Schmauss #endif
17a9d8ea79SErik Schmauss
1895b482a8SLen Brown #define _COMPONENT ACPI_NAMESPACE
1995b482a8SLen Brown ACPI_MODULE_NAME("nsaccess")
2095b482a8SLen Brown
2195b482a8SLen Brown /*******************************************************************************
2295b482a8SLen Brown *
2395b482a8SLen Brown * FUNCTION: acpi_ns_root_initialize
2495b482a8SLen Brown *
2595b482a8SLen Brown * PARAMETERS: None
2695b482a8SLen Brown *
2795b482a8SLen Brown * RETURN: Status
2895b482a8SLen Brown *
2995b482a8SLen Brown * DESCRIPTION: Allocate and initialize the default root named objects
3095b482a8SLen Brown *
3195b482a8SLen Brown * MUTEX: Locks namespace for entire execution
3295b482a8SLen Brown *
3395b482a8SLen Brown ******************************************************************************/
acpi_ns_root_initialize(void)3495b482a8SLen Brown acpi_status acpi_ns_root_initialize(void)
3595b482a8SLen Brown {
3695b482a8SLen Brown acpi_status status;
3795b482a8SLen Brown const struct acpi_predefined_names *init_val = NULL;
3895b482a8SLen Brown struct acpi_namespace_node *new_node;
39f79c8e41SBob Moore struct acpi_namespace_node *prev_node = NULL;
4095b482a8SLen Brown union acpi_operand_object *obj_desc;
4195b482a8SLen Brown acpi_string val = NULL;
4295b482a8SLen Brown
4395b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_root_initialize);
4495b482a8SLen Brown
4595b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
4695b482a8SLen Brown if (ACPI_FAILURE(status)) {
4795b482a8SLen Brown return_ACPI_STATUS(status);
4895b482a8SLen Brown }
4995b482a8SLen Brown
5095b482a8SLen Brown /*
5195b482a8SLen Brown * The global root ptr is initially NULL, so a non-NULL value indicates
5295b482a8SLen Brown * that acpi_ns_root_initialize() has already been called; just return.
5395b482a8SLen Brown */
5495b482a8SLen Brown if (acpi_gbl_root_node) {
5595b482a8SLen Brown status = AE_OK;
5695b482a8SLen Brown goto unlock_and_exit;
5795b482a8SLen Brown }
5895b482a8SLen Brown
5995b482a8SLen Brown /*
6095b482a8SLen Brown * Tell the rest of the subsystem that the root is initialized
6195b482a8SLen Brown * (This is OK because the namespace is locked)
6295b482a8SLen Brown */
6395b482a8SLen Brown acpi_gbl_root_node = &acpi_gbl_root_node_struct;
6495b482a8SLen Brown
65f79c8e41SBob Moore /* Enter the predefined names in the name table */
6695b482a8SLen Brown
6795b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO,
6895b482a8SLen Brown "Entering predefined entries into namespace\n"));
6995b482a8SLen Brown
70f79c8e41SBob Moore /*
71f79c8e41SBob Moore * Create the initial (default) namespace.
72f79c8e41SBob Moore * This namespace looks like something similar to this:
73f79c8e41SBob Moore *
74f79c8e41SBob Moore * ACPI Namespace (from Namespace Root):
75f79c8e41SBob Moore * 0 _GPE Scope 00203160 00
76f79c8e41SBob Moore * 0 _PR_ Scope 002031D0 00
77f79c8e41SBob Moore * 0 _SB_ Device 00203240 00 Notify Object: 0020ADD8
78f79c8e41SBob Moore * 0 _SI_ Scope 002032B0 00
79f79c8e41SBob Moore * 0 _TZ_ Device 00203320 00
80f79c8e41SBob Moore * 0 _REV Integer 00203390 00 = 0000000000000002
81f79c8e41SBob Moore * 0 _OS_ String 00203488 00 Len 14 "Microsoft Windows NT"
82f79c8e41SBob Moore * 0 _GL_ Mutex 00203580 00 Object 002035F0
83f79c8e41SBob Moore * 0 _OSI Method 00203678 00 Args 1 Len 0000 Aml 00000000
84f79c8e41SBob Moore */
8595b482a8SLen Brown for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
86f79c8e41SBob Moore status = AE_OK;
8795b482a8SLen Brown
8895b482a8SLen Brown /* _OSI is optional for now, will be permanent later */
8995b482a8SLen Brown
904fa4616eSBob Moore if (!strcmp(init_val->name, "_OSI")
9195b482a8SLen Brown && !acpi_gbl_create_osi_method) {
9295b482a8SLen Brown continue;
9395b482a8SLen Brown }
9495b482a8SLen Brown
95f79c8e41SBob Moore /*
96f79c8e41SBob Moore * Create, init, and link the new predefined name
97f79c8e41SBob Moore * Note: No need to use acpi_ns_lookup here because all the
98f79c8e41SBob Moore * predefined names are at the root level. It is much easier to
99f79c8e41SBob Moore * just create and link the new node(s) here.
100f79c8e41SBob Moore */
101f79c8e41SBob Moore new_node =
102*25928deeSVegard Nossum acpi_ns_create_node(*ACPI_CAST_PTR(u32, init_val->name));
103f79c8e41SBob Moore if (!new_node) {
104f79c8e41SBob Moore status = AE_NO_MEMORY;
105f79c8e41SBob Moore goto unlock_and_exit;
10695b482a8SLen Brown }
10795b482a8SLen Brown
108f79c8e41SBob Moore new_node->descriptor_type = ACPI_DESC_TYPE_NAMED;
109f79c8e41SBob Moore new_node->type = init_val->type;
110f79c8e41SBob Moore
111f79c8e41SBob Moore if (!prev_node) {
112f79c8e41SBob Moore acpi_gbl_root_node_struct.child = new_node;
113f79c8e41SBob Moore } else {
114f79c8e41SBob Moore prev_node->peer = new_node;
115f79c8e41SBob Moore }
116f79c8e41SBob Moore
117f79c8e41SBob Moore new_node->parent = &acpi_gbl_root_node_struct;
118f79c8e41SBob Moore prev_node = new_node;
119f79c8e41SBob Moore
12095b482a8SLen Brown /*
121d4913dc6SBob Moore * Name entered successfully. If entry in pre_defined_names[] specifies
122d4913dc6SBob Moore * an initial value, create the initial value.
12395b482a8SLen Brown */
12495b482a8SLen Brown if (init_val->val) {
12595b482a8SLen Brown status = acpi_os_predefined_override(init_val, &val);
12695b482a8SLen Brown if (ACPI_FAILURE(status)) {
12795b482a8SLen Brown ACPI_ERROR((AE_INFO,
12895b482a8SLen Brown "Could not override predefined %s",
12995b482a8SLen Brown init_val->name));
13095b482a8SLen Brown }
13195b482a8SLen Brown
13295b482a8SLen Brown if (!val) {
13395b482a8SLen Brown val = init_val->val;
13495b482a8SLen Brown }
13595b482a8SLen Brown
13695b482a8SLen Brown /*
13795b482a8SLen Brown * Entry requests an initial value, allocate a
13895b482a8SLen Brown * descriptor for it.
13995b482a8SLen Brown */
14095b482a8SLen Brown obj_desc =
14195b482a8SLen Brown acpi_ut_create_internal_object(init_val->type);
14295b482a8SLen Brown if (!obj_desc) {
14395b482a8SLen Brown status = AE_NO_MEMORY;
14495b482a8SLen Brown goto unlock_and_exit;
14595b482a8SLen Brown }
14695b482a8SLen Brown
14795b482a8SLen Brown /*
14895b482a8SLen Brown * Convert value string from table entry to
14995b482a8SLen Brown * internal representation. Only types actually
15095b482a8SLen Brown * used for initial values are implemented here.
15195b482a8SLen Brown */
15295b482a8SLen Brown switch (init_val->type) {
15395b482a8SLen Brown case ACPI_TYPE_METHOD:
1541d1ea1b7SChao Guan
15595b482a8SLen Brown obj_desc->method.param_count =
15695b482a8SLen Brown (u8) ACPI_TO_INTEGER(val);
15795b482a8SLen Brown obj_desc->common.flags |= AOPOBJ_DATA_VALID;
15895b482a8SLen Brown
15995b482a8SLen Brown #if defined (ACPI_ASL_COMPILER)
16095b482a8SLen Brown
161ba494beeSBob Moore /* Save the parameter count for the iASL compiler */
16295b482a8SLen Brown
16395b482a8SLen Brown new_node->value = obj_desc->method.param_count;
16495b482a8SLen Brown #else
165f79c8e41SBob Moore /* Mark this as a very SPECIAL method (_OSI) */
16695b482a8SLen Brown
16726294842SLin Ming obj_desc->method.info_flags =
16826294842SLin Ming ACPI_METHOD_INTERNAL_ONLY;
16926294842SLin Ming obj_desc->method.dispatch.implementation =
17095b482a8SLen Brown acpi_ut_osi_implementation;
17195b482a8SLen Brown #endif
17295b482a8SLen Brown break;
17395b482a8SLen Brown
17495b482a8SLen Brown case ACPI_TYPE_INTEGER:
17595b482a8SLen Brown
17695b482a8SLen Brown obj_desc->integer.value = ACPI_TO_INTEGER(val);
17795b482a8SLen Brown break;
17895b482a8SLen Brown
17995b482a8SLen Brown case ACPI_TYPE_STRING:
18095b482a8SLen Brown
181d4913dc6SBob Moore /* Build an object around the static string */
182d4913dc6SBob Moore
1834fa4616eSBob Moore obj_desc->string.length = (u32)strlen(val);
18495b482a8SLen Brown obj_desc->string.pointer = val;
18595b482a8SLen Brown obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
18695b482a8SLen Brown break;
18795b482a8SLen Brown
18895b482a8SLen Brown case ACPI_TYPE_MUTEX:
18995b482a8SLen Brown
19095b482a8SLen Brown obj_desc->mutex.node = new_node;
19195b482a8SLen Brown obj_desc->mutex.sync_level =
19295b482a8SLen Brown (u8) (ACPI_TO_INTEGER(val) - 1);
19395b482a8SLen Brown
19495b482a8SLen Brown /* Create a mutex */
19595b482a8SLen Brown
19695b482a8SLen Brown status =
19795b482a8SLen Brown acpi_os_create_mutex(&obj_desc->mutex.
19895b482a8SLen Brown os_mutex);
19995b482a8SLen Brown if (ACPI_FAILURE(status)) {
20095b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
20195b482a8SLen Brown goto unlock_and_exit;
20295b482a8SLen Brown }
20395b482a8SLen Brown
20495b482a8SLen Brown /* Special case for ACPI Global Lock */
20595b482a8SLen Brown
2064fa4616eSBob Moore if (strcmp(init_val->name, "_GL_") == 0) {
20795b482a8SLen Brown acpi_gbl_global_lock_mutex = obj_desc;
20895b482a8SLen Brown
20995b482a8SLen Brown /* Create additional counting semaphore for global lock */
21095b482a8SLen Brown
21195b482a8SLen Brown status =
21295b482a8SLen Brown acpi_os_create_semaphore(1, 0,
21395b482a8SLen Brown &acpi_gbl_global_lock_semaphore);
21495b482a8SLen Brown if (ACPI_FAILURE(status)) {
21595b482a8SLen Brown acpi_ut_remove_reference
21695b482a8SLen Brown (obj_desc);
21795b482a8SLen Brown goto unlock_and_exit;
21895b482a8SLen Brown }
21995b482a8SLen Brown }
22095b482a8SLen Brown break;
22195b482a8SLen Brown
22295b482a8SLen Brown default:
22395b482a8SLen Brown
22495b482a8SLen Brown ACPI_ERROR((AE_INFO,
225f6a22b0bSBob Moore "Unsupported initial type value 0x%X",
22695b482a8SLen Brown init_val->type));
22795b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
22895b482a8SLen Brown obj_desc = NULL;
22995b482a8SLen Brown continue;
23095b482a8SLen Brown }
23195b482a8SLen Brown
23295b482a8SLen Brown /* Store pointer to value descriptor in the Node */
23395b482a8SLen Brown
23495b482a8SLen Brown status = acpi_ns_attach_object(new_node, obj_desc,
2353371c19cSBob Moore obj_desc->common.type);
23695b482a8SLen Brown
23795b482a8SLen Brown /* Remove local reference to the object */
23895b482a8SLen Brown
23995b482a8SLen Brown acpi_ut_remove_reference(obj_desc);
24095b482a8SLen Brown }
24195b482a8SLen Brown }
24295b482a8SLen Brown
24395b482a8SLen Brown unlock_and_exit:
24495b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
24595b482a8SLen Brown
24695b482a8SLen Brown /* Save a handle to "_GPE", it is always present */
24795b482a8SLen Brown
24895b482a8SLen Brown if (ACPI_SUCCESS(status)) {
24995b482a8SLen Brown status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
25095b482a8SLen Brown &acpi_gbl_fadt_gpe_device);
25195b482a8SLen Brown }
25295b482a8SLen Brown
25395b482a8SLen Brown return_ACPI_STATUS(status);
25495b482a8SLen Brown }
25595b482a8SLen Brown
25695b482a8SLen Brown /*******************************************************************************
25795b482a8SLen Brown *
25895b482a8SLen Brown * FUNCTION: acpi_ns_lookup
25995b482a8SLen Brown *
26095b482a8SLen Brown * PARAMETERS: scope_info - Current scope info block
261ba494beeSBob Moore * pathname - Search pathname, in internal format
26295b482a8SLen Brown * (as represented in the AML stream)
263ba494beeSBob Moore * type - Type associated with name
26495b482a8SLen Brown * interpreter_mode - IMODE_LOAD_PASS2 => add name if not found
265ba494beeSBob Moore * flags - Flags describing the search restrictions
26695b482a8SLen Brown * walk_state - Current state of the walk
26795b482a8SLen Brown * return_node - Where the Node is placed (if found
26895b482a8SLen Brown * or created successfully)
26995b482a8SLen Brown *
27095b482a8SLen Brown * RETURN: Status
27195b482a8SLen Brown *
27295b482a8SLen Brown * DESCRIPTION: Find or enter the passed name in the name space.
27395b482a8SLen Brown * Log an error if name not found in Exec mode.
27495b482a8SLen Brown *
27595b482a8SLen Brown * MUTEX: Assumes namespace is locked.
27695b482a8SLen Brown *
27795b482a8SLen Brown ******************************************************************************/
27895b482a8SLen Brown
27995b482a8SLen Brown acpi_status
acpi_ns_lookup(union acpi_generic_state * scope_info,char * pathname,acpi_object_type type,acpi_interpreter_mode interpreter_mode,u32 flags,struct acpi_walk_state * walk_state,struct acpi_namespace_node ** return_node)28095b482a8SLen Brown acpi_ns_lookup(union acpi_generic_state *scope_info,
28195b482a8SLen Brown char *pathname,
28295b482a8SLen Brown acpi_object_type type,
28395b482a8SLen Brown acpi_interpreter_mode interpreter_mode,
28495b482a8SLen Brown u32 flags,
28595b482a8SLen Brown struct acpi_walk_state *walk_state,
28695b482a8SLen Brown struct acpi_namespace_node **return_node)
28795b482a8SLen Brown {
28895b482a8SLen Brown acpi_status status;
28995b482a8SLen Brown char *path = pathname;
2906d9229d6SBob Moore char *external_path;
29195b482a8SLen Brown struct acpi_namespace_node *prefix_node;
29295b482a8SLen Brown struct acpi_namespace_node *current_node = NULL;
29395b482a8SLen Brown struct acpi_namespace_node *this_node = NULL;
29495b482a8SLen Brown u32 num_segments;
29595b482a8SLen Brown u32 num_carats;
29695b482a8SLen Brown acpi_name simple_name;
29795b482a8SLen Brown acpi_object_type type_to_check_for;
29895b482a8SLen Brown acpi_object_type this_search_type;
29995b482a8SLen Brown u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
30095b482a8SLen Brown u32 local_flags;
301927a6abfSBob Moore acpi_interpreter_mode local_interpreter_mode;
30295b482a8SLen Brown
30395b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_lookup);
30495b482a8SLen Brown
30595b482a8SLen Brown if (!return_node) {
30695b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER);
30795b482a8SLen Brown }
30895b482a8SLen Brown
3098f6f0361SLv Zheng local_flags = flags &
3108f6f0361SLv Zheng ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND |
3118f6f0361SLv Zheng ACPI_NS_SEARCH_PARENT);
31295b482a8SLen Brown *return_node = ACPI_ENTRY_NOT_FOUND;
31395b482a8SLen Brown acpi_gbl_ns_lookup_count++;
31495b482a8SLen Brown
31595b482a8SLen Brown if (!acpi_gbl_root_node) {
31695b482a8SLen Brown return_ACPI_STATUS(AE_NO_NAMESPACE);
31795b482a8SLen Brown }
31895b482a8SLen Brown
319d4913dc6SBob Moore /* Get the prefix scope. A null scope means use the root scope */
320d4913dc6SBob Moore
32195b482a8SLen Brown if ((!scope_info) || (!scope_info->scope.node)) {
32295b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
32395b482a8SLen Brown "Null scope prefix, using root node (%p)\n",
32495b482a8SLen Brown acpi_gbl_root_node));
32595b482a8SLen Brown
32695b482a8SLen Brown prefix_node = acpi_gbl_root_node;
32795b482a8SLen Brown } else {
32895b482a8SLen Brown prefix_node = scope_info->scope.node;
32995b482a8SLen Brown if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) !=
33095b482a8SLen Brown ACPI_DESC_TYPE_NAMED) {
33195b482a8SLen Brown ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]",
33295b482a8SLen Brown prefix_node,
33395b482a8SLen Brown acpi_ut_get_descriptor_name(prefix_node)));
33495b482a8SLen Brown return_ACPI_STATUS(AE_AML_INTERNAL);
33595b482a8SLen Brown }
33695b482a8SLen Brown
33795b482a8SLen Brown if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) {
33895b482a8SLen Brown /*
33995b482a8SLen Brown * This node might not be a actual "scope" node (such as a
340d4913dc6SBob Moore * Device/Method, etc.) It could be a Package or other object
341d4913dc6SBob Moore * node. Backup up the tree to find the containing scope node.
34295b482a8SLen Brown */
34395b482a8SLen Brown while (!acpi_ns_opens_scope(prefix_node->type) &&
34495b482a8SLen Brown prefix_node->type != ACPI_TYPE_ANY) {
345c45b5c09SAlexey Starikovskiy prefix_node = prefix_node->parent;
34695b482a8SLen Brown }
34795b482a8SLen Brown }
34895b482a8SLen Brown }
34995b482a8SLen Brown
350d4913dc6SBob Moore /* Save type. TBD: may be no longer necessary */
35195b482a8SLen Brown
35295b482a8SLen Brown type_to_check_for = type;
35395b482a8SLen Brown
35495b482a8SLen Brown /*
35595b482a8SLen Brown * Begin examination of the actual pathname
35695b482a8SLen Brown */
35795b482a8SLen Brown if (!pathname) {
35895b482a8SLen Brown
35995b482a8SLen Brown /* A Null name_path is allowed and refers to the root */
36095b482a8SLen Brown
36195b482a8SLen Brown num_segments = 0;
36295b482a8SLen Brown this_node = acpi_gbl_root_node;
36395b482a8SLen Brown path = "";
36495b482a8SLen Brown
36595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
36695b482a8SLen Brown "Null Pathname (Zero segments), Flags=%X\n",
36795b482a8SLen Brown flags));
36895b482a8SLen Brown } else {
36995b482a8SLen Brown /*
37095b482a8SLen Brown * Name pointer is valid (and must be in internal name format)
37195b482a8SLen Brown *
37295b482a8SLen Brown * Check for scope prefixes:
37395b482a8SLen Brown *
37495b482a8SLen Brown * As represented in the AML stream, a namepath consists of an
37595b482a8SLen Brown * optional scope prefix followed by a name segment part.
37695b482a8SLen Brown *
37795b482a8SLen Brown * If present, the scope prefix is either a Root Prefix (in
37895b482a8SLen Brown * which case the name is fully qualified), or one or more
37995b482a8SLen Brown * Parent Prefixes (in which case the name's scope is relative
38095b482a8SLen Brown * to the current scope).
38195b482a8SLen Brown */
38295b482a8SLen Brown if (*path == (u8) AML_ROOT_PREFIX) {
38395b482a8SLen Brown
38495b482a8SLen Brown /* Pathname is fully qualified, start from the root */
38595b482a8SLen Brown
38695b482a8SLen Brown this_node = acpi_gbl_root_node;
38795b482a8SLen Brown search_parent_flag = ACPI_NS_NO_UPSEARCH;
38895b482a8SLen Brown
38995b482a8SLen Brown /* Point to name segment part */
39095b482a8SLen Brown
39195b482a8SLen Brown path++;
39295b482a8SLen Brown
39395b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
39495b482a8SLen Brown "Path is absolute from root [%p]\n",
39595b482a8SLen Brown this_node));
39695b482a8SLen Brown } else {
39795b482a8SLen Brown /* Pathname is relative to current scope, start there */
39895b482a8SLen Brown
39995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
40095b482a8SLen Brown "Searching relative to prefix scope [%4.4s] (%p)\n",
40195b482a8SLen Brown acpi_ut_get_node_name(prefix_node),
40295b482a8SLen Brown prefix_node));
40395b482a8SLen Brown
40495b482a8SLen Brown /*
40595b482a8SLen Brown * Handle multiple Parent Prefixes (carat) by just getting
40695b482a8SLen Brown * the parent node for each prefix instance.
40795b482a8SLen Brown */
40895b482a8SLen Brown this_node = prefix_node;
40995b482a8SLen Brown num_carats = 0;
41095b482a8SLen Brown while (*path == (u8) AML_PARENT_PREFIX) {
41195b482a8SLen Brown
41295b482a8SLen Brown /* Name is fully qualified, no search rules apply */
41395b482a8SLen Brown
41495b482a8SLen Brown search_parent_flag = ACPI_NS_NO_UPSEARCH;
415d4913dc6SBob Moore
41695b482a8SLen Brown /*
41795b482a8SLen Brown * Point past this prefix to the name segment
41895b482a8SLen Brown * part or the next Parent Prefix
41995b482a8SLen Brown */
42095b482a8SLen Brown path++;
42195b482a8SLen Brown
42295b482a8SLen Brown /* Backup to the parent node */
42395b482a8SLen Brown
42495b482a8SLen Brown num_carats++;
425c45b5c09SAlexey Starikovskiy this_node = this_node->parent;
42695b482a8SLen Brown if (!this_node) {
4276d9229d6SBob Moore /*
4286d9229d6SBob Moore * Current scope has no parent scope. Externalize
4296d9229d6SBob Moore * the internal path for error message.
4306d9229d6SBob Moore */
4316d9229d6SBob Moore status =
4326d9229d6SBob Moore acpi_ns_externalize_name
4336d9229d6SBob Moore (ACPI_UINT32_MAX, pathname, NULL,
4346d9229d6SBob Moore &external_path);
4356d9229d6SBob Moore if (ACPI_SUCCESS(status)) {
43695b482a8SLen Brown ACPI_ERROR((AE_INFO,
4376d9229d6SBob Moore "%s: Path has too many parent prefixes (^)",
4386d9229d6SBob Moore external_path));
4396d9229d6SBob Moore
4406d9229d6SBob Moore ACPI_FREE(external_path);
4416d9229d6SBob Moore }
4426d9229d6SBob Moore
44395b482a8SLen Brown return_ACPI_STATUS(AE_NOT_FOUND);
44495b482a8SLen Brown }
44595b482a8SLen Brown }
44695b482a8SLen Brown
44795b482a8SLen Brown if (search_parent_flag == ACPI_NS_NO_UPSEARCH) {
44895b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
449b27d6597SBob Moore "Search scope is [%4.4s], path has %u carat(s)\n",
45095b482a8SLen Brown acpi_ut_get_node_name
45195b482a8SLen Brown (this_node), num_carats));
45295b482a8SLen Brown }
45395b482a8SLen Brown }
45495b482a8SLen Brown
45595b482a8SLen Brown /*
45695b482a8SLen Brown * Determine the number of ACPI name segments in this pathname.
45795b482a8SLen Brown *
45895b482a8SLen Brown * The segment part consists of either:
45995b482a8SLen Brown * - A Null name segment (0)
46095b482a8SLen Brown * - A dual_name_prefix followed by two 4-byte name segments
46195b482a8SLen Brown * - A multi_name_prefix followed by a byte indicating the
46295b482a8SLen Brown * number of segments and the segments themselves.
46395b482a8SLen Brown * - A single 4-byte name segment
46495b482a8SLen Brown *
46595b482a8SLen Brown * Examine the name prefix opcode, if any, to determine the number of
46695b482a8SLen Brown * segments.
46795b482a8SLen Brown */
46895b482a8SLen Brown switch (*path) {
46995b482a8SLen Brown case 0:
47095b482a8SLen Brown /*
47195b482a8SLen Brown * Null name after a root or parent prefixes. We already
47295b482a8SLen Brown * have the correct target node and there are no name segments.
47395b482a8SLen Brown */
47495b482a8SLen Brown num_segments = 0;
47595b482a8SLen Brown type = this_node->type;
47695b482a8SLen Brown
47795b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
47895b482a8SLen Brown "Prefix-only Pathname (Zero name segments), Flags=%X\n",
47995b482a8SLen Brown flags));
48095b482a8SLen Brown break;
48195b482a8SLen Brown
48295b482a8SLen Brown case AML_DUAL_NAME_PREFIX:
48395b482a8SLen Brown
48495b482a8SLen Brown /* More than one name_seg, search rules do not apply */
48595b482a8SLen Brown
48695b482a8SLen Brown search_parent_flag = ACPI_NS_NO_UPSEARCH;
48795b482a8SLen Brown
48895b482a8SLen Brown /* Two segments, point to first name segment */
48995b482a8SLen Brown
49095b482a8SLen Brown num_segments = 2;
49195b482a8SLen Brown path++;
49295b482a8SLen Brown
49395b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
49495b482a8SLen Brown "Dual Pathname (2 segments, Flags=%X)\n",
49595b482a8SLen Brown flags));
49695b482a8SLen Brown break;
49795b482a8SLen Brown
4989ff5a21aSBob Moore case AML_MULTI_NAME_PREFIX:
49995b482a8SLen Brown
50095b482a8SLen Brown /* More than one name_seg, search rules do not apply */
50195b482a8SLen Brown
50295b482a8SLen Brown search_parent_flag = ACPI_NS_NO_UPSEARCH;
50395b482a8SLen Brown
50495b482a8SLen Brown /* Extract segment count, point to first name segment */
50595b482a8SLen Brown
50695b482a8SLen Brown path++;
50795b482a8SLen Brown num_segments = (u32) (u8) * path;
50895b482a8SLen Brown path++;
50995b482a8SLen Brown
51095b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
511b27d6597SBob Moore "Multi Pathname (%u Segments, Flags=%X)\n",
51295b482a8SLen Brown num_segments, flags));
51395b482a8SLen Brown break;
51495b482a8SLen Brown
51595b482a8SLen Brown default:
51695b482a8SLen Brown /*
51795b482a8SLen Brown * Not a Null name, no Dual or Multi prefix, hence there is
51895b482a8SLen Brown * only one name segment and Pathname is already pointing to it.
51995b482a8SLen Brown */
52095b482a8SLen Brown num_segments = 1;
52195b482a8SLen Brown
52295b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
52395b482a8SLen Brown "Simple Pathname (1 segment, Flags=%X)\n",
52495b482a8SLen Brown flags));
52595b482a8SLen Brown break;
52695b482a8SLen Brown }
52795b482a8SLen Brown
52895b482a8SLen Brown ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path));
52995b482a8SLen Brown }
53095b482a8SLen Brown
53195b482a8SLen Brown /*
53295b482a8SLen Brown * Search namespace for each segment of the name. Loop through and
53395b482a8SLen Brown * verify (or add to the namespace) each name segment.
53495b482a8SLen Brown *
53595b482a8SLen Brown * The object type is significant only at the last name
53695b482a8SLen Brown * segment. (We don't care about the types along the path, only
53795b482a8SLen Brown * the type of the final target object.)
53895b482a8SLen Brown */
53995b482a8SLen Brown this_search_type = ACPI_TYPE_ANY;
54095b482a8SLen Brown current_node = this_node;
541927a6abfSBob Moore
54295b482a8SLen Brown while (num_segments && current_node) {
54395b482a8SLen Brown num_segments--;
54495b482a8SLen Brown if (!num_segments) {
545d4913dc6SBob Moore
546d4913dc6SBob Moore /* This is the last segment, enable typechecking */
547d4913dc6SBob Moore
54895b482a8SLen Brown this_search_type = type;
54995b482a8SLen Brown
55095b482a8SLen Brown /*
55195b482a8SLen Brown * Only allow automatic parent search (search rules) if the caller
55295b482a8SLen Brown * requested it AND we have a single, non-fully-qualified name_seg
55395b482a8SLen Brown */
55495b482a8SLen Brown if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) &&
55595b482a8SLen Brown (flags & ACPI_NS_SEARCH_PARENT)) {
55695b482a8SLen Brown local_flags |= ACPI_NS_SEARCH_PARENT;
55795b482a8SLen Brown }
55895b482a8SLen Brown
55995b482a8SLen Brown /* Set error flag according to caller */
56095b482a8SLen Brown
56195b482a8SLen Brown if (flags & ACPI_NS_ERROR_IF_FOUND) {
56295b482a8SLen Brown local_flags |= ACPI_NS_ERROR_IF_FOUND;
56395b482a8SLen Brown }
5648f6f0361SLv Zheng
5658f6f0361SLv Zheng /* Set override flag according to caller */
5668f6f0361SLv Zheng
5678f6f0361SLv Zheng if (flags & ACPI_NS_OVERRIDE_IF_FOUND) {
5688f6f0361SLv Zheng local_flags |= ACPI_NS_OVERRIDE_IF_FOUND;
5698f6f0361SLv Zheng }
57095b482a8SLen Brown }
57195b482a8SLen Brown
572927a6abfSBob Moore /* Handle opcodes that create a new name_seg via a full name_path */
573927a6abfSBob Moore
574927a6abfSBob Moore local_interpreter_mode = interpreter_mode;
575927a6abfSBob Moore if ((flags & ACPI_NS_PREFIX_MUST_EXIST) && (num_segments > 0)) {
576927a6abfSBob Moore
577927a6abfSBob Moore /* Every element of the path must exist (except for the final name_seg) */
578927a6abfSBob Moore
579927a6abfSBob Moore local_interpreter_mode = ACPI_IMODE_EXECUTE;
580927a6abfSBob Moore }
581927a6abfSBob Moore
58295b482a8SLen Brown /* Extract one ACPI name from the front of the pathname */
58395b482a8SLen Brown
58495b482a8SLen Brown ACPI_MOVE_32_TO_32(&simple_name, path);
58595b482a8SLen Brown
58695b482a8SLen Brown /* Try to find the single (4 character) ACPI name */
58795b482a8SLen Brown
58895b482a8SLen Brown status =
58995b482a8SLen Brown acpi_ns_search_and_enter(simple_name, walk_state,
590927a6abfSBob Moore current_node,
591927a6abfSBob Moore local_interpreter_mode,
59295b482a8SLen Brown this_search_type, local_flags,
59395b482a8SLen Brown &this_node);
59495b482a8SLen Brown if (ACPI_FAILURE(status)) {
59595b482a8SLen Brown if (status == AE_NOT_FOUND) {
596927a6abfSBob Moore #if !defined ACPI_ASL_COMPILER /* Note: iASL reports this error by itself, not needed here */
597927a6abfSBob Moore if (flags & ACPI_NS_PREFIX_MUST_EXIST) {
598927a6abfSBob Moore acpi_os_printf(ACPI_MSG_BIOS_ERROR
599927a6abfSBob Moore "Object does not exist: %4.4s\n",
60036056d0cSBob Moore (char *)&simple_name);
601927a6abfSBob Moore }
602927a6abfSBob Moore #endif
60395b482a8SLen Brown /* Name not found in ACPI namespace */
60495b482a8SLen Brown
60595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
60695b482a8SLen Brown "Name [%4.4s] not found in scope [%4.4s] %p\n",
60795b482a8SLen Brown (char *)&simple_name,
60895b482a8SLen Brown (char *)¤t_node->name,
60995b482a8SLen Brown current_node));
61095b482a8SLen Brown }
61177d4e096SErik Schmauss #ifdef ACPI_EXEC_APP
61277d4e096SErik Schmauss if ((status == AE_ALREADY_EXISTS) &&
61377d4e096SErik Schmauss (this_node->flags & ANOBJ_NODE_EARLY_INIT)) {
61477d4e096SErik Schmauss this_node->flags &= ~ANOBJ_NODE_EARLY_INIT;
61577d4e096SErik Schmauss status = AE_OK;
61677d4e096SErik Schmauss }
61777d4e096SErik Schmauss #endif
61877d4e096SErik Schmauss
619a9d8ea79SErik Schmauss #ifdef ACPI_ASL_COMPILER
620a9d8ea79SErik Schmauss /*
621a9d8ea79SErik Schmauss * If this ACPI name already exists within the namespace as an
622a9d8ea79SErik Schmauss * external declaration, then mark the external as a conflicting
623a9d8ea79SErik Schmauss * declaration and proceed to process the current node as if it did
624a9d8ea79SErik Schmauss * not exist in the namespace. If this node is not processed as
625a9d8ea79SErik Schmauss * normal, then it could cause improper namespace resolution
626a9d8ea79SErik Schmauss * by failing to open a new scope.
627a9d8ea79SErik Schmauss */
628a9d8ea79SErik Schmauss if (acpi_gbl_disasm_flag &&
629a9d8ea79SErik Schmauss (status == AE_ALREADY_EXISTS) &&
630a9d8ea79SErik Schmauss ((this_node->flags & ANOBJ_IS_EXTERNAL) ||
631a9d8ea79SErik Schmauss (walk_state
632a9d8ea79SErik Schmauss && walk_state->opcode == AML_EXTERNAL_OP))) {
633a9d8ea79SErik Schmauss this_node->flags &= ~ANOBJ_IS_EXTERNAL;
634a9d8ea79SErik Schmauss this_node->type = (u8)this_search_type;
635a9d8ea79SErik Schmauss if (walk_state->opcode != AML_EXTERNAL_OP) {
636a9d8ea79SErik Schmauss acpi_dm_mark_external_conflict
637a9d8ea79SErik Schmauss (this_node);
638a9d8ea79SErik Schmauss }
639a9d8ea79SErik Schmauss break;
640a9d8ea79SErik Schmauss }
641a9d8ea79SErik Schmauss #endif
64295b482a8SLen Brown
64395b482a8SLen Brown *return_node = this_node;
64495b482a8SLen Brown return_ACPI_STATUS(status);
64595b482a8SLen Brown }
64695b482a8SLen Brown
64795b482a8SLen Brown /* More segments to follow? */
64895b482a8SLen Brown
64995b482a8SLen Brown if (num_segments > 0) {
65095b482a8SLen Brown /*
65195b482a8SLen Brown * If we have an alias to an object that opens a scope (such as a
652d4913dc6SBob Moore * device or processor), we need to dereference the alias here so
653d4913dc6SBob Moore * that we can access any children of the original node (via the
654d4913dc6SBob Moore * remaining segments).
65595b482a8SLen Brown */
65695b482a8SLen Brown if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) {
65795b482a8SLen Brown if (!this_node->object) {
65895b482a8SLen Brown return_ACPI_STATUS(AE_NOT_EXIST);
65995b482a8SLen Brown }
66095b482a8SLen Brown
66195b482a8SLen Brown if (acpi_ns_opens_scope
662d4913dc6SBob Moore (((struct acpi_namespace_node *)
663d4913dc6SBob Moore this_node->object)->type)) {
66495b482a8SLen Brown this_node =
66595b482a8SLen Brown (struct acpi_namespace_node *)
66695b482a8SLen Brown this_node->object;
66795b482a8SLen Brown }
66895b482a8SLen Brown }
66995b482a8SLen Brown }
67095b482a8SLen Brown
67195b482a8SLen Brown /* Special handling for the last segment (num_segments == 0) */
67295b482a8SLen Brown
67395b482a8SLen Brown else {
67495b482a8SLen Brown /*
67595b482a8SLen Brown * Sanity typecheck of the target object:
67695b482a8SLen Brown *
67795b482a8SLen Brown * If 1) This is the last segment (num_segments == 0)
67895b482a8SLen Brown * 2) And we are looking for a specific type
67995b482a8SLen Brown * (Not checking for TYPE_ANY)
68095b482a8SLen Brown * 3) Which is not an alias
68195b482a8SLen Brown * 4) Which is not a local type (TYPE_SCOPE)
68295b482a8SLen Brown * 5) And the type of target object is known (not TYPE_ANY)
68395b482a8SLen Brown * 6) And target object does not match what we are looking for
68495b482a8SLen Brown *
68595b482a8SLen Brown * Then we have a type mismatch. Just warn and ignore it.
68695b482a8SLen Brown */
68795b482a8SLen Brown if ((type_to_check_for != ACPI_TYPE_ANY) &&
68895b482a8SLen Brown (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
68995b482a8SLen Brown (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS)
69095b482a8SLen Brown && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE)
69195b482a8SLen Brown && (this_node->type != ACPI_TYPE_ANY)
69295b482a8SLen Brown && (this_node->type != type_to_check_for)) {
69395b482a8SLen Brown
69495b482a8SLen Brown /* Complain about a type mismatch */
69595b482a8SLen Brown
69695b482a8SLen Brown ACPI_WARNING((AE_INFO,
69795b482a8SLen Brown "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
69895b482a8SLen Brown ACPI_CAST_PTR(char, &simple_name),
69995b482a8SLen Brown acpi_ut_get_type_name(this_node->
70095b482a8SLen Brown type),
70195b482a8SLen Brown acpi_ut_get_type_name
70295b482a8SLen Brown (type_to_check_for)));
70395b482a8SLen Brown }
70495b482a8SLen Brown
70595b482a8SLen Brown /*
70695b482a8SLen Brown * If this is the last name segment and we are not looking for a
707d4913dc6SBob Moore * specific type, but the type of found object is known, use that
708d4913dc6SBob Moore * type to (later) see if it opens a scope.
70995b482a8SLen Brown */
71095b482a8SLen Brown if (type == ACPI_TYPE_ANY) {
71195b482a8SLen Brown type = this_node->type;
71295b482a8SLen Brown }
71395b482a8SLen Brown }
71495b482a8SLen Brown
71595b482a8SLen Brown /* Point to next name segment and make this node current */
71695b482a8SLen Brown
71732786755SBob Moore path += ACPI_NAMESEG_SIZE;
71895b482a8SLen Brown current_node = this_node;
71995b482a8SLen Brown }
72095b482a8SLen Brown
721d4913dc6SBob Moore /* Always check if we need to open a new scope */
722d4913dc6SBob Moore
72395b482a8SLen Brown if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) {
72495b482a8SLen Brown /*
72595b482a8SLen Brown * If entry is a type which opens a scope, push the new scope on the
72695b482a8SLen Brown * scope stack.
72795b482a8SLen Brown */
72895b482a8SLen Brown if (acpi_ns_opens_scope(type)) {
72995b482a8SLen Brown status =
73095b482a8SLen Brown acpi_ds_scope_stack_push(this_node, type,
73195b482a8SLen Brown walk_state);
73295b482a8SLen Brown if (ACPI_FAILURE(status)) {
73395b482a8SLen Brown return_ACPI_STATUS(status);
73495b482a8SLen Brown }
73595b482a8SLen Brown }
73695b482a8SLen Brown }
73777d4e096SErik Schmauss #ifdef ACPI_EXEC_APP
73877d4e096SErik Schmauss if (flags & ACPI_NS_EARLY_INIT) {
73977d4e096SErik Schmauss this_node->flags |= ANOBJ_NODE_EARLY_INIT;
74077d4e096SErik Schmauss }
74177d4e096SErik Schmauss #endif
74295b482a8SLen Brown
74395b482a8SLen Brown *return_node = this_node;
74495b482a8SLen Brown return_ACPI_STATUS(AE_OK);
74595b482a8SLen Brown }
746