1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
5  *                        parents and siblings and Scope manipulation
6  *
7  * Copyright (C) 2000 - 2022, Intel Corp.
8  *
9  *****************************************************************************/
10 
11 #include <acpi/acpi.h>
12 #include "accommon.h"
13 #include "acnamesp.h"
14 #include "amlcode.h"
15 
16 #define _COMPONENT          ACPI_NAMESPACE
17 ACPI_MODULE_NAME("nsutils")
18 
19 /* Local prototypes */
20 #ifdef ACPI_OBSOLETE_FUNCTIONS
21 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
22 #endif
23 
24 /*******************************************************************************
25  *
26  * FUNCTION:    acpi_ns_print_node_pathname
27  *
28  * PARAMETERS:  node            - Object
29  *              message         - Prefix message
30  *
31  * DESCRIPTION: Print an object's full namespace pathname
32  *              Manages allocation/freeing of a pathname buffer
33  *
34  ******************************************************************************/
35 
36 void
acpi_ns_print_node_pathname(struct acpi_namespace_node * node,const char * message)37 acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
38 			    const char *message)
39 {
40 	struct acpi_buffer buffer;
41 	acpi_status status;
42 
43 	if (!node) {
44 		acpi_os_printf("[NULL NAME]");
45 		return;
46 	}
47 
48 	/* Convert handle to full pathname and print it (with supplied message) */
49 
50 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
51 
52 	status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
53 	if (ACPI_SUCCESS(status)) {
54 		if (message) {
55 			acpi_os_printf("%s ", message);
56 		}
57 
58 		acpi_os_printf("%s", (char *)buffer.pointer);
59 		ACPI_FREE(buffer.pointer);
60 	}
61 }
62 
63 /*******************************************************************************
64  *
65  * FUNCTION:    acpi_ns_get_type
66  *
67  * PARAMETERS:  node        - Parent Node to be examined
68  *
69  * RETURN:      Type field from Node whose handle is passed
70  *
71  * DESCRIPTION: Return the type of a Namespace node
72  *
73  ******************************************************************************/
74 
acpi_ns_get_type(struct acpi_namespace_node * node)75 acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
76 {
77 	ACPI_FUNCTION_TRACE(ns_get_type);
78 
79 	if (!node) {
80 		ACPI_WARNING((AE_INFO, "Null Node parameter"));
81 		return_UINT8(ACPI_TYPE_ANY);
82 	}
83 
84 	return_UINT8(node->type);
85 }
86 
87 /*******************************************************************************
88  *
89  * FUNCTION:    acpi_ns_local
90  *
91  * PARAMETERS:  type        - A namespace object type
92  *
93  * RETURN:      LOCAL if names must be found locally in objects of the
94  *              passed type, 0 if enclosing scopes should be searched
95  *
96  * DESCRIPTION: Returns scope rule for the given object type.
97  *
98  ******************************************************************************/
99 
acpi_ns_local(acpi_object_type type)100 u32 acpi_ns_local(acpi_object_type type)
101 {
102 	ACPI_FUNCTION_TRACE(ns_local);
103 
104 	if (!acpi_ut_valid_object_type(type)) {
105 
106 		/* Type code out of range  */
107 
108 		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
109 		return_UINT32(ACPI_NS_NORMAL);
110 	}
111 
112 	return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
113 }
114 
115 /*******************************************************************************
116  *
117  * FUNCTION:    acpi_ns_get_internal_name_length
118  *
119  * PARAMETERS:  info            - Info struct initialized with the
120  *                                external name pointer.
121  *
122  * RETURN:      None
123  *
124  * DESCRIPTION: Calculate the length of the internal (AML) namestring
125  *              corresponding to the external (ASL) namestring.
126  *
127  ******************************************************************************/
128 
acpi_ns_get_internal_name_length(struct acpi_namestring_info * info)129 void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
130 {
131 	const char *next_external_char;
132 	u32 i;
133 
134 	ACPI_FUNCTION_ENTRY();
135 
136 	next_external_char = info->external_name;
137 	info->num_carats = 0;
138 	info->num_segments = 0;
139 	info->fully_qualified = FALSE;
140 
141 	/*
142 	 * For the internal name, the required length is 4 bytes per segment,
143 	 * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
144 	 * trailing null (which is not really needed, but no there's harm in
145 	 * putting it there)
146 	 *
147 	 * strlen() + 1 covers the first name_seg, which has no path separator
148 	 */
149 	if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
150 		info->fully_qualified = TRUE;
151 		next_external_char++;
152 
153 		/* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */
154 
155 		while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
156 			next_external_char++;
157 		}
158 	} else {
159 		/* Handle Carat prefixes */
160 
161 		while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
162 			info->num_carats++;
163 			next_external_char++;
164 		}
165 	}
166 
167 	/*
168 	 * Determine the number of ACPI name "segments" by counting the number of
169 	 * path separators within the string. Start with one segment since the
170 	 * segment count is [(# separators) + 1], and zero separators is ok.
171 	 */
172 	if (*next_external_char) {
173 		info->num_segments = 1;
174 		for (i = 0; next_external_char[i]; i++) {
175 			if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
176 				info->num_segments++;
177 			}
178 		}
179 	}
180 
181 	info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
182 	    4 + info->num_carats;
183 
184 	info->next_external_char = next_external_char;
185 }
186 
187 /*******************************************************************************
188  *
189  * FUNCTION:    acpi_ns_build_internal_name
190  *
191  * PARAMETERS:  info            - Info struct fully initialized
192  *
193  * RETURN:      Status
194  *
195  * DESCRIPTION: Construct the internal (AML) namestring
196  *              corresponding to the external (ASL) namestring.
197  *
198  ******************************************************************************/
199 
acpi_ns_build_internal_name(struct acpi_namestring_info * info)200 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
201 {
202 	u32 num_segments = info->num_segments;
203 	char *internal_name = info->internal_name;
204 	const char *external_name = info->next_external_char;
205 	char *result = NULL;
206 	u32 i;
207 
208 	ACPI_FUNCTION_TRACE(ns_build_internal_name);
209 
210 	/* Setup the correct prefixes, counts, and pointers */
211 
212 	if (info->fully_qualified) {
213 		internal_name[0] = AML_ROOT_PREFIX;
214 
215 		if (num_segments <= 1) {
216 			result = &internal_name[1];
217 		} else if (num_segments == 2) {
218 			internal_name[1] = AML_DUAL_NAME_PREFIX;
219 			result = &internal_name[2];
220 		} else {
221 			internal_name[1] = AML_MULTI_NAME_PREFIX;
222 			internal_name[2] = (char)num_segments;
223 			result = &internal_name[3];
224 		}
225 	} else {
226 		/*
227 		 * Not fully qualified.
228 		 * Handle Carats first, then append the name segments
229 		 */
230 		i = 0;
231 		if (info->num_carats) {
232 			for (i = 0; i < info->num_carats; i++) {
233 				internal_name[i] = AML_PARENT_PREFIX;
234 			}
235 		}
236 
237 		if (num_segments <= 1) {
238 			result = &internal_name[i];
239 		} else if (num_segments == 2) {
240 			internal_name[i] = AML_DUAL_NAME_PREFIX;
241 			result = &internal_name[(acpi_size)i + 1];
242 		} else {
243 			internal_name[i] = AML_MULTI_NAME_PREFIX;
244 			internal_name[(acpi_size)i + 1] = (char)num_segments;
245 			result = &internal_name[(acpi_size)i + 2];
246 		}
247 	}
248 
249 	/* Build the name (minus path separators) */
250 
251 	for (; num_segments; num_segments--) {
252 		for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
253 			if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
254 			    (*external_name == 0)) {
255 
256 				/* Pad the segment with underscore(s) if segment is short */
257 
258 				result[i] = '_';
259 			} else {
260 				/* Convert the character to uppercase and save it */
261 
262 				result[i] = (char)toupper((int)*external_name);
263 				external_name++;
264 			}
265 		}
266 
267 		/* Now we must have a path separator, or the pathname is bad */
268 
269 		if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
270 		    (*external_name != 0)) {
271 			return_ACPI_STATUS(AE_BAD_PATHNAME);
272 		}
273 
274 		/* Move on the next segment */
275 
276 		external_name++;
277 		result += ACPI_NAMESEG_SIZE;
278 	}
279 
280 	/* Terminate the string */
281 
282 	*result = 0;
283 
284 	if (info->fully_qualified) {
285 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
286 				  "Returning [%p] (abs) \"\\%s\"\n",
287 				  internal_name, internal_name));
288 	} else {
289 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
290 				  internal_name, internal_name));
291 	}
292 
293 	return_ACPI_STATUS(AE_OK);
294 }
295 
296 /*******************************************************************************
297  *
298  * FUNCTION:    acpi_ns_internalize_name
299  *
300  * PARAMETERS:  *external_name          - External representation of name
301  *              **Converted name        - Where to return the resulting
302  *                                        internal represention of the name
303  *
304  * RETURN:      Status
305  *
306  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
307  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
308  *
309  *******************************************************************************/
310 
311 acpi_status
acpi_ns_internalize_name(const char * external_name,char ** converted_name)312 acpi_ns_internalize_name(const char *external_name, char **converted_name)
313 {
314 	char *internal_name;
315 	struct acpi_namestring_info info;
316 	acpi_status status;
317 
318 	ACPI_FUNCTION_TRACE(ns_internalize_name);
319 
320 	if ((!external_name) || (*external_name == 0) || (!converted_name)) {
321 		return_ACPI_STATUS(AE_BAD_PARAMETER);
322 	}
323 
324 	/* Get the length of the new internal name */
325 
326 	info.external_name = external_name;
327 	acpi_ns_get_internal_name_length(&info);
328 
329 	/* We need a segment to store the internal  name */
330 
331 	internal_name = ACPI_ALLOCATE_ZEROED(info.length);
332 	if (!internal_name) {
333 		return_ACPI_STATUS(AE_NO_MEMORY);
334 	}
335 
336 	/* Build the name */
337 
338 	info.internal_name = internal_name;
339 	status = acpi_ns_build_internal_name(&info);
340 	if (ACPI_FAILURE(status)) {
341 		ACPI_FREE(internal_name);
342 		return_ACPI_STATUS(status);
343 	}
344 
345 	*converted_name = internal_name;
346 	return_ACPI_STATUS(AE_OK);
347 }
348 
349 /*******************************************************************************
350  *
351  * FUNCTION:    acpi_ns_externalize_name
352  *
353  * PARAMETERS:  internal_name_length - Length of the internal name below
354  *              internal_name       - Internal representation of name
355  *              converted_name_length - Where the length is returned
356  *              converted_name      - Where the resulting external name
357  *                                    is returned
358  *
359  * RETURN:      Status
360  *
361  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
362  *              to its external (printable) form (e.g. "\_PR_.CPU0")
363  *
364  ******************************************************************************/
365 
366 acpi_status
acpi_ns_externalize_name(u32 internal_name_length,const char * internal_name,u32 * converted_name_length,char ** converted_name)367 acpi_ns_externalize_name(u32 internal_name_length,
368 			 const char *internal_name,
369 			 u32 * converted_name_length, char **converted_name)
370 {
371 	u32 names_index = 0;
372 	u32 num_segments = 0;
373 	u32 required_length;
374 	u32 prefix_length = 0;
375 	u32 i = 0;
376 	u32 j = 0;
377 
378 	ACPI_FUNCTION_TRACE(ns_externalize_name);
379 
380 	if (!internal_name_length || !internal_name || !converted_name) {
381 		return_ACPI_STATUS(AE_BAD_PARAMETER);
382 	}
383 
384 	/* Check for a prefix (one '\' | one or more '^') */
385 
386 	switch (internal_name[0]) {
387 	case AML_ROOT_PREFIX:
388 
389 		prefix_length = 1;
390 		break;
391 
392 	case AML_PARENT_PREFIX:
393 
394 		for (i = 0; i < internal_name_length; i++) {
395 			if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
396 				prefix_length = i + 1;
397 			} else {
398 				break;
399 			}
400 		}
401 
402 		if (i == internal_name_length) {
403 			prefix_length = i;
404 		}
405 
406 		break;
407 
408 	default:
409 
410 		break;
411 	}
412 
413 	/*
414 	 * Check for object names. Note that there could be 0-255 of these
415 	 * 4-byte elements.
416 	 */
417 	if (prefix_length < internal_name_length) {
418 		switch (internal_name[prefix_length]) {
419 		case AML_MULTI_NAME_PREFIX:
420 
421 			/* <count> 4-byte names */
422 
423 			names_index = prefix_length + 2;
424 			num_segments = (u8)
425 			    internal_name[(acpi_size)prefix_length + 1];
426 			break;
427 
428 		case AML_DUAL_NAME_PREFIX:
429 
430 			/* Two 4-byte names */
431 
432 			names_index = prefix_length + 1;
433 			num_segments = 2;
434 			break;
435 
436 		case 0:
437 
438 			/* null_name */
439 
440 			names_index = 0;
441 			num_segments = 0;
442 			break;
443 
444 		default:
445 
446 			/* one 4-byte name */
447 
448 			names_index = prefix_length;
449 			num_segments = 1;
450 			break;
451 		}
452 	}
453 
454 	/*
455 	 * Calculate the length of converted_name, which equals the length
456 	 * of the prefix, length of all object names, length of any required
457 	 * punctuation ('.') between object names, plus the NULL terminator.
458 	 */
459 	required_length = prefix_length + (4 * num_segments) +
460 	    ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
461 
462 	/*
463 	 * Check to see if we're still in bounds. If not, there's a problem
464 	 * with internal_name (invalid format).
465 	 */
466 	if (required_length > internal_name_length) {
467 		ACPI_ERROR((AE_INFO, "Invalid internal name"));
468 		return_ACPI_STATUS(AE_BAD_PATHNAME);
469 	}
470 
471 	/* Build the converted_name */
472 
473 	*converted_name = ACPI_ALLOCATE_ZEROED(required_length);
474 	if (!(*converted_name)) {
475 		return_ACPI_STATUS(AE_NO_MEMORY);
476 	}
477 
478 	j = 0;
479 
480 	for (i = 0; i < prefix_length; i++) {
481 		(*converted_name)[j++] = internal_name[i];
482 	}
483 
484 	if (num_segments > 0) {
485 		for (i = 0; i < num_segments; i++) {
486 			if (i > 0) {
487 				(*converted_name)[j++] = '.';
488 			}
489 
490 			/* Copy and validate the 4-char name segment */
491 
492 			ACPI_COPY_NAMESEG(&(*converted_name)[j],
493 					  &internal_name[names_index]);
494 			acpi_ut_repair_name(&(*converted_name)[j]);
495 
496 			j += ACPI_NAMESEG_SIZE;
497 			names_index += ACPI_NAMESEG_SIZE;
498 		}
499 	}
500 
501 	if (converted_name_length) {
502 		*converted_name_length = (u32) required_length;
503 	}
504 
505 	return_ACPI_STATUS(AE_OK);
506 }
507 
508 /*******************************************************************************
509  *
510  * FUNCTION:    acpi_ns_validate_handle
511  *
512  * PARAMETERS:  handle          - Handle to be validated and typecast to a
513  *                                namespace node.
514  *
515  * RETURN:      A pointer to a namespace node
516  *
517  * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
518  *              cases for the root node.
519  *
520  * NOTE: Real integer handles would allow for more verification
521  *       and keep all pointers within this subsystem - however this introduces
522  *       more overhead and has not been necessary to this point. Drivers
523  *       holding handles are typically notified before a node becomes invalid
524  *       due to a table unload.
525  *
526  ******************************************************************************/
527 
acpi_ns_validate_handle(acpi_handle handle)528 struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
529 {
530 
531 	ACPI_FUNCTION_ENTRY();
532 
533 	/* Parameter validation */
534 
535 	if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
536 		return (acpi_gbl_root_node);
537 	}
538 
539 	/* We can at least attempt to verify the handle */
540 
541 	if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
542 		return (NULL);
543 	}
544 
545 	return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
546 }
547 
548 /*******************************************************************************
549  *
550  * FUNCTION:    acpi_ns_terminate
551  *
552  * PARAMETERS:  none
553  *
554  * RETURN:      none
555  *
556  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
557  *
558  ******************************************************************************/
559 
acpi_ns_terminate(void)560 void acpi_ns_terminate(void)
561 {
562 	acpi_status status;
563 
564 	ACPI_FUNCTION_TRACE(ns_terminate);
565 
566 	/*
567 	 * Free the entire namespace -- all nodes and all objects
568 	 * attached to the nodes
569 	 */
570 	acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
571 
572 	/* Delete any objects attached to the root node */
573 
574 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
575 	if (ACPI_FAILURE(status)) {
576 		return_VOID;
577 	}
578 
579 	acpi_ns_delete_node(acpi_gbl_root_node);
580 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
581 
582 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
583 	return_VOID;
584 }
585 
586 /*******************************************************************************
587  *
588  * FUNCTION:    acpi_ns_opens_scope
589  *
590  * PARAMETERS:  type        - A valid namespace type
591  *
592  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
593  *              to the ACPI specification, else 0
594  *
595  ******************************************************************************/
596 
acpi_ns_opens_scope(acpi_object_type type)597 u32 acpi_ns_opens_scope(acpi_object_type type)
598 {
599 	ACPI_FUNCTION_ENTRY();
600 
601 	if (type > ACPI_TYPE_LOCAL_MAX) {
602 
603 		/* type code out of range  */
604 
605 		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
606 		return (ACPI_NS_NORMAL);
607 	}
608 
609 	return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
610 }
611 
612 /*******************************************************************************
613  *
614  * FUNCTION:    acpi_ns_get_node_unlocked
615  *
616  * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
617  *                            \ (backslash) and ^ (carat) prefixes, and the
618  *                            . (period) to separate segments are supported.
619  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
620  *                            root of the name space. If Name is fully
621  *                            qualified (first s8 is '\'), the passed value
622  *                            of Scope will not be accessed.
623  *              flags       - Used to indicate whether to perform upsearch or
624  *                            not.
625  *              return_node - Where the Node is returned
626  *
627  * DESCRIPTION: Look up a name relative to a given scope and return the
628  *              corresponding Node. NOTE: Scope can be null.
629  *
630  * MUTEX:       Doesn't locks namespace
631  *
632  ******************************************************************************/
633 
634 acpi_status
acpi_ns_get_node_unlocked(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)635 acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
636 			  const char *pathname,
637 			  u32 flags, struct acpi_namespace_node **return_node)
638 {
639 	union acpi_generic_state scope_info;
640 	acpi_status status;
641 	char *internal_path;
642 
643 	ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
644 				ACPI_CAST_PTR(char, pathname));
645 
646 	/* Simplest case is a null pathname */
647 
648 	if (!pathname) {
649 		*return_node = prefix_node;
650 		if (!prefix_node) {
651 			*return_node = acpi_gbl_root_node;
652 		}
653 
654 		return_ACPI_STATUS(AE_OK);
655 	}
656 
657 	/* Quick check for a reference to the root */
658 
659 	if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
660 		*return_node = acpi_gbl_root_node;
661 		return_ACPI_STATUS(AE_OK);
662 	}
663 
664 	/* Convert path to internal representation */
665 
666 	status = acpi_ns_internalize_name(pathname, &internal_path);
667 	if (ACPI_FAILURE(status)) {
668 		return_ACPI_STATUS(status);
669 	}
670 
671 	/* Setup lookup scope (search starting point) */
672 
673 	scope_info.scope.node = prefix_node;
674 
675 	/* Lookup the name in the namespace */
676 
677 	status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
678 				ACPI_IMODE_EXECUTE,
679 				(flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
680 				return_node);
681 	if (ACPI_FAILURE(status)) {
682 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
683 				  pathname, acpi_format_exception(status)));
684 	}
685 
686 	ACPI_FREE(internal_path);
687 	return_ACPI_STATUS(status);
688 }
689 
690 /*******************************************************************************
691  *
692  * FUNCTION:    acpi_ns_get_node
693  *
694  * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
695  *                            \ (backslash) and ^ (carat) prefixes, and the
696  *                            . (period) to separate segments are supported.
697  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
698  *                            root of the name space. If Name is fully
699  *                            qualified (first s8 is '\'), the passed value
700  *                            of Scope will not be accessed.
701  *              flags       - Used to indicate whether to perform upsearch or
702  *                            not.
703  *              return_node - Where the Node is returned
704  *
705  * DESCRIPTION: Look up a name relative to a given scope and return the
706  *              corresponding Node. NOTE: Scope can be null.
707  *
708  * MUTEX:       Locks namespace
709  *
710  ******************************************************************************/
711 
712 acpi_status
acpi_ns_get_node(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)713 acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
714 		 const char *pathname,
715 		 u32 flags, struct acpi_namespace_node **return_node)
716 {
717 	acpi_status status;
718 
719 	ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
720 
721 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
722 	if (ACPI_FAILURE(status)) {
723 		return_ACPI_STATUS(status);
724 	}
725 
726 	status = acpi_ns_get_node_unlocked(prefix_node, pathname,
727 					   flags, return_node);
728 
729 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
730 	return_ACPI_STATUS(status);
731 }
732