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