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