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