1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing 5 * parents and siblings and Scope manipulation 6 * 7 * Copyright (C) 2000 - 2023, Intel Corp. 8 * 9 *****************************************************************************/ 10 11 #include <acpi/acpi.h> 12 #include "accommon.h" 13 #include "acnamesp.h" 14 #include "amlcode.h" 15 16 #define _COMPONENT ACPI_NAMESPACE 17 ACPI_MODULE_NAME("nsutils") 18 19 /* Local prototypes */ 20 #ifdef ACPI_OBSOLETE_FUNCTIONS 21 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); 22 #endif 23 24 /******************************************************************************* 25 * 26 * FUNCTION: acpi_ns_print_node_pathname 27 * 28 * PARAMETERS: node - Object 29 * message - Prefix message 30 * 31 * DESCRIPTION: Print an object's full namespace pathname 32 * Manages allocation/freeing of a pathname buffer 33 * 34 ******************************************************************************/ 35 36 void 37 acpi_ns_print_node_pathname(struct acpi_namespace_node *node, 38 const char *message) 39 { 40 struct acpi_buffer buffer; 41 acpi_status status; 42 43 if (!node) { 44 acpi_os_printf("[NULL NAME]"); 45 return; 46 } 47 48 /* Convert handle to full pathname and print it (with supplied message) */ 49 50 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 51 52 status = acpi_ns_handle_to_pathname(node, &buffer, TRUE); 53 if (ACPI_SUCCESS(status)) { 54 if (message) { 55 acpi_os_printf("%s ", message); 56 } 57 58 acpi_os_printf("%s", (char *)buffer.pointer); 59 ACPI_FREE(buffer.pointer); 60 } 61 } 62 63 /******************************************************************************* 64 * 65 * FUNCTION: acpi_ns_get_type 66 * 67 * PARAMETERS: node - Parent Node to be examined 68 * 69 * RETURN: Type field from Node whose handle is passed 70 * 71 * DESCRIPTION: Return the type of a Namespace node 72 * 73 ******************************************************************************/ 74 75 acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) 76 { 77 ACPI_FUNCTION_TRACE(ns_get_type); 78 79 if (!node) { 80 ACPI_WARNING((AE_INFO, "Null Node parameter")); 81 return_UINT8(ACPI_TYPE_ANY); 82 } 83 84 return_UINT8(node->type); 85 } 86 87 /******************************************************************************* 88 * 89 * FUNCTION: acpi_ns_local 90 * 91 * PARAMETERS: type - A namespace object type 92 * 93 * RETURN: LOCAL if names must be found locally in objects of the 94 * passed type, 0 if enclosing scopes should be searched 95 * 96 * DESCRIPTION: Returns scope rule for the given object type. 97 * 98 ******************************************************************************/ 99 100 u32 acpi_ns_local(acpi_object_type type) 101 { 102 ACPI_FUNCTION_TRACE(ns_local); 103 104 if (!acpi_ut_valid_object_type(type)) { 105 106 /* Type code out of range */ 107 108 ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); 109 return_UINT32(ACPI_NS_NORMAL); 110 } 111 112 return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); 113 } 114 115 /******************************************************************************* 116 * 117 * FUNCTION: acpi_ns_get_internal_name_length 118 * 119 * PARAMETERS: info - Info struct initialized with the 120 * external name pointer. 121 * 122 * RETURN: None 123 * 124 * DESCRIPTION: Calculate the length of the internal (AML) namestring 125 * corresponding to the external (ASL) namestring. 126 * 127 ******************************************************************************/ 128 129 void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) 130 { 131 const char *next_external_char; 132 u32 i; 133 134 ACPI_FUNCTION_ENTRY(); 135 136 next_external_char = info->external_name; 137 info->num_carats = 0; 138 info->num_segments = 0; 139 info->fully_qualified = FALSE; 140 141 /* 142 * For the internal name, the required length is 4 bytes per segment, 143 * plus 1 each for root_prefix, multi_name_prefix_op, segment count, 144 * trailing null (which is not really needed, but no there's harm in 145 * putting it there) 146 * 147 * strlen() + 1 covers the first name_seg, which has no path separator 148 */ 149 if (ACPI_IS_ROOT_PREFIX(*next_external_char)) { 150 info->fully_qualified = TRUE; 151 next_external_char++; 152 153 /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ 154 155 while (ACPI_IS_ROOT_PREFIX(*next_external_char)) { 156 next_external_char++; 157 } 158 } else { 159 /* Handle Carat prefixes */ 160 161 while (ACPI_IS_PARENT_PREFIX(*next_external_char)) { 162 info->num_carats++; 163 next_external_char++; 164 } 165 } 166 167 /* 168 * Determine the number of ACPI name "segments" by counting the number of 169 * path separators within the string. Start with one segment since the 170 * segment count is [(# separators) + 1], and zero separators is ok. 171 */ 172 if (*next_external_char) { 173 info->num_segments = 1; 174 for (i = 0; next_external_char[i]; i++) { 175 if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) { 176 info->num_segments++; 177 } 178 } 179 } 180 181 info->length = (ACPI_NAMESEG_SIZE * info->num_segments) + 182 4 + info->num_carats; 183 184 info->next_external_char = next_external_char; 185 } 186 187 /******************************************************************************* 188 * 189 * FUNCTION: acpi_ns_build_internal_name 190 * 191 * PARAMETERS: info - Info struct fully initialized 192 * 193 * RETURN: Status 194 * 195 * DESCRIPTION: Construct the internal (AML) namestring 196 * corresponding to the external (ASL) namestring. 197 * 198 ******************************************************************************/ 199 200 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) 201 { 202 u32 num_segments = info->num_segments; 203 char *internal_name = info->internal_name; 204 const char *external_name = info->next_external_char; 205 char *result = NULL; 206 u32 i; 207 208 ACPI_FUNCTION_TRACE(ns_build_internal_name); 209 210 /* Setup the correct prefixes, counts, and pointers */ 211 212 if (info->fully_qualified) { 213 internal_name[0] = AML_ROOT_PREFIX; 214 215 if (num_segments <= 1) { 216 result = &internal_name[1]; 217 } else if (num_segments == 2) { 218 internal_name[1] = AML_DUAL_NAME_PREFIX; 219 result = &internal_name[2]; 220 } else { 221 internal_name[1] = AML_MULTI_NAME_PREFIX; 222 internal_name[2] = (char)num_segments; 223 result = &internal_name[3]; 224 } 225 } else { 226 /* 227 * Not fully qualified. 228 * Handle Carats first, then append the name segments 229 */ 230 i = 0; 231 if (info->num_carats) { 232 for (i = 0; i < info->num_carats; i++) { 233 internal_name[i] = AML_PARENT_PREFIX; 234 } 235 } 236 237 if (num_segments <= 1) { 238 result = &internal_name[i]; 239 } else if (num_segments == 2) { 240 internal_name[i] = AML_DUAL_NAME_PREFIX; 241 result = &internal_name[(acpi_size)i + 1]; 242 } else { 243 internal_name[i] = AML_MULTI_NAME_PREFIX; 244 internal_name[(acpi_size)i + 1] = (char)num_segments; 245 result = &internal_name[(acpi_size)i + 2]; 246 } 247 } 248 249 /* Build the name (minus path separators) */ 250 251 for (; num_segments; num_segments--) { 252 for (i = 0; i < ACPI_NAMESEG_SIZE; i++) { 253 if (ACPI_IS_PATH_SEPARATOR(*external_name) || 254 (*external_name == 0)) { 255 256 /* Pad the segment with underscore(s) if segment is short */ 257 258 result[i] = '_'; 259 } else { 260 /* Convert the character to uppercase and save it */ 261 262 result[i] = (char)toupper((int)*external_name); 263 external_name++; 264 } 265 } 266 267 /* Now we must have a path separator, or the pathname is bad */ 268 269 if (!ACPI_IS_PATH_SEPARATOR(*external_name) && 270 (*external_name != 0)) { 271 return_ACPI_STATUS(AE_BAD_PATHNAME); 272 } 273 274 /* Move on the next segment */ 275 276 external_name++; 277 result += ACPI_NAMESEG_SIZE; 278 } 279 280 /* Terminate the string */ 281 282 *result = 0; 283 284 if (info->fully_qualified) { 285 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 286 "Returning [%p] (abs) \"\\%s\"\n", 287 internal_name, internal_name)); 288 } else { 289 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", 290 internal_name, internal_name)); 291 } 292 293 return_ACPI_STATUS(AE_OK); 294 } 295 296 /******************************************************************************* 297 * 298 * FUNCTION: acpi_ns_internalize_name 299 * 300 * PARAMETERS: *external_name - External representation of name 301 * **Converted name - Where to return the resulting 302 * internal represention of the name 303 * 304 * RETURN: Status 305 * 306 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") 307 * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 308 * 309 *******************************************************************************/ 310 311 acpi_status 312 acpi_ns_internalize_name(const char *external_name, char **converted_name) 313 { 314 char *internal_name; 315 struct acpi_namestring_info info; 316 acpi_status status; 317 318 ACPI_FUNCTION_TRACE(ns_internalize_name); 319 320 if ((!external_name) || (*external_name == 0) || (!converted_name)) { 321 return_ACPI_STATUS(AE_BAD_PARAMETER); 322 } 323 324 /* Get the length of the new internal name */ 325 326 info.external_name = external_name; 327 acpi_ns_get_internal_name_length(&info); 328 329 /* We need a segment to store the internal name */ 330 331 internal_name = ACPI_ALLOCATE_ZEROED(info.length); 332 if (!internal_name) { 333 return_ACPI_STATUS(AE_NO_MEMORY); 334 } 335 336 /* Build the name */ 337 338 info.internal_name = internal_name; 339 status = acpi_ns_build_internal_name(&info); 340 if (ACPI_FAILURE(status)) { 341 ACPI_FREE(internal_name); 342 return_ACPI_STATUS(status); 343 } 344 345 *converted_name = internal_name; 346 return_ACPI_STATUS(AE_OK); 347 } 348 349 /******************************************************************************* 350 * 351 * FUNCTION: acpi_ns_externalize_name 352 * 353 * PARAMETERS: internal_name_length - Length of the internal name below 354 * internal_name - Internal representation of name 355 * converted_name_length - Where the length is returned 356 * converted_name - Where the resulting external name 357 * is returned 358 * 359 * RETURN: Status 360 * 361 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 362 * to its external (printable) form (e.g. "\_PR_.CPU0") 363 * 364 ******************************************************************************/ 365 366 acpi_status 367 acpi_ns_externalize_name(u32 internal_name_length, 368 const char *internal_name, 369 u32 * converted_name_length, char **converted_name) 370 { 371 u32 names_index = 0; 372 u32 num_segments = 0; 373 u32 required_length; 374 u32 prefix_length = 0; 375 u32 i = 0; 376 u32 j = 0; 377 378 ACPI_FUNCTION_TRACE(ns_externalize_name); 379 380 if (!internal_name_length || !internal_name || !converted_name) { 381 return_ACPI_STATUS(AE_BAD_PARAMETER); 382 } 383 384 /* Check for a prefix (one '\' | one or more '^') */ 385 386 switch (internal_name[0]) { 387 case AML_ROOT_PREFIX: 388 389 prefix_length = 1; 390 break; 391 392 case AML_PARENT_PREFIX: 393 394 for (i = 0; i < internal_name_length; i++) { 395 if (ACPI_IS_PARENT_PREFIX(internal_name[i])) { 396 prefix_length = i + 1; 397 } else { 398 break; 399 } 400 } 401 402 if (i == internal_name_length) { 403 prefix_length = i; 404 } 405 406 break; 407 408 default: 409 410 break; 411 } 412 413 /* 414 * Check for object names. Note that there could be 0-255 of these 415 * 4-byte elements. 416 */ 417 if (prefix_length < internal_name_length) { 418 switch (internal_name[prefix_length]) { 419 case AML_MULTI_NAME_PREFIX: 420 421 /* <count> 4-byte names */ 422 423 names_index = prefix_length + 2; 424 num_segments = (u8) 425 internal_name[(acpi_size)prefix_length + 1]; 426 break; 427 428 case AML_DUAL_NAME_PREFIX: 429 430 /* Two 4-byte names */ 431 432 names_index = prefix_length + 1; 433 num_segments = 2; 434 break; 435 436 case 0: 437 438 /* null_name */ 439 440 names_index = 0; 441 num_segments = 0; 442 break; 443 444 default: 445 446 /* one 4-byte name */ 447 448 names_index = prefix_length; 449 num_segments = 1; 450 break; 451 } 452 } 453 454 /* 455 * Calculate the length of converted_name, which equals the length 456 * of the prefix, length of all object names, length of any required 457 * punctuation ('.') between object names, plus the NULL terminator. 458 */ 459 required_length = prefix_length + (4 * num_segments) + 460 ((num_segments > 0) ? (num_segments - 1) : 0) + 1; 461 462 /* 463 * Check to see if we're still in bounds. If not, there's a problem 464 * with internal_name (invalid format). 465 */ 466 if (required_length > internal_name_length) { 467 ACPI_ERROR((AE_INFO, "Invalid internal name")); 468 return_ACPI_STATUS(AE_BAD_PATHNAME); 469 } 470 471 /* Build the converted_name */ 472 473 *converted_name = ACPI_ALLOCATE_ZEROED(required_length); 474 if (!(*converted_name)) { 475 return_ACPI_STATUS(AE_NO_MEMORY); 476 } 477 478 j = 0; 479 480 for (i = 0; i < prefix_length; i++) { 481 (*converted_name)[j++] = internal_name[i]; 482 } 483 484 if (num_segments > 0) { 485 for (i = 0; i < num_segments; i++) { 486 if (i > 0) { 487 (*converted_name)[j++] = '.'; 488 } 489 490 /* Copy and validate the 4-char name segment */ 491 492 ACPI_COPY_NAMESEG(&(*converted_name)[j], 493 &internal_name[names_index]); 494 acpi_ut_repair_name(&(*converted_name)[j]); 495 496 j += ACPI_NAMESEG_SIZE; 497 names_index += ACPI_NAMESEG_SIZE; 498 } 499 } 500 501 if (converted_name_length) { 502 *converted_name_length = (u32) required_length; 503 } 504 505 return_ACPI_STATUS(AE_OK); 506 } 507 508 /******************************************************************************* 509 * 510 * FUNCTION: acpi_ns_validate_handle 511 * 512 * PARAMETERS: handle - Handle to be validated and typecast to a 513 * namespace node. 514 * 515 * RETURN: A pointer to a namespace node 516 * 517 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special 518 * cases for the root node. 519 * 520 * NOTE: Real integer handles would allow for more verification 521 * and keep all pointers within this subsystem - however this introduces 522 * more overhead and has not been necessary to this point. Drivers 523 * holding handles are typically notified before a node becomes invalid 524 * due to a table unload. 525 * 526 ******************************************************************************/ 527 528 struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle) 529 { 530 531 ACPI_FUNCTION_ENTRY(); 532 533 /* Parameter validation */ 534 535 if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { 536 return (acpi_gbl_root_node); 537 } 538 539 /* We can at least attempt to verify the handle */ 540 541 if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { 542 return (NULL); 543 } 544 545 return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); 546 } 547 548 /******************************************************************************* 549 * 550 * FUNCTION: acpi_ns_terminate 551 * 552 * PARAMETERS: none 553 * 554 * RETURN: none 555 * 556 * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 557 * 558 ******************************************************************************/ 559 560 void acpi_ns_terminate(void) 561 { 562 acpi_status status; 563 564 ACPI_FUNCTION_TRACE(ns_terminate); 565 566 /* 567 * Free the entire namespace -- all nodes and all objects 568 * attached to the nodes 569 */ 570 acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); 571 572 /* Delete any objects attached to the root node */ 573 574 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 575 if (ACPI_FAILURE(status)) { 576 return_VOID; 577 } 578 579 acpi_ns_delete_node(acpi_gbl_root_node); 580 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 581 582 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); 583 return_VOID; 584 } 585 586 /******************************************************************************* 587 * 588 * FUNCTION: acpi_ns_opens_scope 589 * 590 * PARAMETERS: type - A valid namespace type 591 * 592 * RETURN: NEWSCOPE if the passed type "opens a name scope" according 593 * to the ACPI specification, else 0 594 * 595 ******************************************************************************/ 596 597 u32 acpi_ns_opens_scope(acpi_object_type type) 598 { 599 ACPI_FUNCTION_ENTRY(); 600 601 if (type > ACPI_TYPE_LOCAL_MAX) { 602 603 /* type code out of range */ 604 605 ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); 606 return (ACPI_NS_NORMAL); 607 } 608 609 return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); 610 } 611 612 /******************************************************************************* 613 * 614 * FUNCTION: acpi_ns_get_node_unlocked 615 * 616 * PARAMETERS: *pathname - Name to be found, in external (ASL) format. The 617 * \ (backslash) and ^ (carat) prefixes, and the 618 * . (period) to separate segments are supported. 619 * prefix_node - Root of subtree to be searched, or NS_ALL for the 620 * root of the name space. If Name is fully 621 * qualified (first s8 is '\'), the passed value 622 * of Scope will not be accessed. 623 * flags - Used to indicate whether to perform upsearch or 624 * not. 625 * return_node - Where the Node is returned 626 * 627 * DESCRIPTION: Look up a name relative to a given scope and return the 628 * corresponding Node. NOTE: Scope can be null. 629 * 630 * MUTEX: Doesn't locks namespace 631 * 632 ******************************************************************************/ 633 634 acpi_status 635 acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node, 636 const char *pathname, 637 u32 flags, struct acpi_namespace_node **return_node) 638 { 639 union acpi_generic_state scope_info; 640 acpi_status status; 641 char *internal_path; 642 643 ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked, 644 ACPI_CAST_PTR(char, pathname)); 645 646 /* Simplest case is a null pathname */ 647 648 if (!pathname) { 649 *return_node = prefix_node; 650 if (!prefix_node) { 651 *return_node = acpi_gbl_root_node; 652 } 653 654 return_ACPI_STATUS(AE_OK); 655 } 656 657 /* Quick check for a reference to the root */ 658 659 if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) { 660 *return_node = acpi_gbl_root_node; 661 return_ACPI_STATUS(AE_OK); 662 } 663 664 /* Convert path to internal representation */ 665 666 status = acpi_ns_internalize_name(pathname, &internal_path); 667 if (ACPI_FAILURE(status)) { 668 return_ACPI_STATUS(status); 669 } 670 671 /* Setup lookup scope (search starting point) */ 672 673 scope_info.scope.node = prefix_node; 674 675 /* Lookup the name in the namespace */ 676 677 status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, 678 ACPI_IMODE_EXECUTE, 679 (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, 680 return_node); 681 if (ACPI_FAILURE(status)) { 682 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n", 683 pathname, acpi_format_exception(status))); 684 } 685 686 ACPI_FREE(internal_path); 687 return_ACPI_STATUS(status); 688 } 689 690 /******************************************************************************* 691 * 692 * FUNCTION: acpi_ns_get_node 693 * 694 * PARAMETERS: *pathname - Name to be found, in external (ASL) format. The 695 * \ (backslash) and ^ (carat) prefixes, and the 696 * . (period) to separate segments are supported. 697 * prefix_node - Root of subtree to be searched, or NS_ALL for the 698 * root of the name space. If Name is fully 699 * qualified (first s8 is '\'), the passed value 700 * of Scope will not be accessed. 701 * flags - Used to indicate whether to perform upsearch or 702 * not. 703 * return_node - Where the Node is returned 704 * 705 * DESCRIPTION: Look up a name relative to a given scope and return the 706 * corresponding Node. NOTE: Scope can be null. 707 * 708 * MUTEX: Locks namespace 709 * 710 ******************************************************************************/ 711 712 acpi_status 713 acpi_ns_get_node(struct acpi_namespace_node *prefix_node, 714 const char *pathname, 715 u32 flags, struct acpi_namespace_node **return_node) 716 { 717 acpi_status status; 718 719 ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); 720 721 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 722 if (ACPI_FAILURE(status)) { 723 return_ACPI_STATUS(status); 724 } 725 726 status = acpi_ns_get_node_unlocked(prefix_node, pathname, 727 flags, return_node); 728 729 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 730 return_ACPI_STATUS(status); 731 } 732