1 /****************************************************************************** 2 * 3 * Module Name: exnames - interpreter/scanner name load/execute 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acinterp.h" 47 #include "amlcode.h" 48 49 #define _COMPONENT ACPI_EXECUTER 50 ACPI_MODULE_NAME("exnames") 51 52 /* Local prototypes */ 53 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs); 54 55 static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string); 56 57 /******************************************************************************* 58 * 59 * FUNCTION: acpi_ex_allocate_name_string 60 * 61 * PARAMETERS: prefix_count - Count of parent levels. Special cases: 62 * (-1)==root, 0==none 63 * num_name_segs - count of 4-character name segments 64 * 65 * RETURN: A pointer to the allocated string segment. This segment must 66 * be deleted by the caller. 67 * 68 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name 69 * string is long enough, and set up prefix if any. 70 * 71 ******************************************************************************/ 72 73 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) 74 { 75 char *temp_ptr; 76 char *name_string; 77 u32 size_needed; 78 79 ACPI_FUNCTION_TRACE(ex_allocate_name_string); 80 81 /* 82 * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix. 83 * Also, one byte for the null terminator. 84 * This may actually be somewhat longer than needed. 85 */ 86 if (prefix_count == ACPI_UINT32_MAX) { 87 88 /* Special case for root */ 89 90 size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; 91 } else { 92 size_needed = 93 prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; 94 } 95 96 /* 97 * Allocate a buffer for the name. 98 * This buffer must be deleted by the caller! 99 */ 100 name_string = ACPI_ALLOCATE(size_needed); 101 if (!name_string) { 102 ACPI_ERROR((AE_INFO, 103 "Could not allocate size %u", size_needed)); 104 return_PTR(NULL); 105 } 106 107 temp_ptr = name_string; 108 109 /* Set up Root or Parent prefixes if needed */ 110 111 if (prefix_count == ACPI_UINT32_MAX) { 112 *temp_ptr++ = AML_ROOT_PREFIX; 113 } else { 114 while (prefix_count--) { 115 *temp_ptr++ = AML_PARENT_PREFIX; 116 } 117 } 118 119 /* Set up Dual or Multi prefixes if needed */ 120 121 if (num_name_segs > 2) { 122 123 /* Set up multi prefixes */ 124 125 *temp_ptr++ = AML_MULTI_NAME_PREFIX; 126 *temp_ptr++ = (char)num_name_segs; 127 } else if (2 == num_name_segs) { 128 129 /* Set up dual prefixes */ 130 131 *temp_ptr++ = AML_DUAL_NAME_PREFIX; 132 } 133 134 /* 135 * Terminate string following prefixes. acpi_ex_name_segment() will 136 * append the segment(s) 137 */ 138 *temp_ptr = 0; 139 140 return_PTR(name_string); 141 } 142 143 /******************************************************************************* 144 * 145 * FUNCTION: acpi_ex_name_segment 146 * 147 * PARAMETERS: in_aml_address - Pointer to the name in the AML code 148 * name_string - Where to return the name. The name is appended 149 * to any existing string to form a namepath 150 * 151 * RETURN: Status 152 * 153 * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream 154 * 155 ******************************************************************************/ 156 157 static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) 158 { 159 char *aml_address = (void *)*in_aml_address; 160 acpi_status status = AE_OK; 161 u32 index; 162 char char_buf[5]; 163 164 ACPI_FUNCTION_TRACE(ex_name_segment); 165 166 /* 167 * If first character is a digit, then we know that we aren't looking 168 * at a valid name segment 169 */ 170 char_buf[0] = *aml_address; 171 172 if ('0' <= char_buf[0] && char_buf[0] <= '9') { 173 ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0])); 174 return_ACPI_STATUS(AE_CTRL_PENDING); 175 } 176 177 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n")); 178 179 for (index = 0; 180 (index < ACPI_NAME_SIZE) 181 && (acpi_ut_valid_name_char(*aml_address, 0)); index++) { 182 char_buf[index] = *aml_address++; 183 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); 184 } 185 186 /* Valid name segment */ 187 188 if (index == 4) { 189 190 /* Found 4 valid characters */ 191 192 char_buf[4] = '\0'; 193 194 if (name_string) { 195 strcat(name_string, char_buf); 196 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 197 "Appended to - %s\n", name_string)); 198 } else { 199 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 200 "No Name string - %s\n", char_buf)); 201 } 202 } else if (index == 0) { 203 /* 204 * First character was not a valid name character, 205 * so we are looking at something other than a name. 206 */ 207 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 208 "Leading character is not alpha: %02Xh (not a name)\n", 209 char_buf[0])); 210 status = AE_CTRL_PENDING; 211 } else { 212 /* 213 * Segment started with one or more valid characters, but fewer than 214 * the required 4 215 */ 216 status = AE_AML_BAD_NAME; 217 ACPI_ERROR((AE_INFO, 218 "Bad character 0x%02x in name, at %p", 219 *aml_address, aml_address)); 220 } 221 222 *in_aml_address = ACPI_CAST_PTR(u8, aml_address); 223 return_ACPI_STATUS(status); 224 } 225 226 /******************************************************************************* 227 * 228 * FUNCTION: acpi_ex_get_name_string 229 * 230 * PARAMETERS: data_type - Object type to be associated with this 231 * name 232 * in_aml_address - Pointer to the namestring in the AML code 233 * out_name_string - Where the namestring is returned 234 * out_name_length - Length of the returned string 235 * 236 * RETURN: Status, namestring and length 237 * 238 * DESCRIPTION: Extract a full namepath from the AML byte stream, 239 * including any prefixes. 240 * 241 ******************************************************************************/ 242 243 acpi_status 244 acpi_ex_get_name_string(acpi_object_type data_type, 245 u8 * in_aml_address, 246 char **out_name_string, u32 * out_name_length) 247 { 248 acpi_status status = AE_OK; 249 u8 *aml_address = in_aml_address; 250 char *name_string = NULL; 251 u32 num_segments; 252 u32 prefix_count = 0; 253 u8 has_prefix = FALSE; 254 255 ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address); 256 257 if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || 258 ACPI_TYPE_LOCAL_BANK_FIELD == data_type || 259 ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { 260 261 /* Disallow prefixes for types associated with field_unit names */ 262 263 name_string = acpi_ex_allocate_name_string(0, 1); 264 if (!name_string) { 265 status = AE_NO_MEMORY; 266 } else { 267 status = 268 acpi_ex_name_segment(&aml_address, name_string); 269 } 270 } else { 271 /* 272 * data_type is not a field name. 273 * Examine first character of name for root or parent prefix operators 274 */ 275 switch (*aml_address) { 276 case AML_ROOT_PREFIX: 277 278 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, 279 "RootPrefix(\\) at %p\n", 280 aml_address)); 281 282 /* 283 * Remember that we have a root_prefix -- 284 * see comment in acpi_ex_allocate_name_string() 285 */ 286 aml_address++; 287 prefix_count = ACPI_UINT32_MAX; 288 has_prefix = TRUE; 289 break; 290 291 case AML_PARENT_PREFIX: 292 293 /* Increment past possibly multiple parent prefixes */ 294 295 do { 296 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, 297 "ParentPrefix (^) at %p\n", 298 aml_address)); 299 300 aml_address++; 301 prefix_count++; 302 303 } while (*aml_address == AML_PARENT_PREFIX); 304 305 has_prefix = TRUE; 306 break; 307 308 default: 309 310 /* Not a prefix character */ 311 312 break; 313 } 314 315 /* Examine first character of name for name segment prefix operator */ 316 317 switch (*aml_address) { 318 case AML_DUAL_NAME_PREFIX: 319 320 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, 321 "DualNamePrefix at %p\n", 322 aml_address)); 323 324 aml_address++; 325 name_string = 326 acpi_ex_allocate_name_string(prefix_count, 2); 327 if (!name_string) { 328 status = AE_NO_MEMORY; 329 break; 330 } 331 332 /* Indicate that we processed a prefix */ 333 334 has_prefix = TRUE; 335 336 status = 337 acpi_ex_name_segment(&aml_address, name_string); 338 if (ACPI_SUCCESS(status)) { 339 status = 340 acpi_ex_name_segment(&aml_address, 341 name_string); 342 } 343 break; 344 345 case AML_MULTI_NAME_PREFIX: 346 347 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, 348 "MultiNamePrefix at %p\n", 349 aml_address)); 350 351 /* Fetch count of segments remaining in name path */ 352 353 aml_address++; 354 num_segments = *aml_address; 355 356 name_string = 357 acpi_ex_allocate_name_string(prefix_count, 358 num_segments); 359 if (!name_string) { 360 status = AE_NO_MEMORY; 361 break; 362 } 363 364 /* Indicate that we processed a prefix */ 365 366 aml_address++; 367 has_prefix = TRUE; 368 369 while (num_segments && 370 (status = 371 acpi_ex_name_segment(&aml_address, 372 name_string)) == AE_OK) { 373 num_segments--; 374 } 375 376 break; 377 378 case 0: 379 380 /* null_name valid as of 8-12-98 ASL/AML Grammar Update */ 381 382 if (prefix_count == ACPI_UINT32_MAX) { 383 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 384 "NameSeg is \"\\\" followed by NULL\n")); 385 } 386 387 /* Consume the NULL byte */ 388 389 aml_address++; 390 name_string = 391 acpi_ex_allocate_name_string(prefix_count, 0); 392 if (!name_string) { 393 status = AE_NO_MEMORY; 394 break; 395 } 396 397 break; 398 399 default: 400 401 /* Name segment string */ 402 403 name_string = 404 acpi_ex_allocate_name_string(prefix_count, 1); 405 if (!name_string) { 406 status = AE_NO_MEMORY; 407 break; 408 } 409 410 status = 411 acpi_ex_name_segment(&aml_address, name_string); 412 break; 413 } 414 } 415 416 if (AE_CTRL_PENDING == status && has_prefix) { 417 418 /* Ran out of segments after processing a prefix */ 419 420 ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string)); 421 status = AE_AML_BAD_NAME; 422 } 423 424 if (ACPI_FAILURE(status)) { 425 if (name_string) { 426 ACPI_FREE(name_string); 427 } 428 return_ACPI_STATUS(status); 429 } 430 431 *out_name_string = name_string; 432 *out_name_length = (u32) (aml_address - in_aml_address); 433 434 return_ACPI_STATUS(status); 435 } 436