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