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