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