cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nsutils.c (19888B)


      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
     17ACPI_MODULE_NAME("nsutils")
     18
     19/* Local prototypes */
     20#ifdef ACPI_OBSOLETE_FUNCTIONS
     21acpi_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
     36void
     37acpi_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
     75acpi_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
    100u32 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
    129void 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
    200acpi_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
    311acpi_status
    312acpi_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
    366acpi_status
    367acpi_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
    528struct 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
    560void 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
    597u32 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
    634acpi_status
    635acpi_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
    712acpi_status
    713acpi_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}