1 /****************************************************************************** 2 * 3 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing 4 * parents and siblings and Scope manipulation 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2008, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acnamesp.h" 48 #include "amlcode.h" 49 #include "actables.h" 50 51 #define _COMPONENT ACPI_NAMESPACE 52 ACPI_MODULE_NAME("nsutils") 53 54 /* Local prototypes */ 55 static u8 acpi_ns_valid_path_separator(char sep); 56 57 #ifdef ACPI_OBSOLETE_FUNCTIONS 58 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); 59 #endif 60 61 /******************************************************************************* 62 * 63 * FUNCTION: acpi_ns_report_error 64 * 65 * PARAMETERS: module_name - Caller's module name (for error output) 66 * line_number - Caller's line number (for error output) 67 * internal_name - Name or path of the namespace node 68 * lookup_status - Exception code from NS lookup 69 * 70 * RETURN: None 71 * 72 * DESCRIPTION: Print warning message with full pathname 73 * 74 ******************************************************************************/ 75 76 void 77 acpi_ns_report_error(const char *module_name, 78 u32 line_number, 79 const char *internal_name, acpi_status lookup_status) 80 { 81 acpi_status status; 82 u32 bad_name; 83 char *name = NULL; 84 85 acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); 86 87 if (lookup_status == AE_BAD_CHARACTER) { 88 89 /* There is a non-ascii character in the name */ 90 91 ACPI_MOVE_32_TO_32(&bad_name, 92 ACPI_CAST_PTR(u32, internal_name)); 93 acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); 94 } else { 95 /* Convert path to external format */ 96 97 status = acpi_ns_externalize_name(ACPI_UINT32_MAX, 98 internal_name, NULL, &name); 99 100 /* Print target name */ 101 102 if (ACPI_SUCCESS(status)) { 103 acpi_os_printf("[%s]", name); 104 } else { 105 acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); 106 } 107 108 if (name) { 109 ACPI_FREE(name); 110 } 111 } 112 113 acpi_os_printf(" Namespace lookup failure, %s\n", 114 acpi_format_exception(lookup_status)); 115 } 116 117 /******************************************************************************* 118 * 119 * FUNCTION: acpi_ns_report_method_error 120 * 121 * PARAMETERS: module_name - Caller's module name (for error output) 122 * line_number - Caller's line number (for error output) 123 * Message - Error message to use on failure 124 * prefix_node - Prefix relative to the path 125 * Path - Path to the node (optional) 126 * method_status - Execution status 127 * 128 * RETURN: None 129 * 130 * DESCRIPTION: Print warning message with full pathname 131 * 132 ******************************************************************************/ 133 134 void 135 acpi_ns_report_method_error(const char *module_name, 136 u32 line_number, 137 const char *message, 138 struct acpi_namespace_node *prefix_node, 139 const char *path, acpi_status method_status) 140 { 141 acpi_status status; 142 struct acpi_namespace_node *node = prefix_node; 143 144 acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); 145 146 if (path) { 147 status = 148 acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, 149 &node); 150 if (ACPI_FAILURE(status)) { 151 acpi_os_printf("[Could not get node by pathname]"); 152 } 153 } 154 155 acpi_ns_print_node_pathname(node, message); 156 acpi_os_printf(", %s\n", acpi_format_exception(method_status)); 157 } 158 159 /******************************************************************************* 160 * 161 * FUNCTION: acpi_ns_print_node_pathname 162 * 163 * PARAMETERS: Node - Object 164 * Message - Prefix message 165 * 166 * DESCRIPTION: Print an object's full namespace pathname 167 * Manages allocation/freeing of a pathname buffer 168 * 169 ******************************************************************************/ 170 171 void 172 acpi_ns_print_node_pathname(struct acpi_namespace_node *node, 173 const char *message) 174 { 175 struct acpi_buffer buffer; 176 acpi_status status; 177 178 if (!node) { 179 acpi_os_printf("[NULL NAME]"); 180 return; 181 } 182 183 /* Convert handle to full pathname and print it (with supplied message) */ 184 185 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 186 187 status = acpi_ns_handle_to_pathname(node, &buffer); 188 if (ACPI_SUCCESS(status)) { 189 if (message) { 190 acpi_os_printf("%s ", message); 191 } 192 193 acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node); 194 ACPI_FREE(buffer.pointer); 195 } 196 } 197 198 /******************************************************************************* 199 * 200 * FUNCTION: acpi_ns_valid_root_prefix 201 * 202 * PARAMETERS: Prefix - Character to be checked 203 * 204 * RETURN: TRUE if a valid prefix 205 * 206 * DESCRIPTION: Check if a character is a valid ACPI Root prefix 207 * 208 ******************************************************************************/ 209 210 u8 acpi_ns_valid_root_prefix(char prefix) 211 { 212 213 return ((u8) (prefix == '\\')); 214 } 215 216 /******************************************************************************* 217 * 218 * FUNCTION: acpi_ns_valid_path_separator 219 * 220 * PARAMETERS: Sep - Character to be checked 221 * 222 * RETURN: TRUE if a valid path separator 223 * 224 * DESCRIPTION: Check if a character is a valid ACPI path separator 225 * 226 ******************************************************************************/ 227 228 static u8 acpi_ns_valid_path_separator(char sep) 229 { 230 231 return ((u8) (sep == '.')); 232 } 233 234 /******************************************************************************* 235 * 236 * FUNCTION: acpi_ns_get_type 237 * 238 * PARAMETERS: Node - Parent Node to be examined 239 * 240 * RETURN: Type field from Node whose handle is passed 241 * 242 * DESCRIPTION: Return the type of a Namespace node 243 * 244 ******************************************************************************/ 245 246 acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) 247 { 248 ACPI_FUNCTION_TRACE(ns_get_type); 249 250 if (!node) { 251 ACPI_WARNING((AE_INFO, "Null Node parameter")); 252 return_UINT32(ACPI_TYPE_ANY); 253 } 254 255 return_UINT32((acpi_object_type) node->type); 256 } 257 258 /******************************************************************************* 259 * 260 * FUNCTION: acpi_ns_local 261 * 262 * PARAMETERS: Type - A namespace object type 263 * 264 * RETURN: LOCAL if names must be found locally in objects of the 265 * passed type, 0 if enclosing scopes should be searched 266 * 267 * DESCRIPTION: Returns scope rule for the given object type. 268 * 269 ******************************************************************************/ 270 271 u32 acpi_ns_local(acpi_object_type type) 272 { 273 ACPI_FUNCTION_TRACE(ns_local); 274 275 if (!acpi_ut_valid_object_type(type)) { 276 277 /* Type code out of range */ 278 279 ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); 280 return_UINT32(ACPI_NS_NORMAL); 281 } 282 283 return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); 284 } 285 286 /******************************************************************************* 287 * 288 * FUNCTION: acpi_ns_get_internal_name_length 289 * 290 * PARAMETERS: Info - Info struct initialized with the 291 * external name pointer. 292 * 293 * RETURN: None 294 * 295 * DESCRIPTION: Calculate the length of the internal (AML) namestring 296 * corresponding to the external (ASL) namestring. 297 * 298 ******************************************************************************/ 299 300 void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) 301 { 302 const char *next_external_char; 303 u32 i; 304 305 ACPI_FUNCTION_ENTRY(); 306 307 next_external_char = info->external_name; 308 info->num_carats = 0; 309 info->num_segments = 0; 310 info->fully_qualified = FALSE; 311 312 /* 313 * For the internal name, the required length is 4 bytes per segment, plus 314 * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null 315 * (which is not really needed, but no there's harm in putting it there) 316 * 317 * strlen() + 1 covers the first name_seg, which has no path separator 318 */ 319 if (acpi_ns_valid_root_prefix(*next_external_char)) { 320 info->fully_qualified = TRUE; 321 next_external_char++; 322 323 /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ 324 325 while (acpi_ns_valid_root_prefix(*next_external_char)) { 326 next_external_char++; 327 } 328 } else { 329 /* Handle Carat prefixes */ 330 331 while (*next_external_char == '^') { 332 info->num_carats++; 333 next_external_char++; 334 } 335 } 336 337 /* 338 * Determine the number of ACPI name "segments" by counting the number of 339 * path separators within the string. Start with one segment since the 340 * segment count is [(# separators) + 1], and zero separators is ok. 341 */ 342 if (*next_external_char) { 343 info->num_segments = 1; 344 for (i = 0; next_external_char[i]; i++) { 345 if (acpi_ns_valid_path_separator(next_external_char[i])) { 346 info->num_segments++; 347 } 348 } 349 } 350 351 info->length = (ACPI_NAME_SIZE * info->num_segments) + 352 4 + info->num_carats; 353 354 info->next_external_char = next_external_char; 355 } 356 357 /******************************************************************************* 358 * 359 * FUNCTION: acpi_ns_build_internal_name 360 * 361 * PARAMETERS: Info - Info struct fully initialized 362 * 363 * RETURN: Status 364 * 365 * DESCRIPTION: Construct the internal (AML) namestring 366 * corresponding to the external (ASL) namestring. 367 * 368 ******************************************************************************/ 369 370 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) 371 { 372 u32 num_segments = info->num_segments; 373 char *internal_name = info->internal_name; 374 const char *external_name = info->next_external_char; 375 char *result = NULL; 376 u32 i; 377 378 ACPI_FUNCTION_TRACE(ns_build_internal_name); 379 380 /* Setup the correct prefixes, counts, and pointers */ 381 382 if (info->fully_qualified) { 383 internal_name[0] = '\\'; 384 385 if (num_segments <= 1) { 386 result = &internal_name[1]; 387 } else if (num_segments == 2) { 388 internal_name[1] = AML_DUAL_NAME_PREFIX; 389 result = &internal_name[2]; 390 } else { 391 internal_name[1] = AML_MULTI_NAME_PREFIX_OP; 392 internal_name[2] = (char)num_segments; 393 result = &internal_name[3]; 394 } 395 } else { 396 /* 397 * Not fully qualified. 398 * Handle Carats first, then append the name segments 399 */ 400 i = 0; 401 if (info->num_carats) { 402 for (i = 0; i < info->num_carats; i++) { 403 internal_name[i] = '^'; 404 } 405 } 406 407 if (num_segments <= 1) { 408 result = &internal_name[i]; 409 } else if (num_segments == 2) { 410 internal_name[i] = AML_DUAL_NAME_PREFIX; 411 result = &internal_name[(acpi_size) i + 1]; 412 } else { 413 internal_name[i] = AML_MULTI_NAME_PREFIX_OP; 414 internal_name[(acpi_size) i + 1] = (char)num_segments; 415 result = &internal_name[(acpi_size) i + 2]; 416 } 417 } 418 419 /* Build the name (minus path separators) */ 420 421 for (; num_segments; num_segments--) { 422 for (i = 0; i < ACPI_NAME_SIZE; i++) { 423 if (acpi_ns_valid_path_separator(*external_name) || 424 (*external_name == 0)) { 425 426 /* Pad the segment with underscore(s) if segment is short */ 427 428 result[i] = '_'; 429 } else { 430 /* Convert the character to uppercase and save it */ 431 432 result[i] = 433 (char)ACPI_TOUPPER((int)*external_name); 434 external_name++; 435 } 436 } 437 438 /* Now we must have a path separator, or the pathname is bad */ 439 440 if (!acpi_ns_valid_path_separator(*external_name) && 441 (*external_name != 0)) { 442 return_ACPI_STATUS(AE_BAD_PARAMETER); 443 } 444 445 /* Move on the next segment */ 446 447 external_name++; 448 result += ACPI_NAME_SIZE; 449 } 450 451 /* Terminate the string */ 452 453 *result = 0; 454 455 if (info->fully_qualified) { 456 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 457 "Returning [%p] (abs) \"\\%s\"\n", 458 internal_name, internal_name)); 459 } else { 460 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", 461 internal_name, internal_name)); 462 } 463 464 return_ACPI_STATUS(AE_OK); 465 } 466 467 /******************************************************************************* 468 * 469 * FUNCTION: acpi_ns_internalize_name 470 * 471 * PARAMETERS: *external_name - External representation of name 472 * **Converted Name - Where to return the resulting 473 * internal represention of the name 474 * 475 * RETURN: Status 476 * 477 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") 478 * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 479 * 480 *******************************************************************************/ 481 482 acpi_status 483 acpi_ns_internalize_name(const char *external_name, char **converted_name) 484 { 485 char *internal_name; 486 struct acpi_namestring_info info; 487 acpi_status status; 488 489 ACPI_FUNCTION_TRACE(ns_internalize_name); 490 491 if ((!external_name) || (*external_name == 0) || (!converted_name)) { 492 return_ACPI_STATUS(AE_BAD_PARAMETER); 493 } 494 495 /* Get the length of the new internal name */ 496 497 info.external_name = external_name; 498 acpi_ns_get_internal_name_length(&info); 499 500 /* We need a segment to store the internal name */ 501 502 internal_name = ACPI_ALLOCATE_ZEROED(info.length); 503 if (!internal_name) { 504 return_ACPI_STATUS(AE_NO_MEMORY); 505 } 506 507 /* Build the name */ 508 509 info.internal_name = internal_name; 510 status = acpi_ns_build_internal_name(&info); 511 if (ACPI_FAILURE(status)) { 512 ACPI_FREE(internal_name); 513 return_ACPI_STATUS(status); 514 } 515 516 *converted_name = internal_name; 517 return_ACPI_STATUS(AE_OK); 518 } 519 520 /******************************************************************************* 521 * 522 * FUNCTION: acpi_ns_externalize_name 523 * 524 * PARAMETERS: internal_name_length - Lenth of the internal name below 525 * internal_name - Internal representation of name 526 * converted_name_length - Where the length is returned 527 * converted_name - Where the resulting external name 528 * is returned 529 * 530 * RETURN: Status 531 * 532 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 533 * to its external (printable) form (e.g. "\_PR_.CPU0") 534 * 535 ******************************************************************************/ 536 537 acpi_status 538 acpi_ns_externalize_name(u32 internal_name_length, 539 const char *internal_name, 540 u32 * converted_name_length, char **converted_name) 541 { 542 u32 names_index = 0; 543 u32 num_segments = 0; 544 u32 required_length; 545 u32 prefix_length = 0; 546 u32 i = 0; 547 u32 j = 0; 548 549 ACPI_FUNCTION_TRACE(ns_externalize_name); 550 551 if (!internal_name_length || !internal_name || !converted_name) { 552 return_ACPI_STATUS(AE_BAD_PARAMETER); 553 } 554 555 /* Check for a prefix (one '\' | one or more '^') */ 556 557 switch (internal_name[0]) { 558 case '\\': 559 prefix_length = 1; 560 break; 561 562 case '^': 563 for (i = 0; i < internal_name_length; i++) { 564 if (internal_name[i] == '^') { 565 prefix_length = i + 1; 566 } else { 567 break; 568 } 569 } 570 571 if (i == internal_name_length) { 572 prefix_length = i; 573 } 574 575 break; 576 577 default: 578 break; 579 } 580 581 /* 582 * Check for object names. Note that there could be 0-255 of these 583 * 4-byte elements. 584 */ 585 if (prefix_length < internal_name_length) { 586 switch (internal_name[prefix_length]) { 587 case AML_MULTI_NAME_PREFIX_OP: 588 589 /* <count> 4-byte names */ 590 591 names_index = prefix_length + 2; 592 num_segments = (u8) 593 internal_name[(acpi_size) prefix_length + 1]; 594 break; 595 596 case AML_DUAL_NAME_PREFIX: 597 598 /* Two 4-byte names */ 599 600 names_index = prefix_length + 1; 601 num_segments = 2; 602 break; 603 604 case 0: 605 606 /* null_name */ 607 608 names_index = 0; 609 num_segments = 0; 610 break; 611 612 default: 613 614 /* one 4-byte name */ 615 616 names_index = prefix_length; 617 num_segments = 1; 618 break; 619 } 620 } 621 622 /* 623 * Calculate the length of converted_name, which equals the length 624 * of the prefix, length of all object names, length of any required 625 * punctuation ('.') between object names, plus the NULL terminator. 626 */ 627 required_length = prefix_length + (4 * num_segments) + 628 ((num_segments > 0) ? (num_segments - 1) : 0) + 1; 629 630 /* 631 * Check to see if we're still in bounds. If not, there's a problem 632 * with internal_name (invalid format). 633 */ 634 if (required_length > internal_name_length) { 635 ACPI_ERROR((AE_INFO, "Invalid internal name")); 636 return_ACPI_STATUS(AE_BAD_PATHNAME); 637 } 638 639 /* Build the converted_name */ 640 641 *converted_name = ACPI_ALLOCATE_ZEROED(required_length); 642 if (!(*converted_name)) { 643 return_ACPI_STATUS(AE_NO_MEMORY); 644 } 645 646 j = 0; 647 648 for (i = 0; i < prefix_length; i++) { 649 (*converted_name)[j++] = internal_name[i]; 650 } 651 652 if (num_segments > 0) { 653 for (i = 0; i < num_segments; i++) { 654 if (i > 0) { 655 (*converted_name)[j++] = '.'; 656 } 657 658 (*converted_name)[j++] = internal_name[names_index++]; 659 (*converted_name)[j++] = internal_name[names_index++]; 660 (*converted_name)[j++] = internal_name[names_index++]; 661 (*converted_name)[j++] = internal_name[names_index++]; 662 } 663 } 664 665 if (converted_name_length) { 666 *converted_name_length = (u32) required_length; 667 } 668 669 return_ACPI_STATUS(AE_OK); 670 } 671 672 /******************************************************************************* 673 * 674 * FUNCTION: acpi_ns_validate_handle 675 * 676 * PARAMETERS: Handle - Handle to be validated and typecast to a 677 * namespace node. 678 * 679 * RETURN: A pointer to a namespace node 680 * 681 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special 682 * cases for the root node. 683 * 684 * NOTE: Real integer handles would allow for more verification 685 * and keep all pointers within this subsystem - however this introduces 686 * more overhead and has not been necessary to this point. Drivers 687 * holding handles are typically notified before a node becomes invalid 688 * due to a table unload. 689 * 690 ******************************************************************************/ 691 692 struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle) 693 { 694 695 ACPI_FUNCTION_ENTRY(); 696 697 /* Parameter validation */ 698 699 if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { 700 return (acpi_gbl_root_node); 701 } 702 703 /* We can at least attempt to verify the handle */ 704 705 if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { 706 return (NULL); 707 } 708 709 return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); 710 } 711 712 /******************************************************************************* 713 * 714 * FUNCTION: acpi_ns_terminate 715 * 716 * PARAMETERS: none 717 * 718 * RETURN: none 719 * 720 * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 721 * 722 ******************************************************************************/ 723 724 void acpi_ns_terminate(void) 725 { 726 union acpi_operand_object *obj_desc; 727 728 ACPI_FUNCTION_TRACE(ns_terminate); 729 730 /* 731 * 1) Free the entire namespace -- all nodes and objects 732 * 733 * Delete all object descriptors attached to namepsace nodes 734 */ 735 acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); 736 737 /* Detach any objects attached to the root */ 738 739 obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); 740 if (obj_desc) { 741 acpi_ns_detach_object(acpi_gbl_root_node); 742 } 743 744 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); 745 return_VOID; 746 } 747 748 /******************************************************************************* 749 * 750 * FUNCTION: acpi_ns_opens_scope 751 * 752 * PARAMETERS: Type - A valid namespace type 753 * 754 * RETURN: NEWSCOPE if the passed type "opens a name scope" according 755 * to the ACPI specification, else 0 756 * 757 ******************************************************************************/ 758 759 u32 acpi_ns_opens_scope(acpi_object_type type) 760 { 761 ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); 762 763 if (!acpi_ut_valid_object_type(type)) { 764 765 /* type code out of range */ 766 767 ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); 768 return_UINT32(ACPI_NS_NORMAL); 769 } 770 771 return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); 772 } 773 774 /******************************************************************************* 775 * 776 * FUNCTION: acpi_ns_get_node 777 * 778 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The 779 * \ (backslash) and ^ (carat) prefixes, and the 780 * . (period) to separate segments are supported. 781 * prefix_node - Root of subtree to be searched, or NS_ALL for the 782 * root of the name space. If Name is fully 783 * qualified (first s8 is '\'), the passed value 784 * of Scope will not be accessed. 785 * Flags - Used to indicate whether to perform upsearch or 786 * not. 787 * return_node - Where the Node is returned 788 * 789 * DESCRIPTION: Look up a name relative to a given scope and return the 790 * corresponding Node. NOTE: Scope can be null. 791 * 792 * MUTEX: Locks namespace 793 * 794 ******************************************************************************/ 795 796 acpi_status 797 acpi_ns_get_node(struct acpi_namespace_node *prefix_node, 798 const char *pathname, 799 u32 flags, struct acpi_namespace_node **return_node) 800 { 801 union acpi_generic_state scope_info; 802 acpi_status status; 803 char *internal_path; 804 805 ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); 806 807 if (!pathname) { 808 *return_node = prefix_node; 809 if (!prefix_node) { 810 *return_node = acpi_gbl_root_node; 811 } 812 return_ACPI_STATUS(AE_OK); 813 } 814 815 /* Convert path to internal representation */ 816 817 status = acpi_ns_internalize_name(pathname, &internal_path); 818 if (ACPI_FAILURE(status)) { 819 return_ACPI_STATUS(status); 820 } 821 822 /* Must lock namespace during lookup */ 823 824 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 825 if (ACPI_FAILURE(status)) { 826 goto cleanup; 827 } 828 829 /* Setup lookup scope (search starting point) */ 830 831 scope_info.scope.node = prefix_node; 832 833 /* Lookup the name in the namespace */ 834 835 status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, 836 ACPI_IMODE_EXECUTE, 837 (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, 838 return_node); 839 if (ACPI_FAILURE(status)) { 840 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n", 841 pathname, acpi_format_exception(status))); 842 } 843 844 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 845 846 cleanup: 847 ACPI_FREE(internal_path); 848 return_ACPI_STATUS(status); 849 } 850 851 /******************************************************************************* 852 * 853 * FUNCTION: acpi_ns_get_parent_node 854 * 855 * PARAMETERS: Node - Current table entry 856 * 857 * RETURN: Parent entry of the given entry 858 * 859 * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. 860 * 861 ******************************************************************************/ 862 863 struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node 864 *node) 865 { 866 ACPI_FUNCTION_ENTRY(); 867 868 if (!node) { 869 return (NULL); 870 } 871 872 /* 873 * Walk to the end of this peer list. The last entry is marked with a flag 874 * and the peer pointer is really a pointer back to the parent. This saves 875 * putting a parent back pointer in each and every named object! 876 */ 877 while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { 878 node = node->peer; 879 } 880 881 return (node->peer); 882 } 883 884 /******************************************************************************* 885 * 886 * FUNCTION: acpi_ns_get_next_valid_node 887 * 888 * PARAMETERS: Node - Current table entry 889 * 890 * RETURN: Next valid Node in the linked node list. NULL if no more valid 891 * nodes. 892 * 893 * DESCRIPTION: Find the next valid node within a name table. 894 * Useful for implementing NULL-end-of-list loops. 895 * 896 ******************************************************************************/ 897 898 struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct 899 acpi_namespace_node 900 *node) 901 { 902 903 /* If we are at the end of this peer list, return NULL */ 904 905 if (node->flags & ANOBJ_END_OF_PEER_LIST) { 906 return NULL; 907 } 908 909 /* Otherwise just return the next peer */ 910 911 return (node->peer); 912 } 913 914 #ifdef ACPI_OBSOLETE_FUNCTIONS 915 /******************************************************************************* 916 * 917 * FUNCTION: acpi_ns_find_parent_name 918 * 919 * PARAMETERS: *child_node - Named Obj whose name is to be found 920 * 921 * RETURN: The ACPI name 922 * 923 * DESCRIPTION: Search for the given obj in its parent scope and return the 924 * name segment, or "????" if the parent name can't be found 925 * (which "should not happen"). 926 * 927 ******************************************************************************/ 928 929 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) 930 { 931 struct acpi_namespace_node *parent_node; 932 933 ACPI_FUNCTION_TRACE(ns_find_parent_name); 934 935 if (child_node) { 936 937 /* Valid entry. Get the parent Node */ 938 939 parent_node = acpi_ns_get_parent_node(child_node); 940 if (parent_node) { 941 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 942 "Parent of %p [%4.4s] is %p [%4.4s]\n", 943 child_node, 944 acpi_ut_get_node_name(child_node), 945 parent_node, 946 acpi_ut_get_node_name(parent_node))); 947 948 if (parent_node->name.integer) { 949 return_VALUE((acpi_name) parent_node->name. 950 integer); 951 } 952 } 953 954 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 955 "Unable to find parent of %p (%4.4s)\n", 956 child_node, 957 acpi_ut_get_node_name(child_node))); 958 } 959 960 return_VALUE(ACPI_UNKNOWN_NAME); 961 } 962 #endif 963