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