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