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_map_handle_to_node 675 * 676 * PARAMETERS: Handle - Handle to be converted to an Node 677 * 678 * RETURN: A Name table entry pointer 679 * 680 * DESCRIPTION: Convert a namespace handle to a real Node 681 * 682 * Note: Real integer handles would allow for more verification 683 * and keep all pointers within this subsystem - however this introduces 684 * more (and perhaps unnecessary) overhead. 685 * 686 * The current implemenation is basically a placeholder until such time comes 687 * that it is needed. 688 * 689 ******************************************************************************/ 690 691 struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) 692 { 693 694 ACPI_FUNCTION_ENTRY(); 695 696 /* Parameter validation */ 697 698 if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { 699 return (acpi_gbl_root_node); 700 } 701 702 /* We can at least attempt to verify the handle */ 703 704 if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) { 705 return (NULL); 706 } 707 708 return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); 709 } 710 711 /******************************************************************************* 712 * 713 * FUNCTION: acpi_ns_convert_entry_to_handle 714 * 715 * PARAMETERS: Node - Node to be converted to a Handle 716 * 717 * RETURN: A user handle 718 * 719 * DESCRIPTION: Convert a real Node to a namespace handle 720 * 721 ******************************************************************************/ 722 723 acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node) 724 { 725 726 /* 727 * Simple implementation for now; 728 */ 729 return ((acpi_handle) node); 730 731 /* Example future implementation --------------------- 732 733 if (!Node) 734 { 735 return (NULL); 736 } 737 738 if (Node == acpi_gbl_root_node) 739 { 740 return (ACPI_ROOT_OBJECT); 741 } 742 743 return ((acpi_handle) Node); 744 ------------------------------------------------------*/ 745 } 746 747 /******************************************************************************* 748 * 749 * FUNCTION: acpi_ns_terminate 750 * 751 * PARAMETERS: none 752 * 753 * RETURN: none 754 * 755 * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 756 * 757 ******************************************************************************/ 758 759 void acpi_ns_terminate(void) 760 { 761 union acpi_operand_object *obj_desc; 762 763 ACPI_FUNCTION_TRACE(ns_terminate); 764 765 /* 766 * 1) Free the entire namespace -- all nodes and objects 767 * 768 * Delete all object descriptors attached to namepsace nodes 769 */ 770 acpi_ns_delete_namespace_subtree(acpi_gbl_root_node); 771 772 /* Detach any objects attached to the root */ 773 774 obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); 775 if (obj_desc) { 776 acpi_ns_detach_object(acpi_gbl_root_node); 777 } 778 779 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); 780 return_VOID; 781 } 782 783 /******************************************************************************* 784 * 785 * FUNCTION: acpi_ns_opens_scope 786 * 787 * PARAMETERS: Type - A valid namespace type 788 * 789 * RETURN: NEWSCOPE if the passed type "opens a name scope" according 790 * to the ACPI specification, else 0 791 * 792 ******************************************************************************/ 793 794 u32 acpi_ns_opens_scope(acpi_object_type type) 795 { 796 ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); 797 798 if (!acpi_ut_valid_object_type(type)) { 799 800 /* type code out of range */ 801 802 ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); 803 return_UINT32(ACPI_NS_NORMAL); 804 } 805 806 return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); 807 } 808 809 /******************************************************************************* 810 * 811 * FUNCTION: acpi_ns_get_node 812 * 813 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The 814 * \ (backslash) and ^ (carat) prefixes, and the 815 * . (period) to separate segments are supported. 816 * prefix_node - Root of subtree to be searched, or NS_ALL for the 817 * root of the name space. If Name is fully 818 * qualified (first s8 is '\'), the passed value 819 * of Scope will not be accessed. 820 * Flags - Used to indicate whether to perform upsearch or 821 * not. 822 * return_node - Where the Node is returned 823 * 824 * DESCRIPTION: Look up a name relative to a given scope and return the 825 * corresponding Node. NOTE: Scope can be null. 826 * 827 * MUTEX: Locks namespace 828 * 829 ******************************************************************************/ 830 831 acpi_status 832 acpi_ns_get_node(struct acpi_namespace_node *prefix_node, 833 const char *pathname, 834 u32 flags, struct acpi_namespace_node **return_node) 835 { 836 union acpi_generic_state scope_info; 837 acpi_status status; 838 char *internal_path; 839 840 ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); 841 842 if (!pathname) { 843 *return_node = prefix_node; 844 if (!prefix_node) { 845 *return_node = acpi_gbl_root_node; 846 } 847 return_ACPI_STATUS(AE_OK); 848 } 849 850 /* Convert path to internal representation */ 851 852 status = acpi_ns_internalize_name(pathname, &internal_path); 853 if (ACPI_FAILURE(status)) { 854 return_ACPI_STATUS(status); 855 } 856 857 /* Must lock namespace during lookup */ 858 859 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 860 if (ACPI_FAILURE(status)) { 861 goto cleanup; 862 } 863 864 /* Setup lookup scope (search starting point) */ 865 866 scope_info.scope.node = prefix_node; 867 868 /* Lookup the name in the namespace */ 869 870 status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, 871 ACPI_IMODE_EXECUTE, 872 (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, 873 return_node); 874 if (ACPI_FAILURE(status)) { 875 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n", 876 pathname, acpi_format_exception(status))); 877 } 878 879 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 880 881 cleanup: 882 ACPI_FREE(internal_path); 883 return_ACPI_STATUS(status); 884 } 885 886 /******************************************************************************* 887 * 888 * FUNCTION: acpi_ns_get_parent_node 889 * 890 * PARAMETERS: Node - Current table entry 891 * 892 * RETURN: Parent entry of the given entry 893 * 894 * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. 895 * 896 ******************************************************************************/ 897 898 struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node 899 *node) 900 { 901 ACPI_FUNCTION_ENTRY(); 902 903 if (!node) { 904 return (NULL); 905 } 906 907 /* 908 * Walk to the end of this peer list. The last entry is marked with a flag 909 * and the peer pointer is really a pointer back to the parent. This saves 910 * putting a parent back pointer in each and every named object! 911 */ 912 while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { 913 node = node->peer; 914 } 915 916 return (node->peer); 917 } 918 919 /******************************************************************************* 920 * 921 * FUNCTION: acpi_ns_get_next_valid_node 922 * 923 * PARAMETERS: Node - Current table entry 924 * 925 * RETURN: Next valid Node in the linked node list. NULL if no more valid 926 * nodes. 927 * 928 * DESCRIPTION: Find the next valid node within a name table. 929 * Useful for implementing NULL-end-of-list loops. 930 * 931 ******************************************************************************/ 932 933 struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct 934 acpi_namespace_node 935 *node) 936 { 937 938 /* If we are at the end of this peer list, return NULL */ 939 940 if (node->flags & ANOBJ_END_OF_PEER_LIST) { 941 return NULL; 942 } 943 944 /* Otherwise just return the next peer */ 945 946 return (node->peer); 947 } 948 949 #ifdef ACPI_OBSOLETE_FUNCTIONS 950 /******************************************************************************* 951 * 952 * FUNCTION: acpi_ns_find_parent_name 953 * 954 * PARAMETERS: *child_node - Named Obj whose name is to be found 955 * 956 * RETURN: The ACPI name 957 * 958 * DESCRIPTION: Search for the given obj in its parent scope and return the 959 * name segment, or "????" if the parent name can't be found 960 * (which "should not happen"). 961 * 962 ******************************************************************************/ 963 964 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node) 965 { 966 struct acpi_namespace_node *parent_node; 967 968 ACPI_FUNCTION_TRACE(ns_find_parent_name); 969 970 if (child_node) { 971 972 /* Valid entry. Get the parent Node */ 973 974 parent_node = acpi_ns_get_parent_node(child_node); 975 if (parent_node) { 976 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 977 "Parent of %p [%4.4s] is %p [%4.4s]\n", 978 child_node, 979 acpi_ut_get_node_name(child_node), 980 parent_node, 981 acpi_ut_get_node_name(parent_node))); 982 983 if (parent_node->name.integer) { 984 return_VALUE((acpi_name) parent_node->name. 985 integer); 986 } 987 } 988 989 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 990 "Unable to find parent of %p (%4.4s)\n", 991 child_node, 992 acpi_ut_get_node_name(child_node))); 993 } 994 995 return_VALUE(ACPI_UNKNOWN_NAME); 996 } 997 #endif 998