brintos

brintos / linux-shallow public Read only

0
0
Text · 13.0 KiB · d91153f Raw
467 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/*******************************************************************************3 *4 * Module Name: nsnames - Name manipulation and search5 *6 ******************************************************************************/7 8#include <acpi/acpi.h>9#include "accommon.h"10#include "amlcode.h"11#include "acnamesp.h"12 13#define _COMPONENT          ACPI_NAMESPACE14ACPI_MODULE_NAME("nsnames")15 16/*******************************************************************************17 *18 * FUNCTION:    acpi_ns_get_external_pathname19 *20 * PARAMETERS:  node            - Namespace node whose pathname is needed21 *22 * RETURN:      Pointer to storage containing the fully qualified name of23 *              the node, In external format (name segments separated by path24 *              separators.)25 *26 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually27 *              for error and debug statements.28 *29 ******************************************************************************/30char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)31{32	char *name_buffer;33 34	ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);35 36	name_buffer = acpi_ns_get_normalized_pathname(node, FALSE);37	return_PTR(name_buffer);38}39 40/*******************************************************************************41 *42 * FUNCTION:    acpi_ns_get_pathname_length43 *44 * PARAMETERS:  node        - Namespace node45 *46 * RETURN:      Length of path, including prefix47 *48 * DESCRIPTION: Get the length of the pathname string for this node49 *50 ******************************************************************************/51 52acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)53{54	acpi_size size;55 56	/* Validate the Node */57 58	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {59		ACPI_ERROR((AE_INFO,60			    "Invalid/cached reference target node: %p, descriptor type %d",61			    node, ACPI_GET_DESCRIPTOR_TYPE(node)));62		return (0);63	}64 65	size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);66	return (size);67}68 69/*******************************************************************************70 *71 * FUNCTION:    acpi_ns_handle_to_name72 *73 * PARAMETERS:  target_handle           - Handle of named object whose name is74 *                                        to be found75 *              buffer                  - Where the name is returned76 *77 * RETURN:      Status, Buffer is filled with name if status is AE_OK78 *79 * DESCRIPTION: Build and return a full namespace name80 *81 ******************************************************************************/82 83acpi_status84acpi_ns_handle_to_name(acpi_handle target_handle, struct acpi_buffer *buffer)85{86	acpi_status status;87	struct acpi_namespace_node *node;88	const char *node_name;89 90	ACPI_FUNCTION_TRACE_PTR(ns_handle_to_name, target_handle);91 92	node = acpi_ns_validate_handle(target_handle);93	if (!node) {94		return_ACPI_STATUS(AE_BAD_PARAMETER);95	}96 97	/* Validate/Allocate/Clear caller buffer */98 99	status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);100	if (ACPI_FAILURE(status)) {101		return_ACPI_STATUS(status);102	}103 104	/* Just copy the ACPI name from the Node and zero terminate it */105 106	node_name = acpi_ut_get_node_name(node);107	ACPI_COPY_NAMESEG(buffer->pointer, node_name);108	((char *)buffer->pointer)[ACPI_NAMESEG_SIZE] = 0;109 110	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%4.4s\n", (char *)buffer->pointer));111	return_ACPI_STATUS(AE_OK);112}113 114/*******************************************************************************115 *116 * FUNCTION:    acpi_ns_handle_to_pathname117 *118 * PARAMETERS:  target_handle           - Handle of named object whose name is119 *                                        to be found120 *              buffer                  - Where the pathname is returned121 *              no_trailing             - Remove trailing '_' for each name122 *                                        segment123 *124 * RETURN:      Status, Buffer is filled with pathname if status is AE_OK125 *126 * DESCRIPTION: Build and return a full namespace pathname127 *128 ******************************************************************************/129 130acpi_status131acpi_ns_handle_to_pathname(acpi_handle target_handle,132			   struct acpi_buffer *buffer, u8 no_trailing)133{134	acpi_status status;135	struct acpi_namespace_node *node;136	acpi_size required_size;137 138	ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);139 140	node = acpi_ns_validate_handle(target_handle);141	if (!node) {142		return_ACPI_STATUS(AE_BAD_PARAMETER);143	}144 145	/* Determine size required for the caller buffer */146 147	required_size =148	    acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);149	if (!required_size) {150		return_ACPI_STATUS(AE_BAD_PARAMETER);151	}152 153	/* Validate/Allocate/Clear caller buffer */154 155	status = acpi_ut_initialize_buffer(buffer, required_size);156	if (ACPI_FAILURE(status)) {157		return_ACPI_STATUS(status);158	}159 160	/* Build the path in the caller buffer */161 162	(void)acpi_ns_build_normalized_path(node, buffer->pointer,163					    (u32)required_size, no_trailing);164 165	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",166			  (char *)buffer->pointer, (u32) required_size));167	return_ACPI_STATUS(AE_OK);168}169 170/*******************************************************************************171 *172 * FUNCTION:    acpi_ns_build_normalized_path173 *174 * PARAMETERS:  node        - Namespace node175 *              full_path   - Where the path name is returned176 *              path_size   - Size of returned path name buffer177 *              no_trailing - Remove trailing '_' from each name segment178 *179 * RETURN:      Return 1 if the AML path is empty, otherwise returning (length180 *              of pathname + 1) which means the 'FullPath' contains a trailing181 *              null.182 *183 * DESCRIPTION: Build and return a full namespace pathname.184 *              Note that if the size of 'FullPath' isn't large enough to185 *              contain the namespace node's path name, the actual required186 *              buffer length is returned, and it should be greater than187 *              'PathSize'. So callers are able to check the returning value188 *              to determine the buffer size of 'FullPath'.189 *190 ******************************************************************************/191 192u32193acpi_ns_build_normalized_path(struct acpi_namespace_node *node,194			      char *full_path, u32 path_size, u8 no_trailing)195{196	u32 length = 0, i;197	char name[ACPI_NAMESEG_SIZE];198	u8 do_no_trailing;199	char c, *left, *right;200	struct acpi_namespace_node *next_node;201 202	ACPI_FUNCTION_TRACE_PTR(ns_build_normalized_path, node);203 204#define ACPI_PATH_PUT8(path, size, byte, length)    \205	do {                                            \206		if ((length) < (size))                      \207		{                                           \208			(path)[(length)] = (byte);              \209		}                                           \210		(length)++;                                 \211	} while (0)212 213	/*214	 * Make sure the path_size is correct, so that we don't need to215	 * validate both full_path and path_size.216	 */217	if (!full_path) {218		path_size = 0;219	}220 221	if (!node) {222		goto build_trailing_null;223	}224 225	next_node = node;226	while (next_node && next_node != acpi_gbl_root_node) {227		if (next_node != node) {228			ACPI_PATH_PUT8(full_path, path_size,229				       AML_DUAL_NAME_PREFIX, length);230		}231 232		ACPI_MOVE_32_TO_32(name, &next_node->name);233		do_no_trailing = no_trailing;234		for (i = 0; i < 4; i++) {235			c = name[4 - i - 1];236			if (do_no_trailing && c != '_') {237				do_no_trailing = FALSE;238			}239			if (!do_no_trailing) {240				ACPI_PATH_PUT8(full_path, path_size, c, length);241			}242		}243 244		next_node = next_node->parent;245	}246 247	ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length);248 249	/* Reverse the path string */250 251	if (length <= path_size) {252		left = full_path;253		right = full_path + length - 1;254 255		while (left < right) {256			c = *left;257			*left++ = *right;258			*right-- = c;259		}260	}261 262	/* Append the trailing null */263 264build_trailing_null:265	ACPI_PATH_PUT8(full_path, path_size, '\0', length);266 267#undef ACPI_PATH_PUT8268 269	return_UINT32(length);270}271 272/*******************************************************************************273 *274 * FUNCTION:    acpi_ns_get_normalized_pathname275 *276 * PARAMETERS:  node            - Namespace node whose pathname is needed277 *              no_trailing     - Remove trailing '_' from each name segment278 *279 * RETURN:      Pointer to storage containing the fully qualified name of280 *              the node, In external format (name segments separated by path281 *              separators.)282 *283 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually284 *              for error and debug statements. All trailing '_' will be285 *              removed from the full pathname if 'NoTrailing' is specified..286 *287 ******************************************************************************/288 289char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,290				      u8 no_trailing)291{292	char *name_buffer;293	acpi_size size;294 295	ACPI_FUNCTION_TRACE_PTR(ns_get_normalized_pathname, node);296 297	/* Calculate required buffer size based on depth below root */298 299	size = acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);300	if (!size) {301		return_PTR(NULL);302	}303 304	/* Allocate a buffer to be returned to caller */305 306	name_buffer = ACPI_ALLOCATE_ZEROED(size);307	if (!name_buffer) {308		ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));309		return_PTR(NULL);310	}311 312	/* Build the path in the allocated buffer */313 314	(void)acpi_ns_build_normalized_path(node, name_buffer, (u32)size,315					    no_trailing);316 317	ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES, "%s: Path \"%s\"\n",318			      ACPI_GET_FUNCTION_NAME, name_buffer));319 320	return_PTR(name_buffer);321}322 323/*******************************************************************************324 *325 * FUNCTION:    acpi_ns_build_prefixed_pathname326 *327 * PARAMETERS:  prefix_scope        - Scope/Path that prefixes the internal path328 *              internal_path       - Name or path of the namespace node329 *330 * RETURN:      None331 *332 * DESCRIPTION: Construct a fully qualified pathname from a concatenation of:333 *              1) Path associated with the prefix_scope namespace node334 *              2) External path representation of the Internal path335 *336 ******************************************************************************/337 338char *acpi_ns_build_prefixed_pathname(union acpi_generic_state *prefix_scope,339				      const char *internal_path)340{341	acpi_status status;342	char *full_path = NULL;343	char *external_path = NULL;344	char *prefix_path = NULL;345	acpi_size prefix_path_length = 0;346 347	/* If there is a prefix, get the pathname to it */348 349	if (prefix_scope && prefix_scope->scope.node) {350		prefix_path =351		    acpi_ns_get_normalized_pathname(prefix_scope->scope.node,352						    TRUE);353		if (prefix_path) {354			prefix_path_length = strlen(prefix_path);355		}356	}357 358	status = acpi_ns_externalize_name(ACPI_UINT32_MAX, internal_path,359					  NULL, &external_path);360	if (ACPI_FAILURE(status)) {361		goto cleanup;362	}363 364	/* Merge the prefix path and the path. 2 is for one dot and trailing null */365 366	full_path =367	    ACPI_ALLOCATE_ZEROED(prefix_path_length + strlen(external_path) +368				 2);369	if (!full_path) {370		goto cleanup;371	}372 373	/* Don't merge if the External path is already fully qualified */374 375	if (prefix_path && (*external_path != '\\') && (*external_path != '^')) {376		strcat(full_path, prefix_path);377		if (prefix_path[1]) {378			strcat(full_path, ".");379		}380	}381 382	acpi_ns_normalize_pathname(external_path);383	strcat(full_path, external_path);384 385cleanup:386	if (prefix_path) {387		ACPI_FREE(prefix_path);388	}389	if (external_path) {390		ACPI_FREE(external_path);391	}392 393	return (full_path);394}395 396/*******************************************************************************397 *398 * FUNCTION:    acpi_ns_normalize_pathname399 *400 * PARAMETERS:  original_path       - Path to be normalized, in External format401 *402 * RETURN:      The original path is processed in-place403 *404 * DESCRIPTION: Remove trailing underscores from each element of a path.405 *406 *              For example:  \A___.B___.C___ becomes \A.B.C407 *408 ******************************************************************************/409 410void acpi_ns_normalize_pathname(char *original_path)411{412	char *input_path = original_path;413	char *new_path_buffer;414	char *new_path;415	u32 i;416 417	/* Allocate a temp buffer in which to construct the new path */418 419	new_path_buffer = ACPI_ALLOCATE_ZEROED(strlen(input_path) + 1);420	new_path = new_path_buffer;421	if (!new_path_buffer) {422		return;423	}424 425	/* Special characters may appear at the beginning of the path */426 427	if (*input_path == '\\') {428		*new_path = *input_path;429		new_path++;430		input_path++;431	}432 433	while (*input_path == '^') {434		*new_path = *input_path;435		new_path++;436		input_path++;437	}438 439	/* Remainder of the path */440 441	while (*input_path) {442 443		/* Do one nameseg at a time */444 445		for (i = 0; (i < ACPI_NAMESEG_SIZE) && *input_path; i++) {446			if ((i == 0) || (*input_path != '_')) {	/* First char is allowed to be underscore */447				*new_path = *input_path;448				new_path++;449			}450 451			input_path++;452		}453 454		/* Dot means that there are more namesegs to come */455 456		if (*input_path == '.') {457			*new_path = *input_path;458			new_path++;459			input_path++;460		}461	}462 463	*new_path = 0;464	strcpy(original_path, new_path_buffer);465	ACPI_FREE(new_path_buffer);466}467