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

exnames.c (9761B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: exnames - interpreter/scanner name load/execute
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acinterp.h"
     13#include "amlcode.h"
     14
     15#define _COMPONENT          ACPI_EXECUTER
     16ACPI_MODULE_NAME("exnames")
     17
     18/* Local prototypes */
     19static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
     20
     21static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
     22
     23/*******************************************************************************
     24 *
     25 * FUNCTION:    acpi_ex_allocate_name_string
     26 *
     27 * PARAMETERS:  prefix_count        - Count of parent levels. Special cases:
     28 *                                    (-1)==root,  0==none
     29 *              num_name_segs       - count of 4-character name segments
     30 *
     31 * RETURN:      A pointer to the allocated string segment. This segment must
     32 *              be deleted by the caller.
     33 *
     34 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
     35 *              string is long enough, and set up prefix if any.
     36 *
     37 ******************************************************************************/
     38
     39static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
     40{
     41	char *temp_ptr;
     42	char *name_string;
     43	u32 size_needed;
     44
     45	ACPI_FUNCTION_TRACE(ex_allocate_name_string);
     46
     47	/*
     48	 * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
     49	 * Also, one byte for the null terminator.
     50	 * This may actually be somewhat longer than needed.
     51	 */
     52	if (prefix_count == ACPI_UINT32_MAX) {
     53
     54		/* Special case for root */
     55
     56		size_needed = 1 + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
     57	} else {
     58		size_needed =
     59		    prefix_count + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
     60	}
     61
     62	/*
     63	 * Allocate a buffer for the name.
     64	 * This buffer must be deleted by the caller!
     65	 */
     66	name_string = ACPI_ALLOCATE(size_needed);
     67	if (!name_string) {
     68		ACPI_ERROR((AE_INFO,
     69			    "Could not allocate size %u", size_needed));
     70		return_PTR(NULL);
     71	}
     72
     73	temp_ptr = name_string;
     74
     75	/* Set up Root or Parent prefixes if needed */
     76
     77	if (prefix_count == ACPI_UINT32_MAX) {
     78		*temp_ptr++ = AML_ROOT_PREFIX;
     79	} else {
     80		while (prefix_count--) {
     81			*temp_ptr++ = AML_PARENT_PREFIX;
     82		}
     83	}
     84
     85	/* Set up Dual or Multi prefixes if needed */
     86
     87	if (num_name_segs > 2) {
     88
     89		/* Set up multi prefixes   */
     90
     91		*temp_ptr++ = AML_MULTI_NAME_PREFIX;
     92		*temp_ptr++ = (char)num_name_segs;
     93	} else if (2 == num_name_segs) {
     94
     95		/* Set up dual prefixes */
     96
     97		*temp_ptr++ = AML_DUAL_NAME_PREFIX;
     98	}
     99
    100	/*
    101	 * Terminate string following prefixes. acpi_ex_name_segment() will
    102	 * append the segment(s)
    103	 */
    104	*temp_ptr = 0;
    105
    106	return_PTR(name_string);
    107}
    108
    109/*******************************************************************************
    110 *
    111 * FUNCTION:    acpi_ex_name_segment
    112 *
    113 * PARAMETERS:  in_aml_address  - Pointer to the name in the AML code
    114 *              name_string     - Where to return the name. The name is appended
    115 *                                to any existing string to form a namepath
    116 *
    117 * RETURN:      Status
    118 *
    119 * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
    120 *
    121 ******************************************************************************/
    122
    123static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
    124{
    125	char *aml_address = (void *)*in_aml_address;
    126	acpi_status status = AE_OK;
    127	u32 index;
    128	char char_buf[5];
    129
    130	ACPI_FUNCTION_TRACE(ex_name_segment);
    131
    132	/*
    133	 * If first character is a digit, then we know that we aren't looking
    134	 * at a valid name segment
    135	 */
    136	char_buf[0] = *aml_address;
    137
    138	if ('0' <= char_buf[0] && char_buf[0] <= '9') {
    139		ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
    140		return_ACPI_STATUS(AE_CTRL_PENDING);
    141	}
    142
    143	for (index = 0;
    144	     (index < ACPI_NAMESEG_SIZE)
    145	     && (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
    146		char_buf[index] = *aml_address++;
    147	}
    148
    149	/* Valid name segment  */
    150
    151	if (index == 4) {
    152
    153		/* Found 4 valid characters */
    154
    155		char_buf[4] = '\0';
    156
    157		if (name_string) {
    158			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
    159					  "Appending NameSeg %s\n", char_buf));
    160			strcat(name_string, char_buf);
    161		} else {
    162			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
    163					  "No Name string - %s\n", char_buf));
    164		}
    165	} else if (index == 0) {
    166		/*
    167		 * First character was not a valid name character,
    168		 * so we are looking at something other than a name.
    169		 */
    170		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
    171				  "Leading character is not alpha: %02Xh (not a name)\n",
    172				  char_buf[0]));
    173		status = AE_CTRL_PENDING;
    174	} else {
    175		/*
    176		 * Segment started with one or more valid characters, but fewer than
    177		 * the required 4
    178		 */
    179		status = AE_AML_BAD_NAME;
    180		ACPI_ERROR((AE_INFO,
    181			    "Bad character 0x%02x in name, at %p",
    182			    *aml_address, aml_address));
    183	}
    184
    185	*in_aml_address = ACPI_CAST_PTR(u8, aml_address);
    186	return_ACPI_STATUS(status);
    187}
    188
    189/*******************************************************************************
    190 *
    191 * FUNCTION:    acpi_ex_get_name_string
    192 *
    193 * PARAMETERS:  data_type           - Object type to be associated with this
    194 *                                    name
    195 *              in_aml_address      - Pointer to the namestring in the AML code
    196 *              out_name_string     - Where the namestring is returned
    197 *              out_name_length     - Length of the returned string
    198 *
    199 * RETURN:      Status, namestring and length
    200 *
    201 * DESCRIPTION: Extract a full namepath from the AML byte stream,
    202 *              including any prefixes.
    203 *
    204 ******************************************************************************/
    205
    206acpi_status
    207acpi_ex_get_name_string(acpi_object_type data_type,
    208			u8 * in_aml_address,
    209			char **out_name_string, u32 * out_name_length)
    210{
    211	acpi_status status = AE_OK;
    212	u8 *aml_address = in_aml_address;
    213	char *name_string = NULL;
    214	u32 num_segments;
    215	u32 prefix_count = 0;
    216	u8 has_prefix = FALSE;
    217
    218	ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
    219
    220	if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
    221	    ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
    222	    ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
    223
    224		/* Disallow prefixes for types associated with field_unit names */
    225
    226		name_string = acpi_ex_allocate_name_string(0, 1);
    227		if (!name_string) {
    228			status = AE_NO_MEMORY;
    229		} else {
    230			status =
    231			    acpi_ex_name_segment(&aml_address, name_string);
    232		}
    233	} else {
    234		/*
    235		 * data_type is not a field name.
    236		 * Examine first character of name for root or parent prefix operators
    237		 */
    238		switch (*aml_address) {
    239		case AML_ROOT_PREFIX:
    240
    241			ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
    242					  "RootPrefix(\\) at %p\n",
    243					  aml_address));
    244
    245			/*
    246			 * Remember that we have a root_prefix --
    247			 * see comment in acpi_ex_allocate_name_string()
    248			 */
    249			aml_address++;
    250			prefix_count = ACPI_UINT32_MAX;
    251			has_prefix = TRUE;
    252			break;
    253
    254		case AML_PARENT_PREFIX:
    255
    256			/* Increment past possibly multiple parent prefixes */
    257
    258			do {
    259				ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
    260						  "ParentPrefix (^) at %p\n",
    261						  aml_address));
    262
    263				aml_address++;
    264				prefix_count++;
    265
    266			} while (*aml_address == AML_PARENT_PREFIX);
    267
    268			has_prefix = TRUE;
    269			break;
    270
    271		default:
    272
    273			/* Not a prefix character */
    274
    275			break;
    276		}
    277
    278		/* Examine first character of name for name segment prefix operator */
    279
    280		switch (*aml_address) {
    281		case AML_DUAL_NAME_PREFIX:
    282
    283			ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
    284					  "DualNamePrefix at %p\n",
    285					  aml_address));
    286
    287			aml_address++;
    288			name_string =
    289			    acpi_ex_allocate_name_string(prefix_count, 2);
    290			if (!name_string) {
    291				status = AE_NO_MEMORY;
    292				break;
    293			}
    294
    295			/* Indicate that we processed a prefix */
    296
    297			has_prefix = TRUE;
    298
    299			status =
    300			    acpi_ex_name_segment(&aml_address, name_string);
    301			if (ACPI_SUCCESS(status)) {
    302				status =
    303				    acpi_ex_name_segment(&aml_address,
    304							 name_string);
    305			}
    306			break;
    307
    308		case AML_MULTI_NAME_PREFIX:
    309
    310			ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
    311					  "MultiNamePrefix at %p\n",
    312					  aml_address));
    313
    314			/* Fetch count of segments remaining in name path */
    315
    316			aml_address++;
    317			num_segments = *aml_address;
    318
    319			name_string =
    320			    acpi_ex_allocate_name_string(prefix_count,
    321							 num_segments);
    322			if (!name_string) {
    323				status = AE_NO_MEMORY;
    324				break;
    325			}
    326
    327			/* Indicate that we processed a prefix */
    328
    329			aml_address++;
    330			has_prefix = TRUE;
    331
    332			while (num_segments &&
    333			       (status =
    334				acpi_ex_name_segment(&aml_address,
    335						     name_string)) == AE_OK) {
    336				num_segments--;
    337			}
    338
    339			break;
    340
    341		case 0:
    342
    343			/* null_name valid as of 8-12-98 ASL/AML Grammar Update */
    344
    345			if (prefix_count == ACPI_UINT32_MAX) {
    346				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
    347						  "NameSeg is \"\\\" followed by NULL\n"));
    348			}
    349
    350			/* Consume the NULL byte */
    351
    352			aml_address++;
    353			name_string =
    354			    acpi_ex_allocate_name_string(prefix_count, 0);
    355			if (!name_string) {
    356				status = AE_NO_MEMORY;
    357				break;
    358			}
    359
    360			break;
    361
    362		default:
    363
    364			/* Name segment string */
    365
    366			name_string =
    367			    acpi_ex_allocate_name_string(prefix_count, 1);
    368			if (!name_string) {
    369				status = AE_NO_MEMORY;
    370				break;
    371			}
    372
    373			status =
    374			    acpi_ex_name_segment(&aml_address, name_string);
    375			break;
    376		}
    377	}
    378
    379	if (AE_CTRL_PENDING == status && has_prefix) {
    380
    381		/* Ran out of segments after processing a prefix */
    382
    383		ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
    384		status = AE_AML_BAD_NAME;
    385	}
    386
    387	if (ACPI_FAILURE(status)) {
    388		if (name_string) {
    389			ACPI_FREE(name_string);
    390		}
    391		return_ACPI_STATUS(status);
    392	}
    393
    394	*out_name_string = name_string;
    395	*out_name_length = (u32) (aml_address - in_aml_address);
    396
    397	return_ACPI_STATUS(status);
    398}