1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /******************************************************************************* |
3 | * |
4 | * Module Name: nsaccess - Top-level functions for accessing ACPI namespace |
5 | * |
6 | ******************************************************************************/ |
7 | |
8 | #include <acpi/acpi.h> |
9 | #include "accommon.h" |
10 | #include "amlcode.h" |
11 | #include "acnamesp.h" |
12 | #include "acdispat.h" |
13 | |
14 | #ifdef ACPI_ASL_COMPILER |
15 | #include "acdisasm.h" |
16 | #endif |
17 | |
18 | #define _COMPONENT ACPI_NAMESPACE |
19 | ACPI_MODULE_NAME("nsaccess" ) |
20 | |
21 | /******************************************************************************* |
22 | * |
23 | * FUNCTION: acpi_ns_root_initialize |
24 | * |
25 | * PARAMETERS: None |
26 | * |
27 | * RETURN: Status |
28 | * |
29 | * DESCRIPTION: Allocate and initialize the default root named objects |
30 | * |
31 | * MUTEX: Locks namespace for entire execution |
32 | * |
33 | ******************************************************************************/ |
34 | acpi_status acpi_ns_root_initialize(void) |
35 | { |
36 | acpi_status status; |
37 | const struct acpi_predefined_names *init_val = NULL; |
38 | struct acpi_namespace_node *new_node; |
39 | struct acpi_namespace_node *prev_node = NULL; |
40 | union acpi_operand_object *obj_desc; |
41 | acpi_string val = NULL; |
42 | |
43 | ACPI_FUNCTION_TRACE(ns_root_initialize); |
44 | |
45 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
46 | if (ACPI_FAILURE(status)) { |
47 | return_ACPI_STATUS(status); |
48 | } |
49 | |
50 | /* |
51 | * The global root ptr is initially NULL, so a non-NULL value indicates |
52 | * that acpi_ns_root_initialize() has already been called; just return. |
53 | */ |
54 | if (acpi_gbl_root_node) { |
55 | status = AE_OK; |
56 | goto unlock_and_exit; |
57 | } |
58 | |
59 | /* |
60 | * Tell the rest of the subsystem that the root is initialized |
61 | * (This is OK because the namespace is locked) |
62 | */ |
63 | acpi_gbl_root_node = &acpi_gbl_root_node_struct; |
64 | |
65 | /* Enter the predefined names in the name table */ |
66 | |
67 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
68 | "Entering predefined entries into namespace\n" )); |
69 | |
70 | /* |
71 | * Create the initial (default) namespace. |
72 | * This namespace looks like something similar to this: |
73 | * |
74 | * ACPI Namespace (from Namespace Root): |
75 | * 0 _GPE Scope 00203160 00 |
76 | * 0 _PR_ Scope 002031D0 00 |
77 | * 0 _SB_ Device 00203240 00 Notify Object: 0020ADD8 |
78 | * 0 _SI_ Scope 002032B0 00 |
79 | * 0 _TZ_ Device 00203320 00 |
80 | * 0 _REV Integer 00203390 00 = 0000000000000002 |
81 | * 0 _OS_ String 00203488 00 Len 14 "Microsoft Windows NT" |
82 | * 0 _GL_ Mutex 00203580 00 Object 002035F0 |
83 | * 0 _OSI Method 00203678 00 Args 1 Len 0000 Aml 00000000 |
84 | */ |
85 | for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { |
86 | status = AE_OK; |
87 | |
88 | /* _OSI is optional for now, will be permanent later */ |
89 | |
90 | if (!strcmp(init_val->name, "_OSI" ) |
91 | && !acpi_gbl_create_osi_method) { |
92 | continue; |
93 | } |
94 | |
95 | /* |
96 | * Create, init, and link the new predefined name |
97 | * Note: No need to use acpi_ns_lookup here because all the |
98 | * predefined names are at the root level. It is much easier to |
99 | * just create and link the new node(s) here. |
100 | */ |
101 | new_node = |
102 | acpi_ns_create_node(name: *ACPI_CAST_PTR(u32, init_val->name)); |
103 | if (!new_node) { |
104 | status = AE_NO_MEMORY; |
105 | goto unlock_and_exit; |
106 | } |
107 | |
108 | new_node->descriptor_type = ACPI_DESC_TYPE_NAMED; |
109 | new_node->type = init_val->type; |
110 | |
111 | if (!prev_node) { |
112 | acpi_gbl_root_node_struct.child = new_node; |
113 | } else { |
114 | prev_node->peer = new_node; |
115 | } |
116 | |
117 | new_node->parent = &acpi_gbl_root_node_struct; |
118 | prev_node = new_node; |
119 | |
120 | /* |
121 | * Name entered successfully. If entry in pre_defined_names[] specifies |
122 | * an initial value, create the initial value. |
123 | */ |
124 | if (init_val->val) { |
125 | status = acpi_os_predefined_override(init_val, new_val: &val); |
126 | if (ACPI_FAILURE(status)) { |
127 | ACPI_ERROR((AE_INFO, |
128 | "Could not override predefined %s" , |
129 | init_val->name)); |
130 | } |
131 | |
132 | if (!val) { |
133 | val = init_val->val; |
134 | } |
135 | |
136 | /* |
137 | * Entry requests an initial value, allocate a |
138 | * descriptor for it. |
139 | */ |
140 | obj_desc = |
141 | acpi_ut_create_internal_object(init_val->type); |
142 | if (!obj_desc) { |
143 | status = AE_NO_MEMORY; |
144 | goto unlock_and_exit; |
145 | } |
146 | |
147 | /* |
148 | * Convert value string from table entry to |
149 | * internal representation. Only types actually |
150 | * used for initial values are implemented here. |
151 | */ |
152 | switch (init_val->type) { |
153 | case ACPI_TYPE_METHOD: |
154 | |
155 | obj_desc->method.param_count = |
156 | (u8) ACPI_TO_INTEGER(val); |
157 | obj_desc->common.flags |= AOPOBJ_DATA_VALID; |
158 | |
159 | #if defined (ACPI_ASL_COMPILER) |
160 | |
161 | /* Save the parameter count for the iASL compiler */ |
162 | |
163 | new_node->value = obj_desc->method.param_count; |
164 | #else |
165 | /* Mark this as a very SPECIAL method (_OSI) */ |
166 | |
167 | obj_desc->method.info_flags = |
168 | ACPI_METHOD_INTERNAL_ONLY; |
169 | obj_desc->method.dispatch.implementation = |
170 | acpi_ut_osi_implementation; |
171 | #endif |
172 | break; |
173 | |
174 | case ACPI_TYPE_INTEGER: |
175 | |
176 | obj_desc->integer.value = ACPI_TO_INTEGER(val); |
177 | break; |
178 | |
179 | case ACPI_TYPE_STRING: |
180 | |
181 | /* Build an object around the static string */ |
182 | |
183 | obj_desc->string.length = (u32)strlen(val); |
184 | obj_desc->string.pointer = val; |
185 | obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; |
186 | break; |
187 | |
188 | case ACPI_TYPE_MUTEX: |
189 | |
190 | obj_desc->mutex.node = new_node; |
191 | obj_desc->mutex.sync_level = |
192 | (u8) (ACPI_TO_INTEGER(val) - 1); |
193 | |
194 | /* Create a mutex */ |
195 | |
196 | status = |
197 | acpi_os_create_mutex(&obj_desc->mutex. |
198 | os_mutex); |
199 | if (ACPI_FAILURE(status)) { |
200 | acpi_ut_remove_reference(object: obj_desc); |
201 | goto unlock_and_exit; |
202 | } |
203 | |
204 | /* Special case for ACPI Global Lock */ |
205 | |
206 | if (strcmp(init_val->name, "_GL_" ) == 0) { |
207 | acpi_gbl_global_lock_mutex = obj_desc; |
208 | |
209 | /* Create additional counting semaphore for global lock */ |
210 | |
211 | status = |
212 | acpi_os_create_semaphore(max_units: 1, initial_units: 0, |
213 | out_handle: &acpi_gbl_global_lock_semaphore); |
214 | if (ACPI_FAILURE(status)) { |
215 | acpi_ut_remove_reference |
216 | (object: obj_desc); |
217 | goto unlock_and_exit; |
218 | } |
219 | } |
220 | break; |
221 | |
222 | default: |
223 | |
224 | ACPI_ERROR((AE_INFO, |
225 | "Unsupported initial type value 0x%X" , |
226 | init_val->type)); |
227 | acpi_ut_remove_reference(object: obj_desc); |
228 | obj_desc = NULL; |
229 | continue; |
230 | } |
231 | |
232 | /* Store pointer to value descriptor in the Node */ |
233 | |
234 | status = acpi_ns_attach_object(node: new_node, object: obj_desc, |
235 | type: obj_desc->common.type); |
236 | |
237 | /* Remove local reference to the object */ |
238 | |
239 | acpi_ut_remove_reference(object: obj_desc); |
240 | } |
241 | } |
242 | |
243 | unlock_and_exit: |
244 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
245 | |
246 | /* Save a handle to "_GPE", it is always present */ |
247 | |
248 | if (ACPI_SUCCESS(status)) { |
249 | status = acpi_ns_get_node(NULL, external_pathname: "\\_GPE" , ACPI_NS_NO_UPSEARCH, |
250 | out_node: &acpi_gbl_fadt_gpe_device); |
251 | } |
252 | |
253 | return_ACPI_STATUS(status); |
254 | } |
255 | |
256 | /******************************************************************************* |
257 | * |
258 | * FUNCTION: acpi_ns_lookup |
259 | * |
260 | * PARAMETERS: scope_info - Current scope info block |
261 | * pathname - Search pathname, in internal format |
262 | * (as represented in the AML stream) |
263 | * type - Type associated with name |
264 | * interpreter_mode - IMODE_LOAD_PASS2 => add name if not found |
265 | * flags - Flags describing the search restrictions |
266 | * walk_state - Current state of the walk |
267 | * return_node - Where the Node is placed (if found |
268 | * or created successfully) |
269 | * |
270 | * RETURN: Status |
271 | * |
272 | * DESCRIPTION: Find or enter the passed name in the name space. |
273 | * Log an error if name not found in Exec mode. |
274 | * |
275 | * MUTEX: Assumes namespace is locked. |
276 | * |
277 | ******************************************************************************/ |
278 | |
279 | acpi_status |
280 | acpi_ns_lookup(union acpi_generic_state *scope_info, |
281 | char *pathname, |
282 | acpi_object_type type, |
283 | acpi_interpreter_mode interpreter_mode, |
284 | u32 flags, |
285 | struct acpi_walk_state *walk_state, |
286 | struct acpi_namespace_node **return_node) |
287 | { |
288 | acpi_status status; |
289 | char *path = pathname; |
290 | char *external_path; |
291 | struct acpi_namespace_node *prefix_node; |
292 | struct acpi_namespace_node *current_node = NULL; |
293 | struct acpi_namespace_node *this_node = NULL; |
294 | u32 num_segments; |
295 | u32 num_carats; |
296 | acpi_name simple_name; |
297 | acpi_object_type type_to_check_for; |
298 | acpi_object_type this_search_type; |
299 | u32 search_parent_flag = ACPI_NS_SEARCH_PARENT; |
300 | u32 local_flags; |
301 | acpi_interpreter_mode local_interpreter_mode; |
302 | |
303 | ACPI_FUNCTION_TRACE(ns_lookup); |
304 | |
305 | if (!return_node) { |
306 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
307 | } |
308 | |
309 | local_flags = flags & |
310 | ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND | |
311 | ACPI_NS_SEARCH_PARENT); |
312 | *return_node = ACPI_ENTRY_NOT_FOUND; |
313 | acpi_gbl_ns_lookup_count++; |
314 | |
315 | if (!acpi_gbl_root_node) { |
316 | return_ACPI_STATUS(AE_NO_NAMESPACE); |
317 | } |
318 | |
319 | /* Get the prefix scope. A null scope means use the root scope */ |
320 | |
321 | if ((!scope_info) || (!scope_info->scope.node)) { |
322 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
323 | "Null scope prefix, using root node (%p)\n" , |
324 | acpi_gbl_root_node)); |
325 | |
326 | prefix_node = acpi_gbl_root_node; |
327 | } else { |
328 | prefix_node = scope_info->scope.node; |
329 | if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) != |
330 | ACPI_DESC_TYPE_NAMED) { |
331 | ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]" , |
332 | prefix_node, |
333 | acpi_ut_get_descriptor_name(prefix_node))); |
334 | return_ACPI_STATUS(AE_AML_INTERNAL); |
335 | } |
336 | |
337 | if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { |
338 | /* |
339 | * This node might not be a actual "scope" node (such as a |
340 | * Device/Method, etc.) It could be a Package or other object |
341 | * node. Backup up the tree to find the containing scope node. |
342 | */ |
343 | while (!acpi_ns_opens_scope(type: prefix_node->type) && |
344 | prefix_node->type != ACPI_TYPE_ANY) { |
345 | prefix_node = prefix_node->parent; |
346 | } |
347 | } |
348 | } |
349 | |
350 | /* Save type. TBD: may be no longer necessary */ |
351 | |
352 | type_to_check_for = type; |
353 | |
354 | /* |
355 | * Begin examination of the actual pathname |
356 | */ |
357 | if (!pathname) { |
358 | |
359 | /* A Null name_path is allowed and refers to the root */ |
360 | |
361 | num_segments = 0; |
362 | this_node = acpi_gbl_root_node; |
363 | path = "" ; |
364 | |
365 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
366 | "Null Pathname (Zero segments), Flags=%X\n" , |
367 | flags)); |
368 | } else { |
369 | /* |
370 | * Name pointer is valid (and must be in internal name format) |
371 | * |
372 | * Check for scope prefixes: |
373 | * |
374 | * As represented in the AML stream, a namepath consists of an |
375 | * optional scope prefix followed by a name segment part. |
376 | * |
377 | * If present, the scope prefix is either a Root Prefix (in |
378 | * which case the name is fully qualified), or one or more |
379 | * Parent Prefixes (in which case the name's scope is relative |
380 | * to the current scope). |
381 | */ |
382 | if (*path == (u8) AML_ROOT_PREFIX) { |
383 | |
384 | /* Pathname is fully qualified, start from the root */ |
385 | |
386 | this_node = acpi_gbl_root_node; |
387 | search_parent_flag = ACPI_NS_NO_UPSEARCH; |
388 | |
389 | /* Point to name segment part */ |
390 | |
391 | path++; |
392 | |
393 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
394 | "Path is absolute from root [%p]\n" , |
395 | this_node)); |
396 | } else { |
397 | /* Pathname is relative to current scope, start there */ |
398 | |
399 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
400 | "Searching relative to prefix scope [%4.4s] (%p)\n" , |
401 | acpi_ut_get_node_name(prefix_node), |
402 | prefix_node)); |
403 | |
404 | /* |
405 | * Handle multiple Parent Prefixes (carat) by just getting |
406 | * the parent node for each prefix instance. |
407 | */ |
408 | this_node = prefix_node; |
409 | num_carats = 0; |
410 | while (*path == (u8) AML_PARENT_PREFIX) { |
411 | |
412 | /* Name is fully qualified, no search rules apply */ |
413 | |
414 | search_parent_flag = ACPI_NS_NO_UPSEARCH; |
415 | |
416 | /* |
417 | * Point past this prefix to the name segment |
418 | * part or the next Parent Prefix |
419 | */ |
420 | path++; |
421 | |
422 | /* Backup to the parent node */ |
423 | |
424 | num_carats++; |
425 | this_node = this_node->parent; |
426 | if (!this_node) { |
427 | /* |
428 | * Current scope has no parent scope. Externalize |
429 | * the internal path for error message. |
430 | */ |
431 | status = |
432 | acpi_ns_externalize_name |
433 | (ACPI_UINT32_MAX, internal_name: pathname, NULL, |
434 | converted_name: &external_path); |
435 | if (ACPI_SUCCESS(status)) { |
436 | ACPI_ERROR((AE_INFO, |
437 | "%s: Path has too many parent prefixes (^)" , |
438 | external_path)); |
439 | |
440 | ACPI_FREE(external_path); |
441 | } |
442 | |
443 | return_ACPI_STATUS(AE_NOT_FOUND); |
444 | } |
445 | } |
446 | |
447 | if (search_parent_flag == ACPI_NS_NO_UPSEARCH) { |
448 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
449 | "Search scope is [%4.4s], path has %u carat(s)\n" , |
450 | acpi_ut_get_node_name |
451 | (this_node), num_carats)); |
452 | } |
453 | } |
454 | |
455 | /* |
456 | * Determine the number of ACPI name segments in this pathname. |
457 | * |
458 | * The segment part consists of either: |
459 | * - A Null name segment (0) |
460 | * - A dual_name_prefix followed by two 4-byte name segments |
461 | * - A multi_name_prefix followed by a byte indicating the |
462 | * number of segments and the segments themselves. |
463 | * - A single 4-byte name segment |
464 | * |
465 | * Examine the name prefix opcode, if any, to determine the number of |
466 | * segments. |
467 | */ |
468 | switch (*path) { |
469 | case 0: |
470 | /* |
471 | * Null name after a root or parent prefixes. We already |
472 | * have the correct target node and there are no name segments. |
473 | */ |
474 | num_segments = 0; |
475 | type = this_node->type; |
476 | |
477 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
478 | "Prefix-only Pathname (Zero name segments), Flags=%X\n" , |
479 | flags)); |
480 | break; |
481 | |
482 | case AML_DUAL_NAME_PREFIX: |
483 | |
484 | /* More than one name_seg, search rules do not apply */ |
485 | |
486 | search_parent_flag = ACPI_NS_NO_UPSEARCH; |
487 | |
488 | /* Two segments, point to first name segment */ |
489 | |
490 | num_segments = 2; |
491 | path++; |
492 | |
493 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
494 | "Dual Pathname (2 segments, Flags=%X)\n" , |
495 | flags)); |
496 | break; |
497 | |
498 | case AML_MULTI_NAME_PREFIX: |
499 | |
500 | /* More than one name_seg, search rules do not apply */ |
501 | |
502 | search_parent_flag = ACPI_NS_NO_UPSEARCH; |
503 | |
504 | /* Extract segment count, point to first name segment */ |
505 | |
506 | path++; |
507 | num_segments = (u32) (u8) * path; |
508 | path++; |
509 | |
510 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
511 | "Multi Pathname (%u Segments, Flags=%X)\n" , |
512 | num_segments, flags)); |
513 | break; |
514 | |
515 | default: |
516 | /* |
517 | * Not a Null name, no Dual or Multi prefix, hence there is |
518 | * only one name segment and Pathname is already pointing to it. |
519 | */ |
520 | num_segments = 1; |
521 | |
522 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
523 | "Simple Pathname (1 segment, Flags=%X)\n" , |
524 | flags)); |
525 | break; |
526 | } |
527 | |
528 | ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path)); |
529 | } |
530 | |
531 | /* |
532 | * Search namespace for each segment of the name. Loop through and |
533 | * verify (or add to the namespace) each name segment. |
534 | * |
535 | * The object type is significant only at the last name |
536 | * segment. (We don't care about the types along the path, only |
537 | * the type of the final target object.) |
538 | */ |
539 | this_search_type = ACPI_TYPE_ANY; |
540 | current_node = this_node; |
541 | |
542 | while (num_segments && current_node) { |
543 | num_segments--; |
544 | if (!num_segments) { |
545 | |
546 | /* This is the last segment, enable typechecking */ |
547 | |
548 | this_search_type = type; |
549 | |
550 | /* |
551 | * Only allow automatic parent search (search rules) if the caller |
552 | * requested it AND we have a single, non-fully-qualified name_seg |
553 | */ |
554 | if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) && |
555 | (flags & ACPI_NS_SEARCH_PARENT)) { |
556 | local_flags |= ACPI_NS_SEARCH_PARENT; |
557 | } |
558 | |
559 | /* Set error flag according to caller */ |
560 | |
561 | if (flags & ACPI_NS_ERROR_IF_FOUND) { |
562 | local_flags |= ACPI_NS_ERROR_IF_FOUND; |
563 | } |
564 | |
565 | /* Set override flag according to caller */ |
566 | |
567 | if (flags & ACPI_NS_OVERRIDE_IF_FOUND) { |
568 | local_flags |= ACPI_NS_OVERRIDE_IF_FOUND; |
569 | } |
570 | } |
571 | |
572 | /* Handle opcodes that create a new name_seg via a full name_path */ |
573 | |
574 | local_interpreter_mode = interpreter_mode; |
575 | if ((flags & ACPI_NS_PREFIX_MUST_EXIST) && (num_segments > 0)) { |
576 | |
577 | /* Every element of the path must exist (except for the final name_seg) */ |
578 | |
579 | local_interpreter_mode = ACPI_IMODE_EXECUTE; |
580 | } |
581 | |
582 | /* Extract one ACPI name from the front of the pathname */ |
583 | |
584 | ACPI_MOVE_32_TO_32(&simple_name, path); |
585 | |
586 | /* Try to find the single (4 character) ACPI name */ |
587 | |
588 | status = |
589 | acpi_ns_search_and_enter(entry_name: simple_name, walk_state, |
590 | node: current_node, |
591 | interpreter_mode: local_interpreter_mode, |
592 | type: this_search_type, flags: local_flags, |
593 | ret_node: &this_node); |
594 | if (ACPI_FAILURE(status)) { |
595 | if (status == AE_NOT_FOUND) { |
596 | #if !defined ACPI_ASL_COMPILER /* Note: iASL reports this error by itself, not needed here */ |
597 | if (flags & ACPI_NS_PREFIX_MUST_EXIST) { |
598 | acpi_os_printf(ACPI_MSG_BIOS_ERROR |
599 | "Object does not exist: %4.4s\n" , |
600 | (char *)&simple_name); |
601 | } |
602 | #endif |
603 | /* Name not found in ACPI namespace */ |
604 | |
605 | ACPI_DEBUG_PRINT((ACPI_DB_NAMES, |
606 | "Name [%4.4s] not found in scope [%4.4s] %p\n" , |
607 | (char *)&simple_name, |
608 | (char *)¤t_node->name, |
609 | current_node)); |
610 | } |
611 | #ifdef ACPI_EXEC_APP |
612 | if ((status == AE_ALREADY_EXISTS) && |
613 | (this_node->flags & ANOBJ_NODE_EARLY_INIT)) { |
614 | this_node->flags &= ~ANOBJ_NODE_EARLY_INIT; |
615 | status = AE_OK; |
616 | } |
617 | #endif |
618 | |
619 | #ifdef ACPI_ASL_COMPILER |
620 | /* |
621 | * If this ACPI name already exists within the namespace as an |
622 | * external declaration, then mark the external as a conflicting |
623 | * declaration and proceed to process the current node as if it did |
624 | * not exist in the namespace. If this node is not processed as |
625 | * normal, then it could cause improper namespace resolution |
626 | * by failing to open a new scope. |
627 | */ |
628 | if (acpi_gbl_disasm_flag && |
629 | (status == AE_ALREADY_EXISTS) && |
630 | ((this_node->flags & ANOBJ_IS_EXTERNAL) || |
631 | (walk_state |
632 | && walk_state->opcode == AML_EXTERNAL_OP))) { |
633 | this_node->flags &= ~ANOBJ_IS_EXTERNAL; |
634 | this_node->type = (u8)this_search_type; |
635 | if (walk_state->opcode != AML_EXTERNAL_OP) { |
636 | acpi_dm_mark_external_conflict |
637 | (this_node); |
638 | } |
639 | break; |
640 | } |
641 | #endif |
642 | |
643 | *return_node = this_node; |
644 | return_ACPI_STATUS(status); |
645 | } |
646 | |
647 | /* More segments to follow? */ |
648 | |
649 | if (num_segments > 0) { |
650 | /* |
651 | * If we have an alias to an object that opens a scope (such as a |
652 | * device or processor), we need to dereference the alias here so |
653 | * that we can access any children of the original node (via the |
654 | * remaining segments). |
655 | */ |
656 | if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { |
657 | if (!this_node->object) { |
658 | return_ACPI_STATUS(AE_NOT_EXIST); |
659 | } |
660 | |
661 | if (acpi_ns_opens_scope |
662 | (type: ((struct acpi_namespace_node *) |
663 | this_node->object)->type)) { |
664 | this_node = |
665 | (struct acpi_namespace_node *) |
666 | this_node->object; |
667 | } |
668 | } |
669 | } |
670 | |
671 | /* Special handling for the last segment (num_segments == 0) */ |
672 | |
673 | else { |
674 | /* |
675 | * Sanity typecheck of the target object: |
676 | * |
677 | * If 1) This is the last segment (num_segments == 0) |
678 | * 2) And we are looking for a specific type |
679 | * (Not checking for TYPE_ANY) |
680 | * 3) Which is not an alias |
681 | * 4) Which is not a local type (TYPE_SCOPE) |
682 | * 5) And the type of target object is known (not TYPE_ANY) |
683 | * 6) And target object does not match what we are looking for |
684 | * |
685 | * Then we have a type mismatch. Just warn and ignore it. |
686 | */ |
687 | if ((type_to_check_for != ACPI_TYPE_ANY) && |
688 | (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && |
689 | (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) |
690 | && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) |
691 | && (this_node->type != ACPI_TYPE_ANY) |
692 | && (this_node->type != type_to_check_for)) { |
693 | |
694 | /* Complain about a type mismatch */ |
695 | |
696 | ACPI_WARNING((AE_INFO, |
697 | "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)" , |
698 | ACPI_CAST_PTR(char, &simple_name), |
699 | acpi_ut_get_type_name(this_node-> |
700 | type), |
701 | acpi_ut_get_type_name |
702 | (type_to_check_for))); |
703 | } |
704 | |
705 | /* |
706 | * If this is the last name segment and we are not looking for a |
707 | * specific type, but the type of found object is known, use that |
708 | * type to (later) see if it opens a scope. |
709 | */ |
710 | if (type == ACPI_TYPE_ANY) { |
711 | type = this_node->type; |
712 | } |
713 | } |
714 | |
715 | /* Point to next name segment and make this node current */ |
716 | |
717 | path += ACPI_NAMESEG_SIZE; |
718 | current_node = this_node; |
719 | } |
720 | |
721 | /* Always check if we need to open a new scope */ |
722 | |
723 | if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) { |
724 | /* |
725 | * If entry is a type which opens a scope, push the new scope on the |
726 | * scope stack. |
727 | */ |
728 | if (acpi_ns_opens_scope(type)) { |
729 | status = |
730 | acpi_ds_scope_stack_push(node: this_node, type, |
731 | walk_state); |
732 | if (ACPI_FAILURE(status)) { |
733 | return_ACPI_STATUS(status); |
734 | } |
735 | } |
736 | } |
737 | #ifdef ACPI_EXEC_APP |
738 | if (flags & ACPI_NS_EARLY_INIT) { |
739 | this_node->flags |= ANOBJ_NODE_EARLY_INIT; |
740 | } |
741 | #endif |
742 | |
743 | *return_node = this_node; |
744 | return_ACPI_STATUS(AE_OK); |
745 | } |
746 | |