1 /****************************************************************************** 2 * 3 * Module Name: exnames - interpreter/scanner name load/execute 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 #define __EXNAMES_C__ 45 46 #include "acpi.h" 47 #include "accommon.h" 48 #include "acinterp.h" 49 #include "amlcode.h" 50 51 #define _COMPONENT ACPI_EXECUTER 52 ACPI_MODULE_NAME ("exnames") 53 54 /* Local prototypes */ 55 56 static char * 57 AcpiExAllocateNameString ( 58 UINT32 PrefixCount, 59 UINT32 NumNameSegs); 60 61 static ACPI_STATUS 62 AcpiExNameSegment ( 63 UINT8 **InAmlAddress, 64 char *NameString); 65 66 67 /******************************************************************************* 68 * 69 * FUNCTION: AcpiExAllocateNameString 70 * 71 * PARAMETERS: PrefixCount - Count of parent levels. Special cases: 72 * (-1)==root, 0==none 73 * NumNameSegs - count of 4-character name segments 74 * 75 * RETURN: A pointer to the allocated string segment. This segment must 76 * be deleted by the caller. 77 * 78 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name 79 * string is long enough, and set up prefix if any. 80 * 81 ******************************************************************************/ 82 83 static char * 84 AcpiExAllocateNameString ( 85 UINT32 PrefixCount, 86 UINT32 NumNameSegs) 87 { 88 char *TempPtr; 89 char *NameString; 90 UINT32 SizeNeeded; 91 92 ACPI_FUNCTION_TRACE (ExAllocateNameString); 93 94 95 /* 96 * Allow room for all \ and ^ prefixes, all segments and a MultiNamePrefix. 97 * Also, one byte for the null terminator. 98 * This may actually be somewhat longer than needed. 99 */ 100 if (PrefixCount == ACPI_UINT32_MAX) 101 { 102 /* Special case for root */ 103 104 SizeNeeded = 1 + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1; 105 } 106 else 107 { 108 SizeNeeded = PrefixCount + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1; 109 } 110 111 /* 112 * Allocate a buffer for the name. 113 * This buffer must be deleted by the caller! 114 */ 115 NameString = ACPI_ALLOCATE (SizeNeeded); 116 if (!NameString) 117 { 118 ACPI_ERROR ((AE_INFO, 119 "Could not allocate size %u", SizeNeeded)); 120 return_PTR (NULL); 121 } 122 123 TempPtr = NameString; 124 125 /* Set up Root or Parent prefixes if needed */ 126 127 if (PrefixCount == ACPI_UINT32_MAX) 128 { 129 *TempPtr++ = AML_ROOT_PREFIX; 130 } 131 else 132 { 133 while (PrefixCount--) 134 { 135 *TempPtr++ = AML_PARENT_PREFIX; 136 } 137 } 138 139 140 /* Set up Dual or Multi prefixes if needed */ 141 142 if (NumNameSegs > 2) 143 { 144 /* Set up multi prefixes */ 145 146 *TempPtr++ = AML_MULTI_NAME_PREFIX_OP; 147 *TempPtr++ = (char) NumNameSegs; 148 } 149 else if (2 == NumNameSegs) 150 { 151 /* Set up dual prefixes */ 152 153 *TempPtr++ = AML_DUAL_NAME_PREFIX; 154 } 155 156 /* 157 * Terminate string following prefixes. AcpiExNameSegment() will 158 * append the segment(s) 159 */ 160 *TempPtr = 0; 161 162 return_PTR (NameString); 163 } 164 165 /******************************************************************************* 166 * 167 * FUNCTION: AcpiExNameSegment 168 * 169 * PARAMETERS: InAmlAddress - Pointer to the name in the AML code 170 * NameString - Where to return the name. The name is appended 171 * to any existing string to form a namepath 172 * 173 * RETURN: Status 174 * 175 * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream 176 * 177 ******************************************************************************/ 178 179 static ACPI_STATUS 180 AcpiExNameSegment ( 181 UINT8 **InAmlAddress, 182 char *NameString) 183 { 184 char *AmlAddress = (void *) *InAmlAddress; 185 ACPI_STATUS Status = AE_OK; 186 UINT32 Index; 187 char CharBuf[5]; 188 189 190 ACPI_FUNCTION_TRACE (ExNameSegment); 191 192 193 /* 194 * If first character is a digit, then we know that we aren't looking at a 195 * valid name segment 196 */ 197 CharBuf[0] = *AmlAddress; 198 199 if ('0' <= CharBuf[0] && CharBuf[0] <= '9') 200 { 201 ACPI_ERROR ((AE_INFO, "Invalid leading digit: %c", CharBuf[0])); 202 return_ACPI_STATUS (AE_CTRL_PENDING); 203 } 204 205 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n")); 206 207 for (Index = 0; 208 (Index < ACPI_NAME_SIZE) && (AcpiUtValidAcpiChar (*AmlAddress, 0)); 209 Index++) 210 { 211 CharBuf[Index] = *AmlAddress++; 212 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", CharBuf[Index])); 213 } 214 215 216 /* Valid name segment */ 217 218 if (Index == 4) 219 { 220 /* Found 4 valid characters */ 221 222 CharBuf[4] = '\0'; 223 224 if (NameString) 225 { 226 ACPI_STRCAT (NameString, CharBuf); 227 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 228 "Appended to - %s\n", NameString)); 229 } 230 else 231 { 232 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 233 "No Name string - %s\n", CharBuf)); 234 } 235 } 236 else if (Index == 0) 237 { 238 /* 239 * First character was not a valid name character, 240 * so we are looking at something other than a name. 241 */ 242 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 243 "Leading character is not alpha: %02Xh (not a name)\n", 244 CharBuf[0])); 245 Status = AE_CTRL_PENDING; 246 } 247 else 248 { 249 /* 250 * Segment started with one or more valid characters, but fewer than 251 * the required 4 252 */ 253 Status = AE_AML_BAD_NAME; 254 ACPI_ERROR ((AE_INFO, 255 "Bad character 0x%02x in name, at %p", 256 *AmlAddress, AmlAddress)); 257 } 258 259 *InAmlAddress = ACPI_CAST_PTR (UINT8, AmlAddress); 260 return_ACPI_STATUS (Status); 261 } 262 263 264 /******************************************************************************* 265 * 266 * FUNCTION: AcpiExGetNameString 267 * 268 * PARAMETERS: DataType - Object type to be associated with this 269 * name 270 * InAmlAddress - Pointer to the namestring in the AML code 271 * OutNameString - Where the namestring is returned 272 * OutNameLength - Length of the returned string 273 * 274 * RETURN: Status, namestring and length 275 * 276 * DESCRIPTION: Extract a full namepath from the AML byte stream, 277 * including any prefixes. 278 * 279 ******************************************************************************/ 280 281 ACPI_STATUS 282 AcpiExGetNameString ( 283 ACPI_OBJECT_TYPE DataType, 284 UINT8 *InAmlAddress, 285 char **OutNameString, 286 UINT32 *OutNameLength) 287 { 288 ACPI_STATUS Status = AE_OK; 289 UINT8 *AmlAddress = InAmlAddress; 290 char *NameString = NULL; 291 UINT32 NumSegments; 292 UINT32 PrefixCount = 0; 293 BOOLEAN HasPrefix = FALSE; 294 295 296 ACPI_FUNCTION_TRACE_PTR (ExGetNameString, AmlAddress); 297 298 299 if (ACPI_TYPE_LOCAL_REGION_FIELD == DataType || 300 ACPI_TYPE_LOCAL_BANK_FIELD == DataType || 301 ACPI_TYPE_LOCAL_INDEX_FIELD == DataType) 302 { 303 /* Disallow prefixes for types associated with FieldUnit names */ 304 305 NameString = AcpiExAllocateNameString (0, 1); 306 if (!NameString) 307 { 308 Status = AE_NO_MEMORY; 309 } 310 else 311 { 312 Status = AcpiExNameSegment (&AmlAddress, NameString); 313 } 314 } 315 else 316 { 317 /* 318 * DataType is not a field name. 319 * Examine first character of name for root or parent prefix operators 320 */ 321 switch (*AmlAddress) 322 { 323 case AML_ROOT_PREFIX: 324 325 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "RootPrefix(\\) at %p\n", 326 AmlAddress)); 327 328 /* 329 * Remember that we have a RootPrefix -- 330 * see comment in AcpiExAllocateNameString() 331 */ 332 AmlAddress++; 333 PrefixCount = ACPI_UINT32_MAX; 334 HasPrefix = TRUE; 335 break; 336 337 case AML_PARENT_PREFIX: 338 339 /* Increment past possibly multiple parent prefixes */ 340 341 do 342 { 343 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n", 344 AmlAddress)); 345 346 AmlAddress++; 347 PrefixCount++; 348 349 } while (*AmlAddress == AML_PARENT_PREFIX); 350 351 HasPrefix = TRUE; 352 break; 353 354 default: 355 356 /* Not a prefix character */ 357 358 break; 359 } 360 361 /* Examine first character of name for name segment prefix operator */ 362 363 switch (*AmlAddress) 364 { 365 case AML_DUAL_NAME_PREFIX: 366 367 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n", 368 AmlAddress)); 369 370 AmlAddress++; 371 NameString = AcpiExAllocateNameString (PrefixCount, 2); 372 if (!NameString) 373 { 374 Status = AE_NO_MEMORY; 375 break; 376 } 377 378 /* Indicate that we processed a prefix */ 379 380 HasPrefix = TRUE; 381 382 Status = AcpiExNameSegment (&AmlAddress, NameString); 383 if (ACPI_SUCCESS (Status)) 384 { 385 Status = AcpiExNameSegment (&AmlAddress, NameString); 386 } 387 break; 388 389 case AML_MULTI_NAME_PREFIX_OP: 390 391 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n", 392 AmlAddress)); 393 394 /* Fetch count of segments remaining in name path */ 395 396 AmlAddress++; 397 NumSegments = *AmlAddress; 398 399 NameString = AcpiExAllocateNameString (PrefixCount, NumSegments); 400 if (!NameString) 401 { 402 Status = AE_NO_MEMORY; 403 break; 404 } 405 406 /* Indicate that we processed a prefix */ 407 408 AmlAddress++; 409 HasPrefix = TRUE; 410 411 while (NumSegments && 412 (Status = AcpiExNameSegment (&AmlAddress, NameString)) == 413 AE_OK) 414 { 415 NumSegments--; 416 } 417 418 break; 419 420 case 0: 421 422 /* NullName valid as of 8-12-98 ASL/AML Grammar Update */ 423 424 if (PrefixCount == ACPI_UINT32_MAX) 425 { 426 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 427 "NameSeg is \"\\\" followed by NULL\n")); 428 } 429 430 /* Consume the NULL byte */ 431 432 AmlAddress++; 433 NameString = AcpiExAllocateNameString (PrefixCount, 0); 434 if (!NameString) 435 { 436 Status = AE_NO_MEMORY; 437 break; 438 } 439 440 break; 441 442 default: 443 444 /* Name segment string */ 445 446 NameString = AcpiExAllocateNameString (PrefixCount, 1); 447 if (!NameString) 448 { 449 Status = AE_NO_MEMORY; 450 break; 451 } 452 453 Status = AcpiExNameSegment (&AmlAddress, NameString); 454 break; 455 } 456 } 457 458 if (AE_CTRL_PENDING == Status && HasPrefix) 459 { 460 /* Ran out of segments after processing a prefix */ 461 462 ACPI_ERROR ((AE_INFO, 463 "Malformed Name at %p", NameString)); 464 Status = AE_AML_BAD_NAME; 465 } 466 467 if (ACPI_FAILURE (Status)) 468 { 469 if (NameString) 470 { 471 ACPI_FREE (NameString); 472 } 473 return_ACPI_STATUS (Status); 474 } 475 476 *OutNameString = NameString; 477 *OutNameLength = (UINT32) (AmlAddress - InAmlAddress); 478 479 return_ACPI_STATUS (Status); 480 }