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