brintos

brintos / linux-shallow public Read only

0
0
Text · 9.5 KiB · 9a44816 Raw
399 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: exnames - interpreter/scanner name load/execute5 *6 * Copyright (C) 2000 - 2023, 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_EXECUTER16ACPI_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_string26 *27 * PARAMETERS:  prefix_count        - Count of parent levels. Special cases:28 *                                    (-1)==root,  0==none29 *              num_name_segs       - count of 4-character name segments30 *31 * RETURN:      A pointer to the allocated string segment. This segment must32 *              be deleted by the caller.33 *34 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name35 *              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() will102	 * append the segment(s)103	 */104	*temp_ptr = 0;105 106	return_PTR(name_string);107}108 109/*******************************************************************************110 *111 * FUNCTION:    acpi_ex_name_segment112 *113 * PARAMETERS:  in_aml_address  - Pointer to the name in the AML code114 *              name_string     - Where to return the name. The name is appended115 *                                to any existing string to form a namepath116 *117 * RETURN:      Status118 *119 * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream120 *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 looking134	 * at a valid name segment135	 */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 than177		 * the required 4178		 */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_string192 *193 * PARAMETERS:  data_type           - Object type to be associated with this194 *                                    name195 *              in_aml_address      - Pointer to the namestring in the AML code196 *              out_name_string     - Where the namestring is returned197 *              out_name_length     - Length of the returned string198 *199 * RETURN:      Status, namestring and length200 *201 * DESCRIPTION: Extract a full namepath from the AML byte stream,202 *              including any prefixes.203 *204 ******************************************************************************/205 206acpi_status207acpi_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 operators237		 */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}399