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 - 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_EXECUTER 16 ACPI_MODULE_NAME("exnames") 17 18 /* Local prototypes */ 19 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs); 20 21 static 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 39 static 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 123 static 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 206 acpi_status 207 acpi_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 } 399