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 <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/acinterp.h> 49 #include <contrib/dev/acpica/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 338 case AML_PARENT_PREFIX: 339 340 /* Increment past possibly multiple parent prefixes */ 341 342 do 343 { 344 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n", 345 AmlAddress)); 346 347 AmlAddress++; 348 PrefixCount++; 349 350 } while (*AmlAddress == AML_PARENT_PREFIX); 351 352 HasPrefix = TRUE; 353 break; 354 355 356 default: 357 358 /* Not a prefix character */ 359 360 break; 361 } 362 363 /* Examine first character of name for name segment prefix operator */ 364 365 switch (*AmlAddress) 366 { 367 case AML_DUAL_NAME_PREFIX: 368 369 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n", 370 AmlAddress)); 371 372 AmlAddress++; 373 NameString = AcpiExAllocateNameString (PrefixCount, 2); 374 if (!NameString) 375 { 376 Status = AE_NO_MEMORY; 377 break; 378 } 379 380 /* Indicate that we processed a prefix */ 381 382 HasPrefix = TRUE; 383 384 Status = AcpiExNameSegment (&AmlAddress, NameString); 385 if (ACPI_SUCCESS (Status)) 386 { 387 Status = AcpiExNameSegment (&AmlAddress, NameString); 388 } 389 break; 390 391 392 case AML_MULTI_NAME_PREFIX_OP: 393 394 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n", 395 AmlAddress)); 396 397 /* Fetch count of segments remaining in name path */ 398 399 AmlAddress++; 400 NumSegments = *AmlAddress; 401 402 NameString = AcpiExAllocateNameString (PrefixCount, NumSegments); 403 if (!NameString) 404 { 405 Status = AE_NO_MEMORY; 406 break; 407 } 408 409 /* Indicate that we processed a prefix */ 410 411 AmlAddress++; 412 HasPrefix = TRUE; 413 414 while (NumSegments && 415 (Status = AcpiExNameSegment (&AmlAddress, NameString)) == 416 AE_OK) 417 { 418 NumSegments--; 419 } 420 421 break; 422 423 424 case 0: 425 426 /* NullName valid as of 8-12-98 ASL/AML Grammar Update */ 427 428 if (PrefixCount == ACPI_UINT32_MAX) 429 { 430 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 431 "NameSeg is \"\\\" followed by NULL\n")); 432 } 433 434 /* Consume the NULL byte */ 435 436 AmlAddress++; 437 NameString = AcpiExAllocateNameString (PrefixCount, 0); 438 if (!NameString) 439 { 440 Status = AE_NO_MEMORY; 441 break; 442 } 443 444 break; 445 446 447 default: 448 449 /* Name segment string */ 450 451 NameString = AcpiExAllocateNameString (PrefixCount, 1); 452 if (!NameString) 453 { 454 Status = AE_NO_MEMORY; 455 break; 456 } 457 458 Status = AcpiExNameSegment (&AmlAddress, NameString); 459 break; 460 } 461 } 462 463 if (AE_CTRL_PENDING == Status && HasPrefix) 464 { 465 /* Ran out of segments after processing a prefix */ 466 467 ACPI_ERROR ((AE_INFO, 468 "Malformed Name at %p", NameString)); 469 Status = AE_AML_BAD_NAME; 470 } 471 472 if (ACPI_FAILURE (Status)) 473 { 474 if (NameString) 475 { 476 ACPI_FREE (NameString); 477 } 478 return_ACPI_STATUS (Status); 479 } 480 481 *OutNameString = NameString; 482 *OutNameLength = (UINT32) (AmlAddress - InAmlAddress); 483 484 return_ACPI_STATUS (Status); 485 } 486