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, internal_name); 92 acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_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_FREE(name); 109 } 110 } 111 112 acpi_os_printf(" Namespace lookup failure, %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 * Message - Error message to use on failure 123 * prefix_node - Prefix relative to the path 124 * Path - Path to the node (optional) 125 * method_status - Execution status 126 * 127 * RETURN: None 128 * 129 * DESCRIPTION: Print warning message with full pathname 130 * 131 ******************************************************************************/ 132 133 void 134 acpi_ns_report_method_error(const char *module_name, 135 u32 line_number, 136 const char *message, 137 struct acpi_namespace_node *prefix_node, 138 const char *path, acpi_status method_status) 139 { 140 acpi_status status; 141 struct acpi_namespace_node *node = prefix_node; 142 143 acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); 144 145 if (path) { 146 status = 147 acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, 148 &node); 149 if (ACPI_FAILURE(status)) { 150 acpi_os_printf("[Could not get node by pathname]"); 151 } 152 } 153 154 acpi_ns_print_node_pathname(node, message); 155 acpi_os_printf(", %s\n", acpi_format_exception(method_status)); 156 } 157 158 /******************************************************************************* 159 * 160 * FUNCTION: acpi_ns_print_node_pathname 161 * 162 * PARAMETERS: Node - Object 163 * Message - Prefix message 164 * 165 * DESCRIPTION: Print an object's full namespace pathname 166 * Manages allocation/freeing of a pathname buffer 167 * 168 ******************************************************************************/ 169 170 void 171 acpi_ns_print_node_pathname(struct acpi_namespace_node *node, 172 const char *message) 173 { 174 struct acpi_buffer buffer; 175 acpi_status status; 176 177 if (!node) { 178 acpi_os_printf("[NULL NAME]"); 179 return; 180 } 181 182 /* Convert handle to full pathname and print it (with supplied message) */ 183 184 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 185 186 status = acpi_ns_handle_to_pathname(node, &buffer); 187 if (ACPI_SUCCESS(status)) { 188 if (message) { 189 acpi_os_printf("%s ", message); 190 } 191 192 acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node); 193 ACPI_FREE(buffer.pointer); 194 } 195 } 196 197 /******************************************************************************* 198 * 199 * FUNCTION: acpi_ns_valid_root_prefix 200 * 201 * PARAMETERS: Prefix - Character to be checked 202 * 203 * RETURN: TRUE if a valid prefix 204 * 205 * DESCRIPTION: Check if a character is a valid ACPI Root prefix 206 * 207 ******************************************************************************/ 208 209 u8 acpi_ns_valid_root_prefix(char prefix) 210 { 211 212 return ((u8) (prefix == '\\')); 213 } 214 215 /******************************************************************************* 216 * 217 * FUNCTION: acpi_ns_valid_path_separator 218 * 219 * PARAMETERS: Sep - Character to be checked 220 * 221 * RETURN: TRUE if a valid path separator 222 * 223 * DESCRIPTION: Check if a character is a valid ACPI path separator 224 * 225 ******************************************************************************/ 226 227 static u8 acpi_ns_valid_path_separator(char sep) 228 { 229 230 return ((u8) (sep == '.')); 231 } 232 233 /******************************************************************************* 234 * 235 * FUNCTION: acpi_ns_get_type 236 * 237 * PARAMETERS: Node - Parent Node to be examined 238 * 239 * RETURN: Type field from Node whose handle is passed 240 * 241 * DESCRIPTION: Return the type of a Namespace node 242 * 243 ******************************************************************************/ 244 245 acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) 246 { 247 ACPI_FUNCTION_TRACE(ns_get_type); 248 249 if (!node) { 250 ACPI_WARNING((AE_INFO, "Null Node parameter")); 251 return_UINT32(ACPI_TYPE_ANY); 252 } 253 254 return_UINT32((acpi_object_type) node->type); 255 } 256 257 /******************************************************************************* 258 * 259 * FUNCTION: acpi_ns_local 260 * 261 * PARAMETERS: Type - A namespace object type 262 * 263 * RETURN: LOCAL if names must be found locally in objects of the 264 * passed type, 0 if enclosing scopes should be searched 265 * 266 * DESCRIPTION: Returns scope rule for the given object type. 267 * 268 ******************************************************************************/ 269 270 u32 acpi_ns_local(acpi_object_type type) 271 { 272 ACPI_FUNCTION_TRACE(ns_local); 273 274 if (!acpi_ut_valid_object_type(type)) { 275 276 /* Type code out of range */ 277 278 ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); 279 return_UINT32(ACPI_NS_NORMAL); 280 } 281 282 return_UINT32((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 299 void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) 300 { 301 const 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)) { 319 info->fully_qualified = TRUE; 320 next_external_char++; 321 322 /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */ 323 324 while (acpi_ns_valid_root_prefix(*next_external_char)) { 325 next_external_char++; 326 } 327 } else { 328 /* Handle Carat prefixes */ 329 330 while (*next_external_char == '^') { 331 info->num_carats++; 332 next_external_char++; 333 } 334 } 335 336 /* 337 * Determine the number of ACPI name "segments" by counting the number of 338 * path separators within the string. Start with one segment since the 339 * segment count is [(# separators) + 1], and zero separators is ok. 340 */ 341 if (*next_external_char) { 342 info->num_segments = 1; 343 for (i = 0; next_external_char[i]; i++) { 344 if (acpi_ns_valid_path_separator(next_external_char[i])) { 345 info->num_segments++; 346 } 347 } 348 } 349 350 info->length = (ACPI_NAME_SIZE * info->num_segments) + 351 4 + info->num_carats; 352 353 info->next_external_char = next_external_char; 354 } 355 356 /******************************************************************************* 357 * 358 * FUNCTION: acpi_ns_build_internal_name 359 * 360 * PARAMETERS: Info - Info struct fully initialized 361 * 362 * RETURN: Status 363 * 364 * DESCRIPTION: Construct the internal (AML) namestring 365 * corresponding to the external (ASL) namestring. 366 * 367 ******************************************************************************/ 368 369 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) 370 { 371 u32 num_segments = info->num_segments; 372 char *internal_name = info->internal_name; 373 const char *external_name = info->next_external_char; 374 char *result = NULL; 375 u32 i; 376 377 ACPI_FUNCTION_TRACE(ns_build_internal_name); 378 379 /* Setup the correct prefixes, counts, and pointers */ 380 381 if (info->fully_qualified) { 382 internal_name[0] = '\\'; 383 384 if (num_segments <= 1) { 385 result = &internal_name[1]; 386 } else if (num_segments == 2) { 387 internal_name[1] = AML_DUAL_NAME_PREFIX; 388 result = &internal_name[2]; 389 } else { 390 internal_name[1] = AML_MULTI_NAME_PREFIX_OP; 391 internal_name[2] = (char)num_segments; 392 result = &internal_name[3]; 393 } 394 } else { 395 /* 396 * Not fully qualified. 397 * Handle Carats first, then append the name segments 398 */ 399 i = 0; 400 if (info->num_carats) { 401 for (i = 0; i < info->num_carats; i++) { 402 internal_name[i] = '^'; 403 } 404 } 405 406 if (num_segments <= 1) { 407 result = &internal_name[i]; 408 } else if (num_segments == 2) { 409 internal_name[i] = AML_DUAL_NAME_PREFIX; 410 result = &internal_name[(acpi_size) i + 1]; 411 } else { 412 internal_name[i] = AML_MULTI_NAME_PREFIX_OP; 413 internal_name[(acpi_size) i + 1] = (char)num_segments; 414 result = &internal_name[(acpi_size) i + 2]; 415 } 416 } 417 418 /* Build the name (minus path separators) */ 419 420 for (; num_segments; num_segments--) { 421 for (i = 0; i < ACPI_NAME_SIZE; i++) { 422 if (acpi_ns_valid_path_separator(*external_name) || 423 (*external_name == 0)) { 424 425 /* Pad the segment with underscore(s) if segment is short */ 426 427 result[i] = '_'; 428 } else { 429 /* Convert the character to uppercase and save it */ 430 431 result[i] = 432 (char)ACPI_TOUPPER((int)*external_name); 433 external_name++; 434 } 435 } 436 437 /* Now we must have a path separator, or the pathname is bad */ 438 439 if (!acpi_ns_valid_path_separator(*external_name) && 440 (*external_name != 0)) { 441 return_ACPI_STATUS(AE_BAD_PARAMETER); 442 } 443 444 /* Move on the next segment */ 445 446 external_name++; 447 result += ACPI_NAME_SIZE; 448 } 449 450 /* Terminate the string */ 451 452 *result = 0; 453 454 if (info->fully_qualified) { 455 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 456 "Returning [%p] (abs) \"\\%s\"\n", 457 internal_name, internal_name)); 458 } else { 459 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", 460 internal_name, internal_name)); 461 } 462 463 return_ACPI_STATUS(AE_OK); 464 } 465 466 /******************************************************************************* 467 * 468 * FUNCTION: acpi_ns_internalize_name 469 * 470 * PARAMETERS: *external_name - External representation of name 471 * **Converted Name - Where to return the resulting 472 * internal represention of the name 473 * 474 * RETURN: Status 475 * 476 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") 477 * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 478 * 479 *******************************************************************************/ 480 481 acpi_status 482 acpi_ns_internalize_name(const char *external_name, char **converted_name) 483 { 484 char *internal_name; 485 struct acpi_namestring_info info; 486 acpi_status status; 487 488 ACPI_FUNCTION_TRACE(ns_internalize_name); 489 490 if ((!external_name) || (*external_name == 0) || (!converted_name)) { 491 return_ACPI_STATUS(AE_BAD_PARAMETER); 492 } 493 494 /* Get the length of the new internal name */ 495 496 info.external_name = external_name; 497 acpi_ns_get_internal_name_length(&info); 498 499 /* We need a segment to store the internal name */ 500 501 internal_name = ACPI_ALLOCATE_ZEROED(info.length); 502 if (!internal_name) { 503 return_ACPI_STATUS(AE_NO_MEMORY); 504 } 505 506 /* Build the name */ 507 508 info.internal_name = internal_name; 509 status = acpi_ns_build_internal_name(&info); 510 if (ACPI_FAILURE(status)) { 511 ACPI_FREE(internal_name); 512 return_ACPI_STATUS(status); 513 } 514 515 *converted_name = internal_name; 516 return_ACPI_STATUS(AE_OK); 517 } 518 519 /******************************************************************************* 520 * 521 * FUNCTION: acpi_ns_externalize_name 522 * 523 * PARAMETERS: internal_name_length - Lenth of the internal name below 524 * internal_name - Internal representation of name 525 * converted_name_length - Where the length is returned 526 * converted_name - Where the resulting external name 527 * is returned 528 * 529 * RETURN: Status 530 * 531 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 532 * to its external (printable) form (e.g. "\_PR_.CPU0") 533 * 534 ******************************************************************************/ 535 536 acpi_status 537 acpi_ns_externalize_name(u32 internal_name_length, 538 const char *internal_name, 539 u32 * converted_name_length, char **converted_name) 540 { 541 u32 names_index = 0; 542 u32 num_segments = 0; 543 u32 required_length; 544 u32 prefix_length = 0; 545 u32 i = 0; 546 u32 j = 0; 547 548 ACPI_FUNCTION_TRACE(ns_externalize_name); 549 550 if (!internal_name_length || !internal_name || !converted_name) { 551 return_ACPI_STATUS(AE_BAD_PARAMETER); 552 } 553 554 /* Check for a prefix (one '\' | one or more '^') */ 555 556 switch (internal_name[0]) { 557 case '\\': 558 prefix_length = 1; 559 break; 560 561 case '^': 562 for (i = 0; i < internal_name_length; i++) { 563 if (internal_name[i] == '^') { 564 prefix_length = i + 1; 565 } else { 566 break; 567 } 568 } 569 570 if (i == internal_name_length) { 571 prefix_length = i; 572 } 573 574 break; 575 576 default: 577 break; 578 } 579 580 /* 581 * Check for object names. Note that there could be 0-255 of these 582 * 4-byte elements. 583 */ 584 if (prefix_length < internal_name_length) { 585 switch (internal_name[prefix_length]) { 586 case AML_MULTI_NAME_PREFIX_OP: 587 588 /* <count> 4-byte names */ 589 590 names_index = prefix_length + 2; 591 num_segments = (u8) 592 internal_name[(acpi_size) prefix_length + 1]; 593 break; 594 595 case AML_DUAL_NAME_PREFIX: 596 597 /* Two 4-byte names */ 598 599 names_index = prefix_length + 1; 600 num_segments = 2; 601 break; 602 603 case 0: 604 605 /* null_name */ 606 607 names_index = 0; 608 num_segments = 0; 609 break; 610 611 default: 612 613 /* one 4-byte name */ 614 615 names_index = prefix_length; 616 num_segments = 1; 617 break; 618 } 619 } 620 621 /* 622 * Calculate the length of converted_name, which equals the length 623 * of the prefix, length of all object names, length of any required 624 * punctuation ('.') between object names, plus the NULL terminator. 625 */ 626 required_length = prefix_length + (4 * num_segments) + 627 ((num_segments > 0) ? (num_segments - 1) : 0) + 1; 628 629 /* 630 * Check to see if we're still in bounds. If not, there's a problem 631 * with internal_name (invalid format). 632 */ 633 if (required_length > internal_name_length) { 634 ACPI_ERROR((AE_INFO, "Invalid internal name")); 635 return_ACPI_STATUS(AE_BAD_PATHNAME); 636 } 637 638 /* Build the converted_name */ 639 640 *converted_name = ACPI_ALLOCATE_ZEROED(required_length); 641 if (!(*converted_name)) { 642 return_ACPI_STATUS(AE_NO_MEMORY); 643 } 644 645 j = 0; 646 647 for (i = 0; i < prefix_length; i++) { 648 (*converted_name)[j++] = internal_name[i]; 649 } 650 651 if (num_segments > 0) { 652 for (i = 0; i < num_segments; i++) { 653 if (i > 0) { 654 (*converted_name)[j++] = '.'; 655 } 656 657 (*converted_name)[j++] = internal_name[names_index++]; 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 } 662 } 663 664 if (converted_name_length) { 665 *converted_name_length = (u32) required_length; 666 } 667 668 return_ACPI_STATUS(AE_OK); 669 } 670 671 /******************************************************************************* 672 * 673 * FUNCTION: acpi_ns_map_handle_to_node 674 * 675 * PARAMETERS: Handle - Handle to be converted to an Node 676 * 677 * RETURN: A Name table entry pointer 678 * 679 * DESCRIPTION: Convert a namespace handle to a real Node 680 * 681 * Note: Real integer handles would allow for more verification 682 * and keep all pointers within this subsystem - however this introduces 683 * more (and perhaps unnecessary) overhead. 684 * 685 * The current implemenation is basically a placeholder until such time comes 686 * that it is needed. 687 * 688 ******************************************************************************/ 689 690 struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) 691 { 692 693 ACPI_FUNCTION_ENTRY(); 694 695 /* Parameter validation */ 696 697 if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { 698 return (acpi_gbl_root_node); 699 } 700 701 /* We can at least attempt to verify the handle */ 702 703 if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { 704 return (NULL); 705 } 706 707 return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); 708 } 709 710 /******************************************************************************* 711 * 712 * FUNCTION: acpi_ns_convert_entry_to_handle 713 * 714 * PARAMETERS: Node - Node to be converted to a Handle 715 * 716 * RETURN: A user handle 717 * 718 * DESCRIPTION: Convert a real Node to a namespace handle 719 * 720 ******************************************************************************/ 721 722 acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node) 723 { 724 725 /* 726 * Simple implementation for now; 727 */ 728 return ((acpi_handle) node); 729 730 /* Example future implementation --------------------- 731 732 if (!Node) 733 { 734 return (NULL); 735 } 736 737 if (Node == acpi_gbl_root_node) 738 { 739 return (ACPI_ROOT_OBJECT); 740 } 741 742 return ((acpi_handle) Node); 743 ------------------------------------------------------*/ 744 } 745 746 /******************************************************************************* 747 * 748 * FUNCTION: acpi_ns_terminate 749 * 750 * PARAMETERS: none 751 * 752 * RETURN: none 753 * 754 * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 755 * 756 ******************************************************************************/ 757 758 void acpi_ns_terminate(void) 759 { 760 union acpi_operand_object *obj_desc; 761 762 ACPI_FUNCTION_TRACE(ns_terminate); 763 764 /* 765 * 1) Free the entire namespace -- all nodes and objects 766 * 767 * Delete all object descriptors attached to namepsace nodes 768 */ 769 acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); 770 771 /* Detach any objects attached to the root */ 772 773 obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); 774 if (obj_desc) { 775 acpi_ns_detach_object(acpi_gbl_root_node); 776 } 777 778 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); 779 return_VOID; 780 } 781 782 /******************************************************************************* 783 * 784 * FUNCTION: acpi_ns_opens_scope 785 * 786 * PARAMETERS: Type - A valid namespace type 787 * 788 * RETURN: NEWSCOPE if the passed type "opens a name scope" according 789 * to the ACPI specification, else 0 790 * 791 ******************************************************************************/ 792 793 u32 acpi_ns_opens_scope(acpi_object_type type) 794 { 795 ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); 796 797 if (!acpi_ut_valid_object_type(type)) { 798 799 /* type code out of range */ 800 801 ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); 802 return_UINT32(ACPI_NS_NORMAL); 803 } 804 805 return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); 806 } 807 808 /******************************************************************************* 809 * 810 * FUNCTION: acpi_ns_get_node 811 * 812 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The 813 * \ (backslash) and ^ (carat) prefixes, and the 814 * . (period) to separate segments are supported. 815 * prefix_node - Root of subtree to be searched, or NS_ALL for the 816 * root of the name space. If Name is fully 817 * qualified (first s8 is '\'), the passed value 818 * of Scope will not be accessed. 819 * Flags - Used to indicate whether to perform upsearch or 820 * not. 821 * return_node - Where the Node is returned 822 * 823 * DESCRIPTION: Look up a name relative to a given scope and return the 824 * corresponding Node. NOTE: Scope can be null. 825 * 826 * MUTEX: Locks namespace 827 * 828 ******************************************************************************/ 829 830 acpi_status 831 acpi_ns_get_node(struct acpi_namespace_node *prefix_node, 832 const char *pathname, 833 u32 flags, struct acpi_namespace_node **return_node) 834 { 835 union acpi_generic_state scope_info; 836 acpi_status status; 837 char *internal_path; 838 839 ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); 840 841 if (!pathname) { 842 *return_node = prefix_node; 843 if (!prefix_node) { 844 *return_node = acpi_gbl_root_node; 845 } 846 return_ACPI_STATUS(AE_OK); 847 } 848 849 /* Convert path to internal representation */ 850 851 status = acpi_ns_internalize_name(pathname, &internal_path); 852 if (ACPI_FAILURE(status)) { 853 return_ACPI_STATUS(status); 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 = prefix_node; 866 867 /* Lookup the name in the namespace */ 868 869 status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, 870 ACPI_IMODE_EXECUTE, 871 (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, 872 return_node); 873 if (ACPI_FAILURE(status)) { 874 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n", 875 pathname, acpi_format_exception(status))); 876 } 877 878 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 879 880 cleanup: 881 ACPI_FREE(internal_path); 882 return_ACPI_STATUS(status); 883 } 884 885 /******************************************************************************* 886 * 887 * FUNCTION: acpi_ns_get_parent_node 888 * 889 * PARAMETERS: Node - Current table entry 890 * 891 * RETURN: Parent entry of the given entry 892 * 893 * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. 894 * 895 ******************************************************************************/ 896 897 struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node 898 *node) 899 { 900 ACPI_FUNCTION_ENTRY(); 901 902 if (!node) { 903 return (NULL); 904 } 905 906 /* 907 * Walk to the end of this peer list. The last entry is marked with a flag 908 * and the peer pointer is really a pointer back to the parent. This saves 909 * putting a parent back pointer in each and every named object! 910 */ 911 while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { 912 node = node->peer; 913 } 914 915 return (node->peer); 916 } 917 918 /******************************************************************************* 919 * 920 * FUNCTION: acpi_ns_get_next_valid_node 921 * 922 * PARAMETERS: Node - Current table entry 923 * 924 * RETURN: Next valid Node in the linked node list. NULL if no more valid 925 * nodes. 926 * 927 * DESCRIPTION: Find the next valid node within a name table. 928 * Useful for implementing NULL-end-of-list loops. 929 * 930 ******************************************************************************/ 931 932 struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct 933 acpi_namespace_node 934 *node) 935 { 936 937 /* If we are at the end of this peer list, return NULL */ 938 939 if (node->flags & ANOBJ_END_OF_PEER_LIST) { 940 return NULL; 941 } 942 943 /* Otherwise just return the next peer */ 944 945 return (node->peer); 946 } 947 948 #ifdef ACPI_OBSOLETE_FUNCTIONS 949 /******************************************************************************* 950 * 951 * FUNCTION: acpi_ns_find_parent_name 952 * 953 * PARAMETERS: *child_node - Named Obj whose name is to be found 954 * 955 * RETURN: The ACPI name 956 * 957 * DESCRIPTION: Search for the given obj in its parent scope and return the 958 * name segment, or "????" if the parent name can't be found 959 * (which "should not happen"). 960 * 961 ******************************************************************************/ 962 963 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) 964 { 965 struct acpi_namespace_node *parent_node; 966 967 ACPI_FUNCTION_TRACE(ns_find_parent_name); 968 969 if (child_node) { 970 971 /* Valid entry. Get the parent Node */ 972 973 parent_node = acpi_ns_get_parent_node(child_node); 974 if (parent_node) { 975 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 976 "Parent of %p [%4.4s] is %p [%4.4s]\n", 977 child_node, 978 acpi_ut_get_node_name(child_node), 979 parent_node, 980 acpi_ut_get_node_name(parent_node))); 981 982 if (parent_node->name.integer) { 983 return_VALUE((acpi_name) parent_node->name. 984 integer); 985 } 986 } 987 988 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 989 "Unable to find parent of %p (%4.4s)\n", 990 child_node, 991 acpi_ut_get_node_name(child_node))); 992 } 993 994 return_VALUE(ACPI_UNKNOWN_NAME); 995 } 996 #endif 997