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 193 if (((struct acpi_namespace_node *)subtree_entry)->parent) { 194 acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n", 195 ((struct acpi_namespace_node *)subtree_entry)-> 196 name.ascii, subtree_entry); 197 } else { 198 acpi_os_printf("ACPI Namespace (from %s):\n", 199 ACPI_NAMESPACE_ROOT); 200 } 201 202 /* Display the subtree */ 203 204 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 205 acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, 206 ACPI_OWNER_ID_MAX, subtree_entry); 207 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 208 } 209 210 /******************************************************************************* 211 * 212 * FUNCTION: acpi_db_dump_namespace_paths 213 * 214 * PARAMETERS: None 215 * 216 * RETURN: None 217 * 218 * DESCRIPTION: Dump entire namespace with full object pathnames and object 219 * type information. Alternative to "namespace" command. 220 * 221 ******************************************************************************/ 222 223 void acpi_db_dump_namespace_paths(void) 224 { 225 226 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 227 acpi_os_printf("ACPI Namespace (from root):\n"); 228 229 /* Display the entire namespace */ 230 231 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 232 acpi_ns_dump_object_paths(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, 233 ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX, 234 acpi_gbl_root_node); 235 236 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 237 } 238 239 /******************************************************************************* 240 * 241 * FUNCTION: acpi_db_dump_namespace_by_owner 242 * 243 * PARAMETERS: owner_arg - Owner ID whose nodes will be displayed 244 * depth_arg - Maximum tree depth to be dumped 245 * 246 * RETURN: None 247 * 248 * DESCRIPTION: Dump elements of the namespace that are owned by the owner_id. 249 * 250 ******************************************************************************/ 251 252 void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg) 253 { 254 acpi_handle subtree_entry = acpi_gbl_root_node; 255 u32 max_depth = ACPI_UINT32_MAX; 256 acpi_owner_id owner_id; 257 258 owner_id = (acpi_owner_id)strtoul(owner_arg, NULL, 0); 259 260 /* Now we can check for the depth argument */ 261 262 if (depth_arg) { 263 max_depth = strtoul(depth_arg, NULL, 0); 264 } 265 266 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 267 acpi_os_printf("ACPI Namespace by owner %X:\n", owner_id); 268 269 /* Display the subtree */ 270 271 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 272 acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, 273 owner_id, subtree_entry); 274 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 275 } 276 277 /******************************************************************************* 278 * 279 * FUNCTION: acpi_db_walk_and_match_name 280 * 281 * PARAMETERS: Callback from walk_namespace 282 * 283 * RETURN: Status 284 * 285 * DESCRIPTION: Find a particular name/names within the namespace. Wildcards 286 * are supported -- '?' matches any character. 287 * 288 ******************************************************************************/ 289 290 static acpi_status 291 acpi_db_walk_and_match_name(acpi_handle obj_handle, 292 u32 nesting_level, 293 void *context, void **return_value) 294 { 295 acpi_status status; 296 char *requested_name = (char *)context; 297 u32 i; 298 struct acpi_buffer buffer; 299 struct acpi_walk_info info; 300 301 /* Check for a name match */ 302 303 for (i = 0; i < 4; i++) { 304 305 /* Wildcard support */ 306 307 if ((requested_name[i] != '?') && 308 (requested_name[i] != ((struct acpi_namespace_node *) 309 obj_handle)->name.ascii[i])) { 310 311 /* No match, just exit */ 312 313 return (AE_OK); 314 } 315 } 316 317 /* Get the full pathname to this object */ 318 319 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 320 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 321 if (ACPI_FAILURE(status)) { 322 acpi_os_printf("Could Not get pathname for object %p\n", 323 obj_handle); 324 } else { 325 info.owner_id = ACPI_OWNER_ID_MAX; 326 info.debug_level = ACPI_UINT32_MAX; 327 info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 328 329 acpi_os_printf("%32s", (char *)buffer.pointer); 330 (void)acpi_ns_dump_one_object(obj_handle, nesting_level, &info, 331 NULL); 332 ACPI_FREE(buffer.pointer); 333 } 334 335 return (AE_OK); 336 } 337 338 /******************************************************************************* 339 * 340 * FUNCTION: acpi_db_find_name_in_namespace 341 * 342 * PARAMETERS: name_arg - The 4-character ACPI name to find. 343 * wildcards are supported. 344 * 345 * RETURN: None 346 * 347 * DESCRIPTION: Search the namespace for a given name (with wildcards) 348 * 349 ******************************************************************************/ 350 351 acpi_status acpi_db_find_name_in_namespace(char *name_arg) 352 { 353 char acpi_name[5] = "____"; 354 char *acpi_name_ptr = acpi_name; 355 356 if (strlen(name_arg) > ACPI_NAME_SIZE) { 357 acpi_os_printf("Name must be no longer than 4 characters\n"); 358 return (AE_OK); 359 } 360 361 /* Pad out name with underscores as necessary to create a 4-char name */ 362 363 acpi_ut_strupr(name_arg); 364 while (*name_arg) { 365 *acpi_name_ptr = *name_arg; 366 acpi_name_ptr++; 367 name_arg++; 368 } 369 370 /* Walk the namespace from the root */ 371 372 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 373 ACPI_UINT32_MAX, acpi_db_walk_and_match_name, 374 NULL, acpi_name, NULL); 375 376 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 377 return (AE_OK); 378 } 379 380 /******************************************************************************* 381 * 382 * FUNCTION: acpi_db_walk_for_predefined_names 383 * 384 * PARAMETERS: Callback from walk_namespace 385 * 386 * RETURN: Status 387 * 388 * DESCRIPTION: Detect and display predefined ACPI names (names that start with 389 * an underscore) 390 * 391 ******************************************************************************/ 392 393 static acpi_status 394 acpi_db_walk_for_predefined_names(acpi_handle obj_handle, 395 u32 nesting_level, 396 void *context, void **return_value) 397 { 398 struct acpi_namespace_node *node = 399 (struct acpi_namespace_node *)obj_handle; 400 u32 *count = (u32 *)context; 401 const union acpi_predefined_info *predefined; 402 const union acpi_predefined_info *package = NULL; 403 char *pathname; 404 char string_buffer[48]; 405 406 predefined = acpi_ut_match_predefined_method(node->name.ascii); 407 if (!predefined) { 408 return (AE_OK); 409 } 410 411 pathname = acpi_ns_get_normalized_pathname(node, TRUE); 412 if (!pathname) { 413 return (AE_OK); 414 } 415 416 /* If method returns a package, the info is in the next table entry */ 417 418 if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) { 419 package = predefined + 1; 420 } 421 422 acpi_ut_get_expected_return_types(string_buffer, 423 predefined->info.expected_btypes); 424 425 acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname, 426 METHOD_GET_ARG_COUNT(predefined->info.argument_list), 427 string_buffer); 428 429 if (package) { 430 acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)", 431 package->ret_info.type, 432 package->ret_info.object_type1, 433 package->ret_info.count1); 434 } 435 436 acpi_os_printf("\n"); 437 438 /* Check that the declared argument count matches the ACPI spec */ 439 440 acpi_ns_check_acpi_compliance(pathname, node, predefined); 441 442 ACPI_FREE(pathname); 443 (*count)++; 444 return (AE_OK); 445 } 446 447 /******************************************************************************* 448 * 449 * FUNCTION: acpi_db_check_predefined_names 450 * 451 * PARAMETERS: None 452 * 453 * RETURN: None 454 * 455 * DESCRIPTION: Validate all predefined names in the namespace 456 * 457 ******************************************************************************/ 458 459 void acpi_db_check_predefined_names(void) 460 { 461 u32 count = 0; 462 463 /* Search all nodes in namespace */ 464 465 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 466 ACPI_UINT32_MAX, 467 acpi_db_walk_for_predefined_names, NULL, 468 (void *)&count, NULL); 469 470 acpi_os_printf("Found %u predefined names in the namespace\n", count); 471 } 472 473 /******************************************************************************* 474 * 475 * FUNCTION: acpi_db_walk_for_object_counts 476 * 477 * PARAMETERS: Callback from walk_namespace 478 * 479 * RETURN: Status 480 * 481 * DESCRIPTION: Display short info about objects in the namespace 482 * 483 ******************************************************************************/ 484 485 static acpi_status 486 acpi_db_walk_for_object_counts(acpi_handle obj_handle, 487 u32 nesting_level, 488 void *context, void **return_value) 489 { 490 struct acpi_object_info *info = (struct acpi_object_info *)context; 491 struct acpi_namespace_node *node = 492 (struct acpi_namespace_node *)obj_handle; 493 494 if (node->type > ACPI_TYPE_NS_NODE_MAX) { 495 acpi_os_printf("[%4.4s]: Unknown object type %X\n", 496 node->name.ascii, node->type); 497 } else { 498 info->types[node->type]++; 499 } 500 501 return (AE_OK); 502 } 503 504 /******************************************************************************* 505 * 506 * FUNCTION: acpi_db_walk_for_specific_objects 507 * 508 * PARAMETERS: Callback from walk_namespace 509 * 510 * RETURN: Status 511 * 512 * DESCRIPTION: Display short info about objects in the namespace 513 * 514 ******************************************************************************/ 515 516 static acpi_status 517 acpi_db_walk_for_specific_objects(acpi_handle obj_handle, 518 u32 nesting_level, 519 void *context, void **return_value) 520 { 521 struct acpi_walk_info *info = (struct acpi_walk_info *)context; 522 struct acpi_buffer buffer; 523 acpi_status status; 524 525 info->count++; 526 527 /* Get and display the full pathname to this object */ 528 529 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 530 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 531 if (ACPI_FAILURE(status)) { 532 acpi_os_printf("Could Not get pathname for object %p\n", 533 obj_handle); 534 return (AE_OK); 535 } 536 537 acpi_os_printf("%32s", (char *)buffer.pointer); 538 ACPI_FREE(buffer.pointer); 539 540 /* Dump short info about the object */ 541 542 (void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL); 543 return (AE_OK); 544 } 545 546 /******************************************************************************* 547 * 548 * FUNCTION: acpi_db_display_objects 549 * 550 * PARAMETERS: obj_type_arg - Type of object to display 551 * display_count_arg - Max depth to display 552 * 553 * RETURN: None 554 * 555 * DESCRIPTION: Display objects in the namespace of the requested type 556 * 557 ******************************************************************************/ 558 559 acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg) 560 { 561 struct acpi_walk_info info; 562 acpi_object_type type; 563 struct acpi_object_info *object_info; 564 u32 i; 565 u32 total_objects = 0; 566 567 /* No argument means display summary/count of all object types */ 568 569 if (!obj_type_arg) { 570 object_info = 571 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info)); 572 573 /* Walk the namespace from the root */ 574 575 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 576 ACPI_UINT32_MAX, 577 acpi_db_walk_for_object_counts, NULL, 578 (void *)object_info, NULL); 579 580 acpi_os_printf("\nSummary of namespace objects:\n\n"); 581 582 for (i = 0; i < ACPI_TOTAL_TYPES; i++) { 583 acpi_os_printf("%8u %s\n", object_info->types[i], 584 acpi_ut_get_type_name(i)); 585 586 total_objects += object_info->types[i]; 587 } 588 589 acpi_os_printf("\n%8u Total namespace objects\n\n", 590 total_objects); 591 592 ACPI_FREE(object_info); 593 return (AE_OK); 594 } 595 596 /* Get the object type */ 597 598 type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types); 599 if (type == ACPI_TYPE_NOT_FOUND) { 600 acpi_os_printf("Invalid or unsupported argument\n"); 601 return (AE_OK); 602 } 603 604 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 605 acpi_os_printf 606 ("Objects of type [%s] defined in the current ACPI Namespace:\n", 607 acpi_ut_get_type_name(type)); 608 609 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 610 611 info.count = 0; 612 info.owner_id = ACPI_OWNER_ID_MAX; 613 info.debug_level = ACPI_UINT32_MAX; 614 info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 615 616 /* Walk the namespace from the root */ 617 618 (void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 619 acpi_db_walk_for_specific_objects, NULL, 620 (void *)&info, NULL); 621 622 acpi_os_printf 623 ("\nFound %u objects of type [%s] in the current ACPI Namespace\n", 624 info.count, acpi_ut_get_type_name(type)); 625 626 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 627 return (AE_OK); 628 } 629 630 /******************************************************************************* 631 * 632 * FUNCTION: acpi_db_integrity_walk 633 * 634 * PARAMETERS: Callback from walk_namespace 635 * 636 * RETURN: Status 637 * 638 * DESCRIPTION: Examine one NS node for valid values. 639 * 640 ******************************************************************************/ 641 642 static acpi_status 643 acpi_db_integrity_walk(acpi_handle obj_handle, 644 u32 nesting_level, void *context, void **return_value) 645 { 646 struct acpi_integrity_info *info = 647 (struct acpi_integrity_info *)context; 648 struct acpi_namespace_node *node = 649 (struct acpi_namespace_node *)obj_handle; 650 union acpi_operand_object *object; 651 u8 alias = TRUE; 652 653 info->nodes++; 654 655 /* Verify the NS node, and dereference aliases */ 656 657 while (alias) { 658 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { 659 acpi_os_printf 660 ("Invalid Descriptor Type for Node %p [%s] - " 661 "is %2.2X should be %2.2X\n", node, 662 acpi_ut_get_descriptor_name(node), 663 ACPI_GET_DESCRIPTOR_TYPE(node), 664 ACPI_DESC_TYPE_NAMED); 665 return (AE_OK); 666 } 667 668 if ((node->type == ACPI_TYPE_LOCAL_ALIAS) || 669 (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { 670 node = (struct acpi_namespace_node *)node->object; 671 } else { 672 alias = FALSE; 673 } 674 } 675 676 if (node->type > ACPI_TYPE_LOCAL_MAX) { 677 acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n", 678 node, node->type); 679 return (AE_OK); 680 } 681 682 if (!acpi_ut_valid_nameseg(node->name.ascii)) { 683 acpi_os_printf("Invalid AcpiName for Node %p\n", node); 684 return (AE_OK); 685 } 686 687 object = acpi_ns_get_attached_object(node); 688 if (object) { 689 info->objects++; 690 if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { 691 acpi_os_printf 692 ("Invalid Descriptor Type for Object %p [%s]\n", 693 object, acpi_ut_get_descriptor_name(object)); 694 } 695 } 696 697 return (AE_OK); 698 } 699 700 /******************************************************************************* 701 * 702 * FUNCTION: acpi_db_check_integrity 703 * 704 * PARAMETERS: None 705 * 706 * RETURN: None 707 * 708 * DESCRIPTION: Check entire namespace for data structure integrity 709 * 710 ******************************************************************************/ 711 712 void acpi_db_check_integrity(void) 713 { 714 struct acpi_integrity_info info = { 0, 0 }; 715 716 /* Search all nodes in namespace */ 717 718 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 719 ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL, 720 (void *)&info, NULL); 721 722 acpi_os_printf("Verified %u namespace nodes with %u Objects\n", 723 info.nodes, info.objects); 724 } 725 726 /******************************************************************************* 727 * 728 * FUNCTION: acpi_db_walk_for_references 729 * 730 * PARAMETERS: Callback from walk_namespace 731 * 732 * RETURN: Status 733 * 734 * DESCRIPTION: Check if this namespace object refers to the target object 735 * that is passed in as the context value. 736 * 737 * Note: Currently doesn't check subobjects within the Node's object 738 * 739 ******************************************************************************/ 740 741 static acpi_status 742 acpi_db_walk_for_references(acpi_handle obj_handle, 743 u32 nesting_level, 744 void *context, void **return_value) 745 { 746 union acpi_operand_object *obj_desc = 747 (union acpi_operand_object *)context; 748 struct acpi_namespace_node *node = 749 (struct acpi_namespace_node *)obj_handle; 750 751 /* Check for match against the namespace node itself */ 752 753 if (node == (void *)obj_desc) { 754 acpi_os_printf("Object is a Node [%4.4s]\n", 755 acpi_ut_get_node_name(node)); 756 } 757 758 /* Check for match against the object attached to the node */ 759 760 if (acpi_ns_get_attached_object(node) == obj_desc) { 761 acpi_os_printf("Reference at Node->Object %p [%4.4s]\n", 762 node, acpi_ut_get_node_name(node)); 763 } 764 765 return (AE_OK); 766 } 767 768 /******************************************************************************* 769 * 770 * FUNCTION: acpi_db_find_references 771 * 772 * PARAMETERS: object_arg - String with hex value of the object 773 * 774 * RETURN: None 775 * 776 * DESCRIPTION: Search namespace for all references to the input object 777 * 778 ******************************************************************************/ 779 780 void acpi_db_find_references(char *object_arg) 781 { 782 union acpi_operand_object *obj_desc; 783 acpi_size address; 784 785 /* Convert string to object pointer */ 786 787 address = strtoul(object_arg, NULL, 16); 788 obj_desc = ACPI_TO_POINTER(address); 789 790 /* Search all nodes in namespace */ 791 792 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 793 ACPI_UINT32_MAX, acpi_db_walk_for_references, 794 NULL, (void *)obj_desc, NULL); 795 } 796 797 /******************************************************************************* 798 * 799 * FUNCTION: acpi_db_bus_walk 800 * 801 * PARAMETERS: Callback from walk_namespace 802 * 803 * RETURN: Status 804 * 805 * DESCRIPTION: Display info about device objects that have a corresponding 806 * _PRT method. 807 * 808 ******************************************************************************/ 809 810 static acpi_status 811 acpi_db_bus_walk(acpi_handle obj_handle, 812 u32 nesting_level, void *context, void **return_value) 813 { 814 struct acpi_namespace_node *node = 815 (struct acpi_namespace_node *)obj_handle; 816 acpi_status status; 817 struct acpi_buffer buffer; 818 struct acpi_namespace_node *temp_node; 819 struct acpi_device_info *info; 820 u32 i; 821 822 if ((node->type != ACPI_TYPE_DEVICE) && 823 (node->type != ACPI_TYPE_PROCESSOR)) { 824 return (AE_OK); 825 } 826 827 /* Exit if there is no _PRT under this device */ 828 829 status = acpi_get_handle(node, METHOD_NAME__PRT, 830 ACPI_CAST_PTR(acpi_handle, &temp_node)); 831 if (ACPI_FAILURE(status)) { 832 return (AE_OK); 833 } 834 835 /* Get the full path to this device object */ 836 837 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 838 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 839 if (ACPI_FAILURE(status)) { 840 acpi_os_printf("Could Not get pathname for object %p\n", 841 obj_handle); 842 return (AE_OK); 843 } 844 845 status = acpi_get_object_info(obj_handle, &info); 846 if (ACPI_FAILURE(status)) { 847 return (AE_OK); 848 } 849 850 /* Display the full path */ 851 852 acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type); 853 ACPI_FREE(buffer.pointer); 854 855 if (info->flags & ACPI_PCI_ROOT_BRIDGE) { 856 acpi_os_printf(" - Is PCI Root Bridge"); 857 } 858 acpi_os_printf("\n"); 859 860 /* _PRT info */ 861 862 acpi_os_printf("_PRT: %p\n", temp_node); 863 864 /* Dump _ADR, _HID, _UID, _CID */ 865 866 if (info->valid & ACPI_VALID_ADR) { 867 acpi_os_printf("_ADR: %8.8X%8.8X\n", 868 ACPI_FORMAT_UINT64(info->address)); 869 } else { 870 acpi_os_printf("_ADR: <Not Present>\n"); 871 } 872 873 if (info->valid & ACPI_VALID_HID) { 874 acpi_os_printf("_HID: %s\n", info->hardware_id.string); 875 } else { 876 acpi_os_printf("_HID: <Not Present>\n"); 877 } 878 879 if (info->valid & ACPI_VALID_UID) { 880 acpi_os_printf("_UID: %s\n", info->unique_id.string); 881 } else { 882 acpi_os_printf("_UID: <Not Present>\n"); 883 } 884 885 if (info->valid & ACPI_VALID_CID) { 886 for (i = 0; i < info->compatible_id_list.count; i++) { 887 acpi_os_printf("_CID: %s\n", 888 info->compatible_id_list.ids[i].string); 889 } 890 } else { 891 acpi_os_printf("_CID: <Not Present>\n"); 892 } 893 894 ACPI_FREE(info); 895 return (AE_OK); 896 } 897 898 /******************************************************************************* 899 * 900 * FUNCTION: acpi_db_get_bus_info 901 * 902 * PARAMETERS: None 903 * 904 * RETURN: None 905 * 906 * DESCRIPTION: Display info about system busses. 907 * 908 ******************************************************************************/ 909 910 void acpi_db_get_bus_info(void) 911 { 912 /* Search all nodes in namespace */ 913 914 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 915 ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL, 916 NULL); 917 } 918