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

nsnames.c (13282B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/*******************************************************************************
      3 *
      4 * Module Name: nsnames - Name manipulation and search
      5 *
      6 ******************************************************************************/
      7
      8#include <acpi/acpi.h>
      9#include "accommon.h"
     10#include "amlcode.h"
     11#include "acnamesp.h"
     12
     13#define _COMPONENT          ACPI_NAMESPACE
     14ACPI_MODULE_NAME("nsnames")
     15
     16/*******************************************************************************
     17 *
     18 * FUNCTION:    acpi_ns_get_external_pathname
     19 *
     20 * PARAMETERS:  node            - Namespace node whose pathname is needed
     21 *
     22 * RETURN:      Pointer to storage containing the fully qualified name of
     23 *              the node, In external format (name segments separated by path
     24 *              separators.)
     25 *
     26 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
     27 *              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_length
     43 *
     44 * PARAMETERS:  node        - Namespace node
     45 *
     46 * RETURN:      Length of path, including prefix
     47 *
     48 * DESCRIPTION: Get the length of the pathname string for this node
     49 *
     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_name
     72 *
     73 * PARAMETERS:  target_handle           - Handle of named object whose name is
     74 *                                        to be found
     75 *              buffer                  - Where the name is returned
     76 *
     77 * RETURN:      Status, Buffer is filled with name if status is AE_OK
     78 *
     79 * DESCRIPTION: Build and return a full namespace name
     80 *
     81 ******************************************************************************/
     82
     83acpi_status
     84acpi_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_pathname
    117 *
    118 * PARAMETERS:  target_handle           - Handle of named object whose name is
    119 *                                        to be found
    120 *              buffer                  - Where the pathname is returned
    121 *              no_trailing             - Remove trailing '_' for each name
    122 *                                        segment
    123 *
    124 * RETURN:      Status, Buffer is filled with pathname if status is AE_OK
    125 *
    126 * DESCRIPTION: Build and return a full namespace pathname
    127 *
    128 ******************************************************************************/
    129
    130acpi_status
    131acpi_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_path
    173 *
    174 * PARAMETERS:  node        - Namespace node
    175 *              full_path   - Where the path name is returned
    176 *              path_size   - Size of returned path name buffer
    177 *              no_trailing - Remove trailing '_' from each name segment
    178 *
    179 * RETURN:      Return 1 if the AML path is empty, otherwise returning (length
    180 *              of pathname + 1) which means the 'FullPath' contains a trailing
    181 *              null.
    182 *
    183 * DESCRIPTION: Build and return a full namespace pathname.
    184 *              Note that if the size of 'FullPath' isn't large enough to
    185 *              contain the namespace node's path name, the actual required
    186 *              buffer length is returned, and it should be greater than
    187 *              'PathSize'. So callers are able to check the returning value
    188 *              to determine the buffer size of 'FullPath'.
    189 *
    190 ******************************************************************************/
    191
    192u32
    193acpi_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 to
    215	 * 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_PUT8
    268
    269	return_UINT32(length);
    270}
    271
    272/*******************************************************************************
    273 *
    274 * FUNCTION:    acpi_ns_get_normalized_pathname
    275 *
    276 * PARAMETERS:  node            - Namespace node whose pathname is needed
    277 *              no_trailing     - Remove trailing '_' from each name segment
    278 *
    279 * RETURN:      Pointer to storage containing the fully qualified name of
    280 *              the node, In external format (name segments separated by path
    281 *              separators.)
    282 *
    283 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
    284 *              for error and debug statements. All trailing '_' will be
    285 *              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_pathname
    326 *
    327 * PARAMETERS:  prefix_scope        - Scope/Path that prefixes the internal path
    328 *              internal_path       - Name or path of the namespace node
    329 *
    330 * RETURN:      None
    331 *
    332 * DESCRIPTION: Construct a fully qualified pathname from a concatenation of:
    333 *              1) Path associated with the prefix_scope namespace node
    334 *              2) External path representation of the Internal path
    335 *
    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_pathname
    399 *
    400 * PARAMETERS:  original_path       - Path to be normalized, in External format
    401 *
    402 * RETURN:      The original path is processed in-place
    403 *
    404 * DESCRIPTION: Remove trailing underscores from each element of a path.
    405 *
    406 *              For example:  \A___.B___.C___ becomes \A.B.C
    407 *
    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}