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