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.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; 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 for (Index = 0; 205 (Index < ACPI_NAME_SIZE) && (AcpiUtValidNameChar (*AmlAddress, 0)); 206 Index++) 207 { 208 CharBuf[Index] = *AmlAddress++; 209 } 210 211 212 /* Valid name segment */ 213 214 if (Index == 4) 215 { 216 /* Found 4 valid characters */ 217 218 CharBuf[4] = '\0'; 219 220 if (NameString) 221 { 222 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 223 "Appending NameSeg %s\n", CharBuf)); 224 strcat (NameString, CharBuf); 225 } 226 else 227 { 228 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 229 "No Name string - %s\n", CharBuf)); 230 } 231 } 232 else if (Index == 0) 233 { 234 /* 235 * First character was not a valid name character, 236 * so we are looking at something other than a name. 237 */ 238 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 239 "Leading character is not alpha: %02Xh (not a name)\n", 240 CharBuf[0])); 241 Status = AE_CTRL_PENDING; 242 } 243 else 244 { 245 /* 246 * Segment started with one or more valid characters, but fewer than 247 * the required 4 248 */ 249 Status = AE_AML_BAD_NAME; 250 ACPI_ERROR ((AE_INFO, 251 "Bad character 0x%02x in name, at %p", 252 *AmlAddress, AmlAddress)); 253 } 254 255 *InAmlAddress = ACPI_CAST_PTR (UINT8, AmlAddress); 256 return_ACPI_STATUS (Status); 257 } 258 259 260 /******************************************************************************* 261 * 262 * FUNCTION: AcpiExGetNameString 263 * 264 * PARAMETERS: DataType - Object type to be associated with this 265 * name 266 * InAmlAddress - Pointer to the namestring in the AML code 267 * OutNameString - Where the namestring is returned 268 * OutNameLength - Length of the returned string 269 * 270 * RETURN: Status, namestring and length 271 * 272 * DESCRIPTION: Extract a full namepath from the AML byte stream, 273 * including any prefixes. 274 * 275 ******************************************************************************/ 276 277 ACPI_STATUS 278 AcpiExGetNameString ( 279 ACPI_OBJECT_TYPE DataType, 280 UINT8 *InAmlAddress, 281 char **OutNameString, 282 UINT32 *OutNameLength) 283 { 284 ACPI_STATUS Status = AE_OK; 285 UINT8 *AmlAddress = InAmlAddress; 286 char *NameString = NULL; 287 UINT32 NumSegments; 288 UINT32 PrefixCount = 0; 289 BOOLEAN HasPrefix = FALSE; 290 291 292 ACPI_FUNCTION_TRACE_PTR (ExGetNameString, AmlAddress); 293 294 295 if (ACPI_TYPE_LOCAL_REGION_FIELD == DataType || 296 ACPI_TYPE_LOCAL_BANK_FIELD == DataType || 297 ACPI_TYPE_LOCAL_INDEX_FIELD == DataType) 298 { 299 /* Disallow prefixes for types associated with FieldUnit names */ 300 301 NameString = AcpiExAllocateNameString (0, 1); 302 if (!NameString) 303 { 304 Status = AE_NO_MEMORY; 305 } 306 else 307 { 308 Status = AcpiExNameSegment (&AmlAddress, NameString); 309 } 310 } 311 else 312 { 313 /* 314 * DataType is not a field name. 315 * Examine first character of name for root or parent prefix operators 316 */ 317 switch (*AmlAddress) 318 { 319 case AML_ROOT_PREFIX: 320 321 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "RootPrefix(\\) at %p\n", 322 AmlAddress)); 323 324 /* 325 * Remember that we have a RootPrefix -- 326 * see comment in AcpiExAllocateNameString() 327 */ 328 AmlAddress++; 329 PrefixCount = ACPI_UINT32_MAX; 330 HasPrefix = TRUE; 331 break; 332 333 case AML_PARENT_PREFIX: 334 335 /* Increment past possibly multiple parent prefixes */ 336 337 do 338 { 339 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n", 340 AmlAddress)); 341 342 AmlAddress++; 343 PrefixCount++; 344 345 } while (*AmlAddress == AML_PARENT_PREFIX); 346 347 HasPrefix = TRUE; 348 break; 349 350 default: 351 352 /* Not a prefix character */ 353 354 break; 355 } 356 357 /* Examine first character of name for name segment prefix operator */ 358 359 switch (*AmlAddress) 360 { 361 case AML_DUAL_NAME_PREFIX: 362 363 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n", 364 AmlAddress)); 365 366 AmlAddress++; 367 NameString = AcpiExAllocateNameString (PrefixCount, 2); 368 if (!NameString) 369 { 370 Status = AE_NO_MEMORY; 371 break; 372 } 373 374 /* Indicate that we processed a prefix */ 375 376 HasPrefix = TRUE; 377 378 Status = AcpiExNameSegment (&AmlAddress, NameString); 379 if (ACPI_SUCCESS (Status)) 380 { 381 Status = AcpiExNameSegment (&AmlAddress, NameString); 382 } 383 break; 384 385 case AML_MULTI_NAME_PREFIX: 386 387 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n", 388 AmlAddress)); 389 390 /* Fetch count of segments remaining in name path */ 391 392 AmlAddress++; 393 NumSegments = *AmlAddress; 394 395 NameString = AcpiExAllocateNameString ( 396 PrefixCount, NumSegments); 397 if (!NameString) 398 { 399 Status = AE_NO_MEMORY; 400 break; 401 } 402 403 /* Indicate that we processed a prefix */ 404 405 AmlAddress++; 406 HasPrefix = TRUE; 407 408 while (NumSegments && 409 (Status = AcpiExNameSegment (&AmlAddress, NameString)) == 410 AE_OK) 411 { 412 NumSegments--; 413 } 414 415 break; 416 417 case 0: 418 419 /* NullName valid as of 8-12-98 ASL/AML Grammar Update */ 420 421 if (PrefixCount == ACPI_UINT32_MAX) 422 { 423 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 424 "NameSeg is \"\\\" followed by NULL\n")); 425 } 426 427 /* Consume the NULL byte */ 428 429 AmlAddress++; 430 NameString = AcpiExAllocateNameString (PrefixCount, 0); 431 if (!NameString) 432 { 433 Status = AE_NO_MEMORY; 434 break; 435 } 436 437 break; 438 439 default: 440 441 /* Name segment string */ 442 443 NameString = AcpiExAllocateNameString (PrefixCount, 1); 444 if (!NameString) 445 { 446 Status = AE_NO_MEMORY; 447 break; 448 } 449 450 Status = AcpiExNameSegment (&AmlAddress, NameString); 451 break; 452 } 453 } 454 455 if (AE_CTRL_PENDING == Status && HasPrefix) 456 { 457 /* Ran out of segments after processing a prefix */ 458 459 ACPI_ERROR ((AE_INFO, 460 "Malformed Name at %p", NameString)); 461 Status = AE_AML_BAD_NAME; 462 } 463 464 if (ACPI_FAILURE (Status)) 465 { 466 if (NameString) 467 { 468 ACPI_FREE (NameString); 469 } 470 return_ACPI_STATUS (Status); 471 } 472 473 *OutNameString = NameString; 474 *OutNameLength = (UINT32) (AmlAddress - InAmlAddress); 475 476 return_ACPI_STATUS (Status); 477 } 478