1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /******************************************************************************* 3 * 4 * Module Name: dbnames - Debugger commands for the acpi namespace 5 * 6 ******************************************************************************/ 7 8 #include <acpi/acpi.h> 9 #include "accommon.h" 10 #include "acnamesp.h" 11 #include "acdebug.h" 12 #include "acpredef.h" 13 14 #define _COMPONENT ACPI_CA_DEBUGGER 15 ACPI_MODULE_NAME("dbnames") 16 17 /* Local prototypes */ 18 static acpi_status 19 acpi_db_walk_and_match_name(acpi_handle obj_handle, 20 u32 nesting_level, 21 void *context, void **return_value); 22 23 static acpi_status 24 acpi_db_walk_for_predefined_names(acpi_handle obj_handle, 25 u32 nesting_level, 26 void *context, void **return_value); 27 28 static acpi_status 29 acpi_db_walk_for_specific_objects(acpi_handle obj_handle, 30 u32 nesting_level, 31 void *context, void **return_value); 32 33 static acpi_status 34 acpi_db_walk_for_object_counts(acpi_handle obj_handle, 35 u32 nesting_level, 36 void *context, void **return_value); 37 38 static acpi_status 39 acpi_db_integrity_walk(acpi_handle obj_handle, 40 u32 nesting_level, void *context, void **return_value); 41 42 static acpi_status 43 acpi_db_walk_for_references(acpi_handle obj_handle, 44 u32 nesting_level, 45 void *context, void **return_value); 46 47 static acpi_status 48 acpi_db_bus_walk(acpi_handle obj_handle, 49 u32 nesting_level, void *context, void **return_value); 50 51 /* 52 * Arguments for the Objects command 53 * These object types map directly to the ACPI_TYPES 54 */ 55 static struct acpi_db_argument_info acpi_db_object_types[] = { 56 {"ANY"}, 57 {"INTEGERS"}, 58 {"STRINGS"}, 59 {"BUFFERS"}, 60 {"PACKAGES"}, 61 {"FIELDS"}, 62 {"DEVICES"}, 63 {"EVENTS"}, 64 {"METHODS"}, 65 {"MUTEXES"}, 66 {"REGIONS"}, 67 {"POWERRESOURCES"}, 68 {"PROCESSORS"}, 69 {"THERMALZONES"}, 70 {"BUFFERFIELDS"}, 71 {"DDBHANDLES"}, 72 {"DEBUG"}, 73 {"REGIONFIELDS"}, 74 {"BANKFIELDS"}, 75 {"INDEXFIELDS"}, 76 {"REFERENCES"}, 77 {"ALIASES"}, 78 {"METHODALIASES"}, 79 {"NOTIFY"}, 80 {"ADDRESSHANDLER"}, 81 {"RESOURCE"}, 82 {"RESOURCEFIELD"}, 83 {"SCOPES"}, 84 {NULL} /* Must be null terminated */ 85 }; 86 87 /******************************************************************************* 88 * 89 * FUNCTION: acpi_db_set_scope 90 * 91 * PARAMETERS: name - New scope path 92 * 93 * RETURN: Status 94 * 95 * DESCRIPTION: Set the "current scope" as maintained by this utility. 96 * The scope is used as a prefix to ACPI paths. 97 * 98 ******************************************************************************/ 99 100 void acpi_db_set_scope(char *name) 101 { 102 acpi_status status; 103 struct acpi_namespace_node *node; 104 105 if (!name || name[0] == 0) { 106 acpi_os_printf("Current scope: %s\n", acpi_gbl_db_scope_buf); 107 return; 108 } 109 110 acpi_db_prep_namestring(name); 111 112 if (ACPI_IS_ROOT_PREFIX(name[0])) { 113 114 /* Validate new scope from the root */ 115 116 status = acpi_ns_get_node(acpi_gbl_root_node, name, 117 ACPI_NS_NO_UPSEARCH, &node); 118 if (ACPI_FAILURE(status)) { 119 goto error_exit; 120 } 121 122 acpi_gbl_db_scope_buf[0] = 0; 123 } else { 124 /* Validate new scope relative to old scope */ 125 126 status = acpi_ns_get_node(acpi_gbl_db_scope_node, name, 127 ACPI_NS_NO_UPSEARCH, &node); 128 if (ACPI_FAILURE(status)) { 129 goto error_exit; 130 } 131 } 132 133 /* Build the final pathname */ 134 135 if (acpi_ut_safe_strcat 136 (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), name)) { 137 status = AE_BUFFER_OVERFLOW; 138 goto error_exit; 139 } 140 141 if (acpi_ut_safe_strcat 142 (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), "\\")) { 143 status = AE_BUFFER_OVERFLOW; 144 goto error_exit; 145 } 146 147 acpi_gbl_db_scope_node = node; 148 acpi_os_printf("New scope: %s\n", acpi_gbl_db_scope_buf); 149 return; 150 151 error_exit: 152 153 acpi_os_printf("Could not attach scope: %s, %s\n", 154 name, acpi_format_exception(status)); 155 } 156 157 /******************************************************************************* 158 * 159 * FUNCTION: acpi_db_dump_namespace 160 * 161 * PARAMETERS: start_arg - Node to begin namespace dump 162 * depth_arg - Maximum tree depth to be dumped 163 * 164 * RETURN: None 165 * 166 * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed 167 * with type and other information. 168 * 169 ******************************************************************************/ 170 171 void acpi_db_dump_namespace(char *start_arg, char *depth_arg) 172 { 173 acpi_handle subtree_entry = acpi_gbl_root_node; 174 u32 max_depth = ACPI_UINT32_MAX; 175 176 /* No argument given, just start at the root and dump entire namespace */ 177 178 if (start_arg) { 179 subtree_entry = acpi_db_convert_to_node(start_arg); 180 if (!subtree_entry) { 181 return; 182 } 183 184 /* Now we can check for the depth argument */ 185 186 if (depth_arg) { 187 max_depth = strtoul(depth_arg, NULL, 0); 188 } 189 } 190 191 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 192 acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n", 193 ((struct acpi_namespace_node *)subtree_entry)->name. 194 ascii, subtree_entry); 195 196 /* Display the subtree */ 197 198 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 199 acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, 200 ACPI_OWNER_ID_MAX, subtree_entry); 201 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 202 } 203 204 /******************************************************************************* 205 * 206 * FUNCTION: acpi_db_dump_namespace_paths 207 * 208 * PARAMETERS: None 209 * 210 * RETURN: None 211 * 212 * DESCRIPTION: Dump entire namespace with full object pathnames and object 213 * type information. Alternative to "namespace" command. 214 * 215 ******************************************************************************/ 216 217 void acpi_db_dump_namespace_paths(void) 218 { 219 220 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 221 acpi_os_printf("ACPI Namespace (from root):\n"); 222 223 /* Display the entire namespace */ 224 225 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 226 acpi_ns_dump_object_paths(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, 227 ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX, 228 acpi_gbl_root_node); 229 230 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 231 } 232 233 /******************************************************************************* 234 * 235 * FUNCTION: acpi_db_dump_namespace_by_owner 236 * 237 * PARAMETERS: owner_arg - Owner ID whose nodes will be displayed 238 * depth_arg - Maximum tree depth to be dumped 239 * 240 * RETURN: None 241 * 242 * DESCRIPTION: Dump elements of the namespace that are owned by the owner_id. 243 * 244 ******************************************************************************/ 245 246 void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg) 247 { 248 acpi_handle subtree_entry = acpi_gbl_root_node; 249 u32 max_depth = ACPI_UINT32_MAX; 250 acpi_owner_id owner_id; 251 252 owner_id = (acpi_owner_id)strtoul(owner_arg, NULL, 0); 253 254 /* Now we can check for the depth argument */ 255 256 if (depth_arg) { 257 max_depth = strtoul(depth_arg, NULL, 0); 258 } 259 260 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 261 acpi_os_printf("ACPI Namespace by owner %X:\n", owner_id); 262 263 /* Display the subtree */ 264 265 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 266 acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, 267 owner_id, subtree_entry); 268 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 269 } 270 271 /******************************************************************************* 272 * 273 * FUNCTION: acpi_db_walk_and_match_name 274 * 275 * PARAMETERS: Callback from walk_namespace 276 * 277 * RETURN: Status 278 * 279 * DESCRIPTION: Find a particular name/names within the namespace. Wildcards 280 * are supported -- '?' matches any character. 281 * 282 ******************************************************************************/ 283 284 static acpi_status 285 acpi_db_walk_and_match_name(acpi_handle obj_handle, 286 u32 nesting_level, 287 void *context, void **return_value) 288 { 289 acpi_status status; 290 char *requested_name = (char *)context; 291 u32 i; 292 struct acpi_buffer buffer; 293 struct acpi_walk_info info; 294 295 /* Check for a name match */ 296 297 for (i = 0; i < 4; i++) { 298 299 /* Wildcard support */ 300 301 if ((requested_name[i] != '?') && 302 (requested_name[i] != ((struct acpi_namespace_node *) 303 obj_handle)->name.ascii[i])) { 304 305 /* No match, just exit */ 306 307 return (AE_OK); 308 } 309 } 310 311 /* Get the full pathname to this object */ 312 313 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 314 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 315 if (ACPI_FAILURE(status)) { 316 acpi_os_printf("Could Not get pathname for object %p\n", 317 obj_handle); 318 } else { 319 info.owner_id = ACPI_OWNER_ID_MAX; 320 info.debug_level = ACPI_UINT32_MAX; 321 info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 322 323 acpi_os_printf("%32s", (char *)buffer.pointer); 324 (void)acpi_ns_dump_one_object(obj_handle, nesting_level, &info, 325 NULL); 326 ACPI_FREE(buffer.pointer); 327 } 328 329 return (AE_OK); 330 } 331 332 /******************************************************************************* 333 * 334 * FUNCTION: acpi_db_find_name_in_namespace 335 * 336 * PARAMETERS: name_arg - The 4-character ACPI name to find. 337 * wildcards are supported. 338 * 339 * RETURN: None 340 * 341 * DESCRIPTION: Search the namespace for a given name (with wildcards) 342 * 343 ******************************************************************************/ 344 345 acpi_status acpi_db_find_name_in_namespace(char *name_arg) 346 { 347 char acpi_name[5] = "____"; 348 char *acpi_name_ptr = acpi_name; 349 350 if (strlen(name_arg) > ACPI_NAME_SIZE) { 351 acpi_os_printf("Name must be no longer than 4 characters\n"); 352 return (AE_OK); 353 } 354 355 /* Pad out name with underscores as necessary to create a 4-char name */ 356 357 acpi_ut_strupr(name_arg); 358 while (*name_arg) { 359 *acpi_name_ptr = *name_arg; 360 acpi_name_ptr++; 361 name_arg++; 362 } 363 364 /* Walk the namespace from the root */ 365 366 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 367 ACPI_UINT32_MAX, acpi_db_walk_and_match_name, 368 NULL, acpi_name, NULL); 369 370 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 371 return (AE_OK); 372 } 373 374 /******************************************************************************* 375 * 376 * FUNCTION: acpi_db_walk_for_predefined_names 377 * 378 * PARAMETERS: Callback from walk_namespace 379 * 380 * RETURN: Status 381 * 382 * DESCRIPTION: Detect and display predefined ACPI names (names that start with 383 * an underscore) 384 * 385 ******************************************************************************/ 386 387 static acpi_status 388 acpi_db_walk_for_predefined_names(acpi_handle obj_handle, 389 u32 nesting_level, 390 void *context, void **return_value) 391 { 392 struct acpi_namespace_node *node = 393 (struct acpi_namespace_node *)obj_handle; 394 u32 *count = (u32 *)context; 395 const union acpi_predefined_info *predefined; 396 const union acpi_predefined_info *package = NULL; 397 char *pathname; 398 char string_buffer[48]; 399 400 predefined = acpi_ut_match_predefined_method(node->name.ascii); 401 if (!predefined) { 402 return (AE_OK); 403 } 404 405 pathname = acpi_ns_get_normalized_pathname(node, TRUE); 406 if (!pathname) { 407 return (AE_OK); 408 } 409 410 /* If method returns a package, the info is in the next table entry */ 411 412 if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) { 413 package = predefined + 1; 414 } 415 416 acpi_ut_get_expected_return_types(string_buffer, 417 predefined->info.expected_btypes); 418 419 acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname, 420 METHOD_GET_ARG_COUNT(predefined->info.argument_list), 421 string_buffer); 422 423 if (package) { 424 acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)", 425 package->ret_info.type, 426 package->ret_info.object_type1, 427 package->ret_info.count1); 428 } 429 430 acpi_os_printf("\n"); 431 432 /* Check that the declared argument count matches the ACPI spec */ 433 434 acpi_ns_check_acpi_compliance(pathname, node, predefined); 435 436 ACPI_FREE(pathname); 437 (*count)++; 438 return (AE_OK); 439 } 440 441 /******************************************************************************* 442 * 443 * FUNCTION: acpi_db_check_predefined_names 444 * 445 * PARAMETERS: None 446 * 447 * RETURN: None 448 * 449 * DESCRIPTION: Validate all predefined names in the namespace 450 * 451 ******************************************************************************/ 452 453 void acpi_db_check_predefined_names(void) 454 { 455 u32 count = 0; 456 457 /* Search all nodes in namespace */ 458 459 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 460 ACPI_UINT32_MAX, 461 acpi_db_walk_for_predefined_names, NULL, 462 (void *)&count, NULL); 463 464 acpi_os_printf("Found %u predefined names in the namespace\n", count); 465 } 466 467 /******************************************************************************* 468 * 469 * FUNCTION: acpi_db_walk_for_object_counts 470 * 471 * PARAMETERS: Callback from walk_namespace 472 * 473 * RETURN: Status 474 * 475 * DESCRIPTION: Display short info about objects in the namespace 476 * 477 ******************************************************************************/ 478 479 static acpi_status 480 acpi_db_walk_for_object_counts(acpi_handle obj_handle, 481 u32 nesting_level, 482 void *context, void **return_value) 483 { 484 struct acpi_object_info *info = (struct acpi_object_info *)context; 485 struct acpi_namespace_node *node = 486 (struct acpi_namespace_node *)obj_handle; 487 488 if (node->type > ACPI_TYPE_NS_NODE_MAX) { 489 acpi_os_printf("[%4.4s]: Unknown object type %X\n", 490 node->name.ascii, node->type); 491 } else { 492 info->types[node->type]++; 493 } 494 495 return (AE_OK); 496 } 497 498 /******************************************************************************* 499 * 500 * FUNCTION: acpi_db_walk_for_specific_objects 501 * 502 * PARAMETERS: Callback from walk_namespace 503 * 504 * RETURN: Status 505 * 506 * DESCRIPTION: Display short info about objects in the namespace 507 * 508 ******************************************************************************/ 509 510 static acpi_status 511 acpi_db_walk_for_specific_objects(acpi_handle obj_handle, 512 u32 nesting_level, 513 void *context, void **return_value) 514 { 515 struct acpi_walk_info *info = (struct acpi_walk_info *)context; 516 struct acpi_buffer buffer; 517 acpi_status status; 518 519 info->count++; 520 521 /* Get and display the full pathname to this object */ 522 523 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 524 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 525 if (ACPI_FAILURE(status)) { 526 acpi_os_printf("Could Not get pathname for object %p\n", 527 obj_handle); 528 return (AE_OK); 529 } 530 531 acpi_os_printf("%32s", (char *)buffer.pointer); 532 ACPI_FREE(buffer.pointer); 533 534 /* Dump short info about the object */ 535 536 (void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL); 537 return (AE_OK); 538 } 539 540 /******************************************************************************* 541 * 542 * FUNCTION: acpi_db_display_objects 543 * 544 * PARAMETERS: obj_type_arg - Type of object to display 545 * display_count_arg - Max depth to display 546 * 547 * RETURN: None 548 * 549 * DESCRIPTION: Display objects in the namespace of the requested type 550 * 551 ******************************************************************************/ 552 553 acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg) 554 { 555 struct acpi_walk_info info; 556 acpi_object_type type; 557 struct acpi_object_info *object_info; 558 u32 i; 559 u32 total_objects = 0; 560 561 /* No argument means display summary/count of all object types */ 562 563 if (!obj_type_arg) { 564 object_info = 565 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info)); 566 567 /* Walk the namespace from the root */ 568 569 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 570 ACPI_UINT32_MAX, 571 acpi_db_walk_for_object_counts, NULL, 572 (void *)object_info, NULL); 573 574 acpi_os_printf("\nSummary of namespace objects:\n\n"); 575 576 for (i = 0; i < ACPI_TOTAL_TYPES; i++) { 577 acpi_os_printf("%8u %s\n", object_info->types[i], 578 acpi_ut_get_type_name(i)); 579 580 total_objects += object_info->types[i]; 581 } 582 583 acpi_os_printf("\n%8u Total namespace objects\n\n", 584 total_objects); 585 586 ACPI_FREE(object_info); 587 return (AE_OK); 588 } 589 590 /* Get the object type */ 591 592 type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types); 593 if (type == ACPI_TYPE_NOT_FOUND) { 594 acpi_os_printf("Invalid or unsupported argument\n"); 595 return (AE_OK); 596 } 597 598 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 599 acpi_os_printf 600 ("Objects of type [%s] defined in the current ACPI Namespace:\n", 601 acpi_ut_get_type_name(type)); 602 603 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 604 605 info.count = 0; 606 info.owner_id = ACPI_OWNER_ID_MAX; 607 info.debug_level = ACPI_UINT32_MAX; 608 info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 609 610 /* Walk the namespace from the root */ 611 612 (void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 613 acpi_db_walk_for_specific_objects, NULL, 614 (void *)&info, NULL); 615 616 acpi_os_printf 617 ("\nFound %u objects of type [%s] in the current ACPI Namespace\n", 618 info.count, acpi_ut_get_type_name(type)); 619 620 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 621 return (AE_OK); 622 } 623 624 /******************************************************************************* 625 * 626 * FUNCTION: acpi_db_integrity_walk 627 * 628 * PARAMETERS: Callback from walk_namespace 629 * 630 * RETURN: Status 631 * 632 * DESCRIPTION: Examine one NS node for valid values. 633 * 634 ******************************************************************************/ 635 636 static acpi_status 637 acpi_db_integrity_walk(acpi_handle obj_handle, 638 u32 nesting_level, void *context, void **return_value) 639 { 640 struct acpi_integrity_info *info = 641 (struct acpi_integrity_info *)context; 642 struct acpi_namespace_node *node = 643 (struct acpi_namespace_node *)obj_handle; 644 union acpi_operand_object *object; 645 u8 alias = TRUE; 646 647 info->nodes++; 648 649 /* Verify the NS node, and dereference aliases */ 650 651 while (alias) { 652 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { 653 acpi_os_printf 654 ("Invalid Descriptor Type for Node %p [%s] - " 655 "is %2.2X should be %2.2X\n", node, 656 acpi_ut_get_descriptor_name(node), 657 ACPI_GET_DESCRIPTOR_TYPE(node), 658 ACPI_DESC_TYPE_NAMED); 659 return (AE_OK); 660 } 661 662 if ((node->type == ACPI_TYPE_LOCAL_ALIAS) || 663 (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { 664 node = (struct acpi_namespace_node *)node->object; 665 } else { 666 alias = FALSE; 667 } 668 } 669 670 if (node->type > ACPI_TYPE_LOCAL_MAX) { 671 acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n", 672 node, node->type); 673 return (AE_OK); 674 } 675 676 if (!acpi_ut_valid_nameseg(node->name.ascii)) { 677 acpi_os_printf("Invalid AcpiName for Node %p\n", node); 678 return (AE_OK); 679 } 680 681 object = acpi_ns_get_attached_object(node); 682 if (object) { 683 info->objects++; 684 if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { 685 acpi_os_printf 686 ("Invalid Descriptor Type for Object %p [%s]\n", 687 object, acpi_ut_get_descriptor_name(object)); 688 } 689 } 690 691 return (AE_OK); 692 } 693 694 /******************************************************************************* 695 * 696 * FUNCTION: acpi_db_check_integrity 697 * 698 * PARAMETERS: None 699 * 700 * RETURN: None 701 * 702 * DESCRIPTION: Check entire namespace for data structure integrity 703 * 704 ******************************************************************************/ 705 706 void acpi_db_check_integrity(void) 707 { 708 struct acpi_integrity_info info = { 0, 0 }; 709 710 /* Search all nodes in namespace */ 711 712 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 713 ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL, 714 (void *)&info, NULL); 715 716 acpi_os_printf("Verified %u namespace nodes with %u Objects\n", 717 info.nodes, info.objects); 718 } 719 720 /******************************************************************************* 721 * 722 * FUNCTION: acpi_db_walk_for_references 723 * 724 * PARAMETERS: Callback from walk_namespace 725 * 726 * RETURN: Status 727 * 728 * DESCRIPTION: Check if this namespace object refers to the target object 729 * that is passed in as the context value. 730 * 731 * Note: Currently doesn't check subobjects within the Node's object 732 * 733 ******************************************************************************/ 734 735 static acpi_status 736 acpi_db_walk_for_references(acpi_handle obj_handle, 737 u32 nesting_level, 738 void *context, void **return_value) 739 { 740 union acpi_operand_object *obj_desc = 741 (union acpi_operand_object *)context; 742 struct acpi_namespace_node *node = 743 (struct acpi_namespace_node *)obj_handle; 744 745 /* Check for match against the namespace node itself */ 746 747 if (node == (void *)obj_desc) { 748 acpi_os_printf("Object is a Node [%4.4s]\n", 749 acpi_ut_get_node_name(node)); 750 } 751 752 /* Check for match against the object attached to the node */ 753 754 if (acpi_ns_get_attached_object(node) == obj_desc) { 755 acpi_os_printf("Reference at Node->Object %p [%4.4s]\n", 756 node, acpi_ut_get_node_name(node)); 757 } 758 759 return (AE_OK); 760 } 761 762 /******************************************************************************* 763 * 764 * FUNCTION: acpi_db_find_references 765 * 766 * PARAMETERS: object_arg - String with hex value of the object 767 * 768 * RETURN: None 769 * 770 * DESCRIPTION: Search namespace for all references to the input object 771 * 772 ******************************************************************************/ 773 774 void acpi_db_find_references(char *object_arg) 775 { 776 union acpi_operand_object *obj_desc; 777 acpi_size address; 778 779 /* Convert string to object pointer */ 780 781 address = strtoul(object_arg, NULL, 16); 782 obj_desc = ACPI_TO_POINTER(address); 783 784 /* Search all nodes in namespace */ 785 786 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 787 ACPI_UINT32_MAX, acpi_db_walk_for_references, 788 NULL, (void *)obj_desc, NULL); 789 } 790 791 /******************************************************************************* 792 * 793 * FUNCTION: acpi_db_bus_walk 794 * 795 * PARAMETERS: Callback from walk_namespace 796 * 797 * RETURN: Status 798 * 799 * DESCRIPTION: Display info about device objects that have a corresponding 800 * _PRT method. 801 * 802 ******************************************************************************/ 803 804 static acpi_status 805 acpi_db_bus_walk(acpi_handle obj_handle, 806 u32 nesting_level, void *context, void **return_value) 807 { 808 struct acpi_namespace_node *node = 809 (struct acpi_namespace_node *)obj_handle; 810 acpi_status status; 811 struct acpi_buffer buffer; 812 struct acpi_namespace_node *temp_node; 813 struct acpi_device_info *info; 814 u32 i; 815 816 if ((node->type != ACPI_TYPE_DEVICE) && 817 (node->type != ACPI_TYPE_PROCESSOR)) { 818 return (AE_OK); 819 } 820 821 /* Exit if there is no _PRT under this device */ 822 823 status = acpi_get_handle(node, METHOD_NAME__PRT, 824 ACPI_CAST_PTR(acpi_handle, &temp_node)); 825 if (ACPI_FAILURE(status)) { 826 return (AE_OK); 827 } 828 829 /* Get the full path to this device object */ 830 831 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 832 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 833 if (ACPI_FAILURE(status)) { 834 acpi_os_printf("Could Not get pathname for object %p\n", 835 obj_handle); 836 return (AE_OK); 837 } 838 839 status = acpi_get_object_info(obj_handle, &info); 840 if (ACPI_FAILURE(status)) { 841 return (AE_OK); 842 } 843 844 /* Display the full path */ 845 846 acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type); 847 ACPI_FREE(buffer.pointer); 848 849 if (info->flags & ACPI_PCI_ROOT_BRIDGE) { 850 acpi_os_printf(" - Is PCI Root Bridge"); 851 } 852 acpi_os_printf("\n"); 853 854 /* _PRT info */ 855 856 acpi_os_printf("_PRT: %p\n", temp_node); 857 858 /* Dump _ADR, _HID, _UID, _CID */ 859 860 if (info->valid & ACPI_VALID_ADR) { 861 acpi_os_printf("_ADR: %8.8X%8.8X\n", 862 ACPI_FORMAT_UINT64(info->address)); 863 } else { 864 acpi_os_printf("_ADR: <Not Present>\n"); 865 } 866 867 if (info->valid & ACPI_VALID_HID) { 868 acpi_os_printf("_HID: %s\n", info->hardware_id.string); 869 } else { 870 acpi_os_printf("_HID: <Not Present>\n"); 871 } 872 873 if (info->valid & ACPI_VALID_UID) { 874 acpi_os_printf("_UID: %s\n", info->unique_id.string); 875 } else { 876 acpi_os_printf("_UID: <Not Present>\n"); 877 } 878 879 if (info->valid & ACPI_VALID_CID) { 880 for (i = 0; i < info->compatible_id_list.count; i++) { 881 acpi_os_printf("_CID: %s\n", 882 info->compatible_id_list.ids[i].string); 883 } 884 } else { 885 acpi_os_printf("_CID: <Not Present>\n"); 886 } 887 888 ACPI_FREE(info); 889 return (AE_OK); 890 } 891 892 /******************************************************************************* 893 * 894 * FUNCTION: acpi_db_get_bus_info 895 * 896 * PARAMETERS: None 897 * 898 * RETURN: None 899 * 900 * DESCRIPTION: Display info about system busses. 901 * 902 ******************************************************************************/ 903 904 void acpi_db_get_bus_info(void) 905 { 906 /* Search all nodes in namespace */ 907 908 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 909 ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL, 910 NULL); 911 } 912