1 /******************************************************************************* 2 * 3 * Module Name: nsnames - Name manipulation and search 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2019, 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 "amlcode.h" 47 #include "acnamesp.h" 48 49 50 #define _COMPONENT ACPI_NAMESPACE 51 ACPI_MODULE_NAME ("nsnames") 52 53 /* Local Prototypes */ 54 55 static void 56 AcpiNsNormalizePathname ( 57 char *OriginalPath); 58 59 60 /******************************************************************************* 61 * 62 * FUNCTION: AcpiNsGetExternalPathname 63 * 64 * PARAMETERS: Node - Namespace node whose pathname is needed 65 * 66 * RETURN: Pointer to storage containing the fully qualified name of 67 * the node, In external format (name segments separated by path 68 * separators.) 69 * 70 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually 71 * for error and debug statements. 72 * 73 ******************************************************************************/ 74 75 char * 76 AcpiNsGetExternalPathname ( 77 ACPI_NAMESPACE_NODE *Node) 78 { 79 char *NameBuffer; 80 81 82 ACPI_FUNCTION_TRACE_PTR (NsGetExternalPathname, Node); 83 84 85 NameBuffer = AcpiNsGetNormalizedPathname (Node, FALSE); 86 return_PTR (NameBuffer); 87 } 88 89 90 /******************************************************************************* 91 * 92 * FUNCTION: AcpiNsGetPathnameLength 93 * 94 * PARAMETERS: Node - Namespace node 95 * 96 * RETURN: Length of path, including prefix 97 * 98 * DESCRIPTION: Get the length of the pathname string for this node 99 * 100 ******************************************************************************/ 101 102 ACPI_SIZE 103 AcpiNsGetPathnameLength ( 104 ACPI_NAMESPACE_NODE *Node) 105 { 106 ACPI_SIZE Size; 107 108 109 /* Validate the Node */ 110 111 if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) 112 { 113 ACPI_ERROR ((AE_INFO, 114 "Invalid/cached reference target node: %p, descriptor type %d", 115 Node, ACPI_GET_DESCRIPTOR_TYPE (Node))); 116 return (0); 117 } 118 119 Size = AcpiNsBuildNormalizedPath (Node, NULL, 0, FALSE); 120 return (Size); 121 } 122 123 124 /******************************************************************************* 125 * 126 * FUNCTION: AcpiNsHandleToName 127 * 128 * PARAMETERS: TargetHandle - Handle of named object whose name is 129 * to be found 130 * Buffer - Where the name is returned 131 * 132 * RETURN: Status, Buffer is filled with name if status is AE_OK 133 * 134 * DESCRIPTION: Build and return a full namespace name 135 * 136 ******************************************************************************/ 137 138 ACPI_STATUS 139 AcpiNsHandleToName ( 140 ACPI_HANDLE TargetHandle, 141 ACPI_BUFFER *Buffer) 142 { 143 ACPI_STATUS Status; 144 ACPI_NAMESPACE_NODE *Node; 145 const char *NodeName; 146 147 148 ACPI_FUNCTION_TRACE_PTR (NsHandleToName, TargetHandle); 149 150 151 Node = AcpiNsValidateHandle (TargetHandle); 152 if (!Node) 153 { 154 return_ACPI_STATUS (AE_BAD_PARAMETER); 155 } 156 157 /* Validate/Allocate/Clear caller buffer */ 158 159 Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH); 160 if (ACPI_FAILURE (Status)) 161 { 162 return_ACPI_STATUS (Status); 163 } 164 165 /* Just copy the ACPI name from the Node and zero terminate it */ 166 167 NodeName = AcpiUtGetNodeName (Node); 168 ACPI_COPY_NAMESEG (Buffer->Pointer, NodeName); 169 ((char *) Buffer->Pointer) [ACPI_NAMESEG_SIZE] = 0; 170 171 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%4.4s\n", (char *) Buffer->Pointer)); 172 return_ACPI_STATUS (AE_OK); 173 } 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: AcpiNsHandleToPathname 179 * 180 * PARAMETERS: TargetHandle - Handle of named object whose name is 181 * to be found 182 * Buffer - Where the pathname is returned 183 * NoTrailing - Remove trailing '_' for each name 184 * segment 185 * 186 * RETURN: Status, Buffer is filled with pathname if status is AE_OK 187 * 188 * DESCRIPTION: Build and return a full namespace pathname 189 * 190 ******************************************************************************/ 191 192 ACPI_STATUS 193 AcpiNsHandleToPathname ( 194 ACPI_HANDLE TargetHandle, 195 ACPI_BUFFER *Buffer, 196 BOOLEAN NoTrailing) 197 { 198 ACPI_STATUS Status; 199 ACPI_NAMESPACE_NODE *Node; 200 ACPI_SIZE RequiredSize; 201 202 203 ACPI_FUNCTION_TRACE_PTR (NsHandleToPathname, TargetHandle); 204 205 206 Node = AcpiNsValidateHandle (TargetHandle); 207 if (!Node) 208 { 209 return_ACPI_STATUS (AE_BAD_PARAMETER); 210 } 211 212 /* Determine size required for the caller buffer */ 213 214 RequiredSize = AcpiNsBuildNormalizedPath (Node, NULL, 0, NoTrailing); 215 if (!RequiredSize) 216 { 217 return_ACPI_STATUS (AE_BAD_PARAMETER); 218 } 219 220 /* Validate/Allocate/Clear caller buffer */ 221 222 Status = AcpiUtInitializeBuffer (Buffer, RequiredSize); 223 if (ACPI_FAILURE (Status)) 224 { 225 return_ACPI_STATUS (Status); 226 } 227 228 /* Build the path in the caller buffer */ 229 230 (void) AcpiNsBuildNormalizedPath (Node, Buffer->Pointer, 231 RequiredSize, NoTrailing); 232 233 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X]\n", 234 (char *) Buffer->Pointer, (UINT32) RequiredSize)); 235 return_ACPI_STATUS (AE_OK); 236 } 237 238 239 /******************************************************************************* 240 * 241 * FUNCTION: AcpiNsBuildNormalizedPath 242 * 243 * PARAMETERS: Node - Namespace node 244 * FullPath - Where the path name is returned 245 * PathSize - Size of returned path name buffer 246 * NoTrailing - Remove trailing '_' from each name segment 247 * 248 * RETURN: Return 1 if the AML path is empty, otherwise returning (length 249 * of pathname + 1) which means the 'FullPath' contains a trailing 250 * null. 251 * 252 * DESCRIPTION: Build and return a full namespace pathname. 253 * Note that if the size of 'FullPath' isn't large enough to 254 * contain the namespace node's path name, the actual required 255 * buffer length is returned, and it should be greater than 256 * 'PathSize'. So callers are able to check the returning value 257 * to determine the buffer size of 'FullPath'. 258 * 259 ******************************************************************************/ 260 261 UINT32 262 AcpiNsBuildNormalizedPath ( 263 ACPI_NAMESPACE_NODE *Node, 264 char *FullPath, 265 UINT32 PathSize, 266 BOOLEAN NoTrailing) 267 { 268 UINT32 Length = 0, i; 269 char Name[ACPI_NAMESEG_SIZE]; 270 BOOLEAN DoNoTrailing; 271 char c, *Left, *Right; 272 ACPI_NAMESPACE_NODE *NextNode; 273 274 275 ACPI_FUNCTION_TRACE_PTR (NsBuildNormalizedPath, Node); 276 277 278 #define ACPI_PATH_PUT8(Path, Size, Byte, Length) \ 279 do { \ 280 if ((Length) < (Size)) \ 281 { \ 282 (Path)[(Length)] = (Byte); \ 283 } \ 284 (Length)++; \ 285 } while (0) 286 287 /* 288 * Make sure the PathSize is correct, so that we don't need to 289 * validate both FullPath and PathSize. 290 */ 291 if (!FullPath) 292 { 293 PathSize = 0; 294 } 295 296 if (!Node) 297 { 298 goto BuildTrailingNull; 299 } 300 301 NextNode = Node; 302 while (NextNode && NextNode != AcpiGbl_RootNode) 303 { 304 if (NextNode != Node) 305 { 306 ACPI_PATH_PUT8(FullPath, PathSize, AML_DUAL_NAME_PREFIX, Length); 307 } 308 309 ACPI_MOVE_32_TO_32 (Name, &NextNode->Name); 310 DoNoTrailing = NoTrailing; 311 for (i = 0; i < 4; i++) 312 { 313 c = Name[4-i-1]; 314 if (DoNoTrailing && c != '_') 315 { 316 DoNoTrailing = FALSE; 317 } 318 if (!DoNoTrailing) 319 { 320 ACPI_PATH_PUT8(FullPath, PathSize, c, Length); 321 } 322 } 323 324 NextNode = NextNode->Parent; 325 } 326 327 ACPI_PATH_PUT8(FullPath, PathSize, AML_ROOT_PREFIX, Length); 328 329 /* Reverse the path string */ 330 331 if (Length <= PathSize) 332 { 333 Left = FullPath; 334 Right = FullPath+Length - 1; 335 336 while (Left < Right) 337 { 338 c = *Left; 339 *Left++ = *Right; 340 *Right-- = c; 341 } 342 } 343 344 /* Append the trailing null */ 345 346 BuildTrailingNull: 347 ACPI_PATH_PUT8 (FullPath, PathSize, '\0', Length); 348 349 #undef ACPI_PATH_PUT8 350 351 return_UINT32 (Length); 352 } 353 354 355 /******************************************************************************* 356 * 357 * FUNCTION: AcpiNsGetNormalizedPathname 358 * 359 * PARAMETERS: Node - Namespace node whose pathname is needed 360 * NoTrailing - Remove trailing '_' from each name segment 361 * 362 * RETURN: Pointer to storage containing the fully qualified name of 363 * the node, In external format (name segments separated by path 364 * separators.) 365 * 366 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually 367 * for error and debug statements. All trailing '_' will be 368 * removed from the full pathname if 'NoTrailing' is specified.. 369 * 370 ******************************************************************************/ 371 372 char * 373 AcpiNsGetNormalizedPathname ( 374 ACPI_NAMESPACE_NODE *Node, 375 BOOLEAN NoTrailing) 376 { 377 char *NameBuffer; 378 ACPI_SIZE Size; 379 380 381 ACPI_FUNCTION_TRACE_PTR (NsGetNormalizedPathname, Node); 382 383 384 /* Calculate required buffer size based on depth below root */ 385 386 Size = AcpiNsBuildNormalizedPath (Node, NULL, 0, NoTrailing); 387 if (!Size) 388 { 389 return_PTR (NULL); 390 } 391 392 /* Allocate a buffer to be returned to caller */ 393 394 NameBuffer = ACPI_ALLOCATE_ZEROED (Size); 395 if (!NameBuffer) 396 { 397 ACPI_ERROR ((AE_INFO, 398 "Could not allocate %u bytes", (UINT32) Size)); 399 return_PTR (NULL); 400 } 401 402 /* Build the path in the allocated buffer */ 403 404 (void) AcpiNsBuildNormalizedPath (Node, NameBuffer, Size, NoTrailing); 405 406 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, "%s: Path \"%s\"\n", 407 ACPI_GET_FUNCTION_NAME, NameBuffer)); 408 409 return_PTR (NameBuffer); 410 } 411 412 413 /******************************************************************************* 414 * 415 * FUNCTION: AcpiNsBuildPrefixedPathname 416 * 417 * PARAMETERS: PrefixScope - Scope/Path that prefixes the internal path 418 * InternalPath - Name or path of the namespace node 419 * 420 * RETURN: None 421 * 422 * DESCRIPTION: Construct a fully qualified pathname from a concatenation of: 423 * 1) Path associated with the PrefixScope namespace node 424 * 2) External path representation of the Internal path 425 * 426 ******************************************************************************/ 427 428 char * 429 AcpiNsBuildPrefixedPathname ( 430 ACPI_GENERIC_STATE *PrefixScope, 431 const char *InternalPath) 432 { 433 ACPI_STATUS Status; 434 char *FullPath = NULL; 435 char *ExternalPath = NULL; 436 char *PrefixPath = NULL; 437 UINT32 PrefixPathLength = 0; 438 439 440 /* If there is a prefix, get the pathname to it */ 441 442 if (PrefixScope && PrefixScope->Scope.Node) 443 { 444 PrefixPath = AcpiNsGetNormalizedPathname (PrefixScope->Scope.Node, TRUE); 445 if (PrefixPath) 446 { 447 PrefixPathLength = strlen (PrefixPath); 448 } 449 } 450 451 Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, 452 NULL, &ExternalPath); 453 if (ACPI_FAILURE (Status)) 454 { 455 goto Cleanup; 456 } 457 458 /* Merge the prefix path and the path. 2 is for one dot and trailing null */ 459 460 FullPath = ACPI_ALLOCATE_ZEROED ( 461 PrefixPathLength + strlen (ExternalPath) + 2); 462 if (!FullPath) 463 { 464 goto Cleanup; 465 } 466 467 /* Don't merge if the External path is already fully qualified */ 468 469 if (PrefixPath && 470 (*ExternalPath != '\\') && 471 (*ExternalPath != '^')) 472 { 473 strcat (FullPath, PrefixPath); 474 if (PrefixPath[1]) 475 { 476 strcat (FullPath, "."); 477 } 478 } 479 480 AcpiNsNormalizePathname (ExternalPath); 481 strcat (FullPath, ExternalPath); 482 483 Cleanup: 484 if (PrefixPath) 485 { 486 ACPI_FREE (PrefixPath); 487 } 488 if (ExternalPath) 489 { 490 ACPI_FREE (ExternalPath); 491 } 492 493 return (FullPath); 494 } 495 496 497 /******************************************************************************* 498 * 499 * FUNCTION: AcpiNsNormalizePathname 500 * 501 * PARAMETERS: OriginalPath - Path to be normalized, in External format 502 * 503 * RETURN: The original path is processed in-place 504 * 505 * DESCRIPTION: Remove trailing underscores from each element of a path. 506 * 507 * For example: \A___.B___.C___ becomes \A.B.C 508 * 509 ******************************************************************************/ 510 511 static void 512 AcpiNsNormalizePathname ( 513 char *OriginalPath) 514 { 515 char *InputPath = OriginalPath; 516 char *NewPathBuffer; 517 char *NewPath; 518 UINT32 i; 519 520 521 /* Allocate a temp buffer in which to construct the new path */ 522 523 NewPathBuffer = ACPI_ALLOCATE_ZEROED (strlen (InputPath) + 1); 524 NewPath = NewPathBuffer; 525 if (!NewPathBuffer) 526 { 527 return; 528 } 529 530 /* Special characters may appear at the beginning of the path */ 531 532 if (*InputPath == '\\') 533 { 534 *NewPath = *InputPath; 535 NewPath++; 536 InputPath++; 537 } 538 539 while (*InputPath == '^') 540 { 541 *NewPath = *InputPath; 542 NewPath++; 543 InputPath++; 544 } 545 546 /* Remainder of the path */ 547 548 while (*InputPath) 549 { 550 /* Do one nameseg at a time */ 551 552 for (i = 0; (i < ACPI_NAMESEG_SIZE) && *InputPath; i++) 553 { 554 if ((i == 0) || (*InputPath != '_')) /* First char is allowed to be underscore */ 555 { 556 *NewPath = *InputPath; 557 NewPath++; 558 } 559 560 InputPath++; 561 } 562 563 /* Dot means that there are more namesegs to come */ 564 565 if (*InputPath == '.') 566 { 567 *NewPath = *InputPath; 568 NewPath++; 569 InputPath++; 570 } 571 } 572 573 *NewPath = 0; 574 strcpy (OriginalPath, NewPathBuffer); 575 ACPI_FREE (NewPathBuffer); 576 } 577