at v2.6.15 998 lines 28 kB view raw
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 - 2005, R. Byron Moore 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 <acpi/acnamesp.h> 47#include <acpi/amlcode.h> 48#include <acpi/actables.h> 49 50#define _COMPONENT ACPI_NAMESPACE 51ACPI_MODULE_NAME("nsutils") 52 53/* Local prototypes */ 54static u8 acpi_ns_valid_path_separator(char sep); 55 56#ifdef ACPI_OBSOLETE_FUNCTIONS 57acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); 58#endif 59 60/******************************************************************************* 61 * 62 * FUNCTION: acpi_ns_report_error 63 * 64 * PARAMETERS: module_name - Caller's module name (for error output) 65 * line_number - Caller's line number (for error output) 66 * component_id - Caller's component ID (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 76void 77acpi_ns_report_error(char *module_name, 78 u32 line_number, 79 u32 component_id, 80 char *internal_name, acpi_status lookup_status) 81{ 82 acpi_status status; 83 char *name = NULL; 84 85 acpi_os_printf("%8s-%04d: *** Error: Looking up ", 86 module_name, line_number); 87 88 if (lookup_status == AE_BAD_CHARACTER) { 89 /* There is a non-ascii character in the name */ 90 91 acpi_os_printf("[0x%4.4X] (NON-ASCII)\n", 92 *(ACPI_CAST_PTR(u32, internal_name))); 93 } else { 94 /* Convert path to external format */ 95 96 status = acpi_ns_externalize_name(ACPI_UINT32_MAX, 97 internal_name, NULL, &name); 98 99 /* Print target name */ 100 101 if (ACPI_SUCCESS(status)) { 102 acpi_os_printf("[%s]", name); 103 } else { 104 acpi_os_printf("[COULD NOT EXTERNALIZE NAME]"); 105 } 106 107 if (name) { 108 ACPI_MEM_FREE(name); 109 } 110 } 111 112 acpi_os_printf(" in namespace, %s\n", 113 acpi_format_exception(lookup_status)); 114} 115 116/******************************************************************************* 117 * 118 * FUNCTION: acpi_ns_report_method_error 119 * 120 * PARAMETERS: module_name - Caller's module name (for error output) 121 * line_number - Caller's line number (for error output) 122 * component_id - Caller's component ID (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 126 * method_status - Execution status 127 * 128 * RETURN: None 129 * 130 * DESCRIPTION: Print warning message with full pathname 131 * 132 ******************************************************************************/ 133 134void 135acpi_ns_report_method_error(char *module_name, 136 u32 line_number, 137 u32 component_id, 138 char *message, 139 struct acpi_namespace_node *prefix_node, 140 char *path, acpi_status method_status) 141{ 142 acpi_status status; 143 struct acpi_namespace_node *node = prefix_node; 144 145 if (path) { 146 status = acpi_ns_get_node_by_path(path, prefix_node, 147 ACPI_NS_NO_UPSEARCH, &node); 148 if (ACPI_FAILURE(status)) { 149 acpi_os_printf 150 ("report_method_error: Could not get node\n"); 151 return; 152 } 153 } 154 155 acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number); 156 acpi_ns_print_node_pathname(node, message); 157 acpi_os_printf(", %s\n", acpi_format_exception(method_status)); 158} 159 160/******************************************************************************* 161 * 162 * FUNCTION: acpi_ns_print_node_pathname 163 * 164 * PARAMETERS: Node - Object 165 * Message - Prefix message 166 * 167 * DESCRIPTION: Print an object's full namespace pathname 168 * Manages allocation/freeing of a pathname buffer 169 * 170 ******************************************************************************/ 171 172void 173acpi_ns_print_node_pathname(struct acpi_namespace_node *node, 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_MEM_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 210u8 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 228static 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 246acpi_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_REPORT_WARNING(("ns_get_type: Null Node input pointer\n")); 252 return_VALUE(ACPI_TYPE_ANY); 253 } 254 255 return_VALUE((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 271u32 acpi_ns_local(acpi_object_type type) 272{ 273 ACPI_FUNCTION_TRACE("ns_local"); 274 275 if (!acpi_ut_valid_object_type(type)) { 276 /* Type code out of range */ 277 278 ACPI_REPORT_WARNING(("ns_local: Invalid Object Type\n")); 279 return_VALUE(ACPI_NS_NORMAL); 280 } 281 282 return_VALUE((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL); 283} 284 285/******************************************************************************* 286 * 287 * FUNCTION: acpi_ns_get_internal_name_length 288 * 289 * PARAMETERS: Info - Info struct initialized with the 290 * external name pointer. 291 * 292 * RETURN: None 293 * 294 * DESCRIPTION: Calculate the length of the internal (AML) namestring 295 * corresponding to the external (ASL) namestring. 296 * 297 ******************************************************************************/ 298 299void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) 300{ 301 char *next_external_char; 302 u32 i; 303 304 ACPI_FUNCTION_ENTRY(); 305 306 next_external_char = info->external_name; 307 info->num_carats = 0; 308 info->num_segments = 0; 309 info->fully_qualified = FALSE; 310 311 /* 312 * For the internal name, the required length is 4 bytes per segment, plus 313 * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null 314 * (which is not really needed, but no there's harm in putting it there) 315 * 316 * strlen() + 1 covers the first name_seg, which has no path separator 317 */ 318 if (acpi_ns_valid_root_prefix(next_external_char[0])) { 319 info->fully_qualified = TRUE; 320 next_external_char++; 321 } else { 322 /* 323 * Handle Carat prefixes 324 */ 325 while (*next_external_char == '^') { 326 info->num_carats++; 327 next_external_char++; 328 } 329 } 330 331 /* 332 * Determine the number of ACPI name "segments" by counting the number of 333 * path separators within the string. Start with one segment since the 334 * segment count is [(# separators) + 1], and zero separators is ok. 335 */ 336 if (*next_external_char) { 337 info->num_segments = 1; 338 for (i = 0; next_external_char[i]; i++) { 339 if (acpi_ns_valid_path_separator(next_external_char[i])) { 340 info->num_segments++; 341 } 342 } 343 } 344 345 info->length = (ACPI_NAME_SIZE * info->num_segments) + 346 4 + info->num_carats; 347 348 info->next_external_char = next_external_char; 349} 350 351/******************************************************************************* 352 * 353 * FUNCTION: acpi_ns_build_internal_name 354 * 355 * PARAMETERS: Info - Info struct fully initialized 356 * 357 * RETURN: Status 358 * 359 * DESCRIPTION: Construct the internal (AML) namestring 360 * corresponding to the external (ASL) namestring. 361 * 362 ******************************************************************************/ 363 364acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) 365{ 366 u32 num_segments = info->num_segments; 367 char *internal_name = info->internal_name; 368 char *external_name = info->next_external_char; 369 char *result = NULL; 370 acpi_native_uint i; 371 372 ACPI_FUNCTION_TRACE("ns_build_internal_name"); 373 374 /* Setup the correct prefixes, counts, and pointers */ 375 376 if (info->fully_qualified) { 377 internal_name[0] = '\\'; 378 379 if (num_segments <= 1) { 380 result = &internal_name[1]; 381 } else if (num_segments == 2) { 382 internal_name[1] = AML_DUAL_NAME_PREFIX; 383 result = &internal_name[2]; 384 } else { 385 internal_name[1] = AML_MULTI_NAME_PREFIX_OP; 386 internal_name[2] = (char)num_segments; 387 result = &internal_name[3]; 388 } 389 } else { 390 /* 391 * Not fully qualified. 392 * Handle Carats first, then append the name segments 393 */ 394 i = 0; 395 if (info->num_carats) { 396 for (i = 0; i < info->num_carats; i++) { 397 internal_name[i] = '^'; 398 } 399 } 400 401 if (num_segments <= 1) { 402 result = &internal_name[i]; 403 } else if (num_segments == 2) { 404 internal_name[i] = AML_DUAL_NAME_PREFIX; 405 result = &internal_name[(acpi_native_uint) (i + 1)]; 406 } else { 407 internal_name[i] = AML_MULTI_NAME_PREFIX_OP; 408 internal_name[(acpi_native_uint) (i + 1)] = 409 (char)num_segments; 410 result = &internal_name[(acpi_native_uint) (i + 2)]; 411 } 412 } 413 414 /* Build the name (minus path separators) */ 415 416 for (; num_segments; num_segments--) { 417 for (i = 0; i < ACPI_NAME_SIZE; i++) { 418 if (acpi_ns_valid_path_separator(*external_name) || 419 (*external_name == 0)) { 420 /* Pad the segment with underscore(s) if segment is short */ 421 422 result[i] = '_'; 423 } else { 424 /* Convert the character to uppercase and save it */ 425 426 result[i] = 427 (char)ACPI_TOUPPER((int)*external_name); 428 external_name++; 429 } 430 } 431 432 /* Now we must have a path separator, or the pathname is bad */ 433 434 if (!acpi_ns_valid_path_separator(*external_name) && 435 (*external_name != 0)) { 436 return_ACPI_STATUS(AE_BAD_PARAMETER); 437 } 438 439 /* Move on the next segment */ 440 441 external_name++; 442 result += ACPI_NAME_SIZE; 443 } 444 445 /* Terminate the string */ 446 447 *result = 0; 448 449 if (info->fully_qualified) { 450 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 451 "Returning [%p] (abs) \"\\%s\"\n", 452 internal_name, internal_name)); 453 } else { 454 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", 455 internal_name, internal_name)); 456 } 457 458 return_ACPI_STATUS(AE_OK); 459} 460 461/******************************************************************************* 462 * 463 * FUNCTION: acpi_ns_internalize_name 464 * 465 * PARAMETERS: *external_name - External representation of name 466 * **Converted Name - Where to return the resulting 467 * internal represention of the name 468 * 469 * RETURN: Status 470 * 471 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") 472 * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 473 * 474 *******************************************************************************/ 475 476acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name) 477{ 478 char *internal_name; 479 struct acpi_namestring_info info; 480 acpi_status status; 481 482 ACPI_FUNCTION_TRACE("ns_internalize_name"); 483 484 if ((!external_name) || (*external_name == 0) || (!converted_name)) { 485 return_ACPI_STATUS(AE_BAD_PARAMETER); 486 } 487 488 /* Get the length of the new internal name */ 489 490 info.external_name = external_name; 491 acpi_ns_get_internal_name_length(&info); 492 493 /* We need a segment to store the internal name */ 494 495 internal_name = ACPI_MEM_CALLOCATE(info.length); 496 if (!internal_name) { 497 return_ACPI_STATUS(AE_NO_MEMORY); 498 } 499 500 /* Build the name */ 501 502 info.internal_name = internal_name; 503 status = acpi_ns_build_internal_name(&info); 504 if (ACPI_FAILURE(status)) { 505 ACPI_MEM_FREE(internal_name); 506 return_ACPI_STATUS(status); 507 } 508 509 *converted_name = internal_name; 510 return_ACPI_STATUS(AE_OK); 511} 512 513/******************************************************************************* 514 * 515 * FUNCTION: acpi_ns_externalize_name 516 * 517 * PARAMETERS: internal_name_length - Lenth of the internal name below 518 * internal_name - Internal representation of name 519 * converted_name_length - Where the length is returned 520 * converted_name - Where the resulting external name 521 * is returned 522 * 523 * RETURN: Status 524 * 525 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 526 * to its external (printable) form (e.g. "\_PR_.CPU0") 527 * 528 ******************************************************************************/ 529 530acpi_status 531acpi_ns_externalize_name(u32 internal_name_length, 532 char *internal_name, 533 u32 * converted_name_length, char **converted_name) 534{ 535 acpi_native_uint names_index = 0; 536 acpi_native_uint num_segments = 0; 537 acpi_native_uint required_length; 538 acpi_native_uint prefix_length = 0; 539 acpi_native_uint i = 0; 540 acpi_native_uint j = 0; 541 542 ACPI_FUNCTION_TRACE("ns_externalize_name"); 543 544 if (!internal_name_length || !internal_name || !converted_name) { 545 return_ACPI_STATUS(AE_BAD_PARAMETER); 546 } 547 548 /* 549 * Check for a prefix (one '\' | one or more '^'). 550 */ 551 switch (internal_name[0]) { 552 case '\\': 553 prefix_length = 1; 554 break; 555 556 case '^': 557 for (i = 0; i < internal_name_length; i++) { 558 if (internal_name[i] == '^') { 559 prefix_length = i + 1; 560 } else { 561 break; 562 } 563 } 564 565 if (i == internal_name_length) { 566 prefix_length = i; 567 } 568 569 break; 570 571 default: 572 break; 573 } 574 575 /* 576 * Check for object names. Note that there could be 0-255 of these 577 * 4-byte elements. 578 */ 579 if (prefix_length < internal_name_length) { 580 switch (internal_name[prefix_length]) { 581 case AML_MULTI_NAME_PREFIX_OP: 582 583 /* <count> 4-byte names */ 584 585 names_index = prefix_length + 2; 586 num_segments = (acpi_native_uint) (u8) 587 internal_name[(acpi_native_uint) 588 (prefix_length + 1)]; 589 break; 590 591 case AML_DUAL_NAME_PREFIX: 592 593 /* Two 4-byte names */ 594 595 names_index = prefix_length + 1; 596 num_segments = 2; 597 break; 598 599 case 0: 600 601 /* null_name */ 602 603 names_index = 0; 604 num_segments = 0; 605 break; 606 607 default: 608 609 /* one 4-byte name */ 610 611 names_index = prefix_length; 612 num_segments = 1; 613 break; 614 } 615 } 616 617 /* 618 * Calculate the length of converted_name, which equals the length 619 * of the prefix, length of all object names, length of any required 620 * punctuation ('.') between object names, plus the NULL terminator. 621 */ 622 required_length = prefix_length + (4 * num_segments) + 623 ((num_segments > 0) ? (num_segments - 1) : 0) + 1; 624 625 /* 626 * Check to see if we're still in bounds. If not, there's a problem 627 * with internal_name (invalid format). 628 */ 629 if (required_length > internal_name_length) { 630 ACPI_REPORT_ERROR(("ns_externalize_name: Invalid internal name\n")); 631 return_ACPI_STATUS(AE_BAD_PATHNAME); 632 } 633 634 /* 635 * Build converted_name 636 */ 637 *converted_name = ACPI_MEM_CALLOCATE(required_length); 638 if (!(*converted_name)) { 639 return_ACPI_STATUS(AE_NO_MEMORY); 640 } 641 642 j = 0; 643 644 for (i = 0; i < prefix_length; i++) { 645 (*converted_name)[j++] = internal_name[i]; 646 } 647 648 if (num_segments > 0) { 649 for (i = 0; i < num_segments; i++) { 650 if (i > 0) { 651 (*converted_name)[j++] = '.'; 652 } 653 654 (*converted_name)[j++] = internal_name[names_index++]; 655 (*converted_name)[j++] = internal_name[names_index++]; 656 (*converted_name)[j++] = internal_name[names_index++]; 657 (*converted_name)[j++] = internal_name[names_index++]; 658 } 659 } 660 661 if (converted_name_length) { 662 *converted_name_length = (u32) required_length; 663 } 664 665 return_ACPI_STATUS(AE_OK); 666} 667 668/******************************************************************************* 669 * 670 * FUNCTION: acpi_ns_map_handle_to_node 671 * 672 * PARAMETERS: Handle - Handle to be converted to an Node 673 * 674 * RETURN: A Name table entry pointer 675 * 676 * DESCRIPTION: Convert a namespace handle to a real Node 677 * 678 * Note: Real integer handles would allow for more verification 679 * and keep all pointers within this subsystem - however this introduces 680 * more (and perhaps unnecessary) overhead. 681 * 682 ******************************************************************************/ 683 684struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) 685{ 686 687 ACPI_FUNCTION_ENTRY(); 688 689 /* 690 * Simple implementation. 691 */ 692 if (!handle) { 693 return (NULL); 694 } 695 696 if (handle == ACPI_ROOT_OBJECT) { 697 return (acpi_gbl_root_node); 698 } 699 700 /* We can at least attempt to verify the handle */ 701 702 if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { 703 return (NULL); 704 } 705 706 return ((struct acpi_namespace_node *)handle); 707} 708 709/******************************************************************************* 710 * 711 * FUNCTION: acpi_ns_convert_entry_to_handle 712 * 713 * PARAMETERS: Node - Node to be converted to a Handle 714 * 715 * RETURN: A user handle 716 * 717 * DESCRIPTION: Convert a real Node to a namespace handle 718 * 719 ******************************************************************************/ 720 721acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node) 722{ 723 724 /* 725 * Simple implementation for now; 726 */ 727 return ((acpi_handle) node); 728 729/* Example future implementation --------------------- 730 731 if (!Node) 732 { 733 return (NULL); 734 } 735 736 if (Node == acpi_gbl_root_node) 737 { 738 return (ACPI_ROOT_OBJECT); 739 } 740 741 return ((acpi_handle) Node); 742------------------------------------------------------*/ 743} 744 745/******************************************************************************* 746 * 747 * FUNCTION: acpi_ns_terminate 748 * 749 * PARAMETERS: none 750 * 751 * RETURN: none 752 * 753 * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 754 * 755 ******************************************************************************/ 756 757void acpi_ns_terminate(void) 758{ 759 union acpi_operand_object *obj_desc; 760 761 ACPI_FUNCTION_TRACE("ns_terminate"); 762 763 /* 764 * 1) Free the entire namespace -- all nodes and objects 765 * 766 * Delete all object descriptors attached to namepsace nodes 767 */ 768 acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); 769 770 /* Detach any objects attached to the root */ 771 772 obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); 773 if (obj_desc) { 774 acpi_ns_detach_object(acpi_gbl_root_node); 775 } 776 777 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); 778 779 /* 780 * 2) Now we can delete the ACPI tables 781 */ 782 acpi_tb_delete_all_tables(); 783 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); 784 785 return_VOID; 786} 787 788/******************************************************************************* 789 * 790 * FUNCTION: acpi_ns_opens_scope 791 * 792 * PARAMETERS: Type - A valid namespace type 793 * 794 * RETURN: NEWSCOPE if the passed type "opens a name scope" according 795 * to the ACPI specification, else 0 796 * 797 ******************************************************************************/ 798 799u32 acpi_ns_opens_scope(acpi_object_type type) 800{ 801 ACPI_FUNCTION_TRACE_STR("ns_opens_scope", acpi_ut_get_type_name(type)); 802 803 if (!acpi_ut_valid_object_type(type)) { 804 /* type code out of range */ 805 806 ACPI_REPORT_WARNING(("ns_opens_scope: Invalid Object Type %X\n", 807 type)); 808 return_VALUE(ACPI_NS_NORMAL); 809 } 810 811 return_VALUE(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); 812} 813 814/******************************************************************************* 815 * 816 * FUNCTION: acpi_ns_get_node_by_path 817 * 818 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The 819 * \ (backslash) and ^ (carat) prefixes, and the 820 * . (period) to separate segments are supported. 821 * start_node - Root of subtree to be searched, or NS_ALL for the 822 * root of the name space. If Name is fully 823 * qualified (first s8 is '\'), the passed value 824 * of Scope will not be accessed. 825 * Flags - Used to indicate whether to perform upsearch or 826 * not. 827 * return_node - Where the Node is returned 828 * 829 * DESCRIPTION: Look up a name relative to a given scope and return the 830 * corresponding Node. NOTE: Scope can be null. 831 * 832 * MUTEX: Locks namespace 833 * 834 ******************************************************************************/ 835 836acpi_status 837acpi_ns_get_node_by_path(char *pathname, 838 struct acpi_namespace_node *start_node, 839 u32 flags, struct acpi_namespace_node **return_node) 840{ 841 union acpi_generic_state scope_info; 842 acpi_status status; 843 char *internal_path = NULL; 844 845 ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname); 846 847 if (pathname) { 848 /* Convert path to internal representation */ 849 850 status = acpi_ns_internalize_name(pathname, &internal_path); 851 if (ACPI_FAILURE(status)) { 852 return_ACPI_STATUS(status); 853 } 854 } 855 856 /* Must lock namespace during lookup */ 857 858 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 859 if (ACPI_FAILURE(status)) { 860 goto cleanup; 861 } 862 863 /* Setup lookup scope (search starting point) */ 864 865 scope_info.scope.node = start_node; 866 867 /* Lookup the name in the namespace */ 868 869 status = acpi_ns_lookup(&scope_info, internal_path, 870 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 871 (flags | ACPI_NS_DONT_OPEN_SCOPE), 872 NULL, return_node); 873 if (ACPI_FAILURE(status)) { 874 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", 875 internal_path, 876 acpi_format_exception(status))); 877 } 878 879 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 880 881 cleanup: 882 if (internal_path) { 883 ACPI_MEM_FREE(internal_path); 884 } 885 return_ACPI_STATUS(status); 886} 887 888/******************************************************************************* 889 * 890 * FUNCTION: acpi_ns_get_parent_node 891 * 892 * PARAMETERS: Node - Current table entry 893 * 894 * RETURN: Parent entry of the given entry 895 * 896 * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. 897 * 898 ******************************************************************************/ 899 900struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node 901 *node) 902{ 903 ACPI_FUNCTION_ENTRY(); 904 905 if (!node) { 906 return (NULL); 907 } 908 909 /* 910 * Walk to the end of this peer list. The last entry is marked with a flag 911 * and the peer pointer is really a pointer back to the parent. This saves 912 * putting a parent back pointer in each and every named object! 913 */ 914 while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { 915 node = node->peer; 916 } 917 918 return (node->peer); 919} 920 921/******************************************************************************* 922 * 923 * FUNCTION: acpi_ns_get_next_valid_node 924 * 925 * PARAMETERS: Node - Current table entry 926 * 927 * RETURN: Next valid Node in the linked node list. NULL if no more valid 928 * nodes. 929 * 930 * DESCRIPTION: Find the next valid node within a name table. 931 * Useful for implementing NULL-end-of-list loops. 932 * 933 ******************************************************************************/ 934 935struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct 936 acpi_namespace_node 937 *node) 938{ 939 940 /* If we are at the end of this peer list, return NULL */ 941 942 if (node->flags & ANOBJ_END_OF_PEER_LIST) { 943 return NULL; 944 } 945 946 /* Otherwise just return the next peer */ 947 948 return (node->peer); 949} 950 951#ifdef ACPI_OBSOLETE_FUNCTIONS 952/******************************************************************************* 953 * 954 * FUNCTION: acpi_ns_find_parent_name 955 * 956 * PARAMETERS: *child_node - Named Obj whose name is to be found 957 * 958 * RETURN: The ACPI name 959 * 960 * DESCRIPTION: Search for the given obj in its parent scope and return the 961 * name segment, or "????" if the parent name can't be found 962 * (which "should not happen"). 963 * 964 ******************************************************************************/ 965 966acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) 967{ 968 struct acpi_namespace_node *parent_node; 969 970 ACPI_FUNCTION_TRACE("ns_find_parent_name"); 971 972 if (child_node) { 973 /* Valid entry. Get the parent Node */ 974 975 parent_node = acpi_ns_get_parent_node(child_node); 976 if (parent_node) { 977 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 978 "Parent of %p [%4.4s] is %p [%4.4s]\n", 979 child_node, 980 acpi_ut_get_node_name(child_node), 981 parent_node, 982 acpi_ut_get_node_name(parent_node))); 983 984 if (parent_node->name.integer) { 985 return_VALUE((acpi_name) parent_node->name. 986 integer); 987 } 988 } 989 990 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 991 "Unable to find parent of %p (%4.4s)\n", 992 child_node, 993 acpi_ut_get_node_name(child_node))); 994 } 995 996 return_VALUE(ACPI_UNKNOWN_NAME); 997} 998#endif