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 acpi_evaluate_object(obj_handle, NULL, NULL, &buffer); 554 555 /* 556 * Since this is a field unit, surround the output in braces 557 */ 558 acpi_os_printf("{"); 559 560 ret_value = (union acpi_object *)buffer.pointer; 561 switch (ret_value->type) { 562 case ACPI_TYPE_INTEGER: 563 564 acpi_os_printf("%8.8X%8.8X", 565 ACPI_FORMAT_UINT64(ret_value->integer.value)); 566 break; 567 568 case ACPI_TYPE_BUFFER: 569 570 acpi_ut_dump_buffer(ret_value->buffer.pointer, 571 ret_value->buffer.length, 572 DB_DISPLAY_DATA_ONLY | DB_BYTE_DISPLAY, 0); 573 break; 574 575 default: 576 577 break; 578 } 579 acpi_os_printf("}\n"); 580 581 ACPI_FREE(buffer.pointer); 582 583 return (AE_OK); 584 } 585 586 /******************************************************************************* 587 * 588 * FUNCTION: acpi_db_walk_for_specific_objects 589 * 590 * PARAMETERS: Callback from walk_namespace 591 * 592 * RETURN: Status 593 * 594 * DESCRIPTION: Display short info about objects in the namespace 595 * 596 ******************************************************************************/ 597 598 static acpi_status 599 acpi_db_walk_for_specific_objects(acpi_handle obj_handle, 600 u32 nesting_level, 601 void *context, void **return_value) 602 { 603 struct acpi_walk_info *info = (struct acpi_walk_info *)context; 604 struct acpi_buffer buffer; 605 acpi_status status; 606 607 info->count++; 608 609 /* Get and display the full pathname to this object */ 610 611 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 612 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 613 if (ACPI_FAILURE(status)) { 614 acpi_os_printf("Could Not get pathname for object %p\n", 615 obj_handle); 616 return (AE_OK); 617 } 618 619 acpi_os_printf("%32s", (char *)buffer.pointer); 620 ACPI_FREE(buffer.pointer); 621 622 /* Dump short info about the object */ 623 624 (void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL); 625 return (AE_OK); 626 } 627 628 /******************************************************************************* 629 * 630 * FUNCTION: acpi_db_display_objects 631 * 632 * PARAMETERS: obj_type_arg - Type of object to display 633 * display_count_arg - Max depth to display 634 * 635 * RETURN: None 636 * 637 * DESCRIPTION: Display objects in the namespace of the requested type 638 * 639 ******************************************************************************/ 640 641 acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg) 642 { 643 struct acpi_walk_info info; 644 acpi_object_type type; 645 struct acpi_object_info *object_info; 646 u32 i; 647 u32 total_objects = 0; 648 649 /* No argument means display summary/count of all object types */ 650 651 if (!obj_type_arg) { 652 object_info = 653 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info)); 654 655 if (!object_info) 656 return (AE_NO_MEMORY); 657 658 /* Walk the namespace from the root */ 659 660 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 661 ACPI_UINT32_MAX, 662 acpi_db_walk_for_object_counts, NULL, 663 (void *)object_info, NULL); 664 665 acpi_os_printf("\nSummary of namespace objects:\n\n"); 666 667 for (i = 0; i < ACPI_TOTAL_TYPES; i++) { 668 acpi_os_printf("%8u %s\n", object_info->types[i], 669 acpi_ut_get_type_name(i)); 670 671 total_objects += object_info->types[i]; 672 } 673 674 acpi_os_printf("\n%8u Total namespace objects\n\n", 675 total_objects); 676 677 ACPI_FREE(object_info); 678 return (AE_OK); 679 } 680 681 /* Get the object type */ 682 683 type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types); 684 if (type == ACPI_TYPE_NOT_FOUND) { 685 acpi_os_printf("Invalid or unsupported argument\n"); 686 return (AE_OK); 687 } 688 689 acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); 690 acpi_os_printf 691 ("Objects of type [%s] defined in the current ACPI Namespace:\n", 692 acpi_ut_get_type_name(type)); 693 694 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 695 696 info.count = 0; 697 info.owner_id = ACPI_OWNER_ID_MAX; 698 info.debug_level = ACPI_UINT32_MAX; 699 info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 700 701 /* Walk the namespace from the root */ 702 703 (void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 704 acpi_db_walk_for_specific_objects, NULL, 705 (void *)&info, NULL); 706 707 acpi_os_printf 708 ("\nFound %u objects of type [%s] in the current ACPI Namespace\n", 709 info.count, acpi_ut_get_type_name(type)); 710 711 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 712 return (AE_OK); 713 } 714 715 /******************************************************************************* 716 * 717 * FUNCTION: acpi_db_display_fields 718 * 719 * PARAMETERS: obj_type_arg - Type of object to display 720 * display_count_arg - Max depth to display 721 * 722 * RETURN: None 723 * 724 * DESCRIPTION: Display objects in the namespace of the requested type 725 * 726 ******************************************************************************/ 727 728 acpi_status acpi_db_display_fields(u32 address_space_id) 729 { 730 struct acpi_region_walk_info info; 731 732 info.count = 0; 733 info.owner_id = ACPI_OWNER_ID_MAX; 734 info.debug_level = ACPI_UINT32_MAX; 735 info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; 736 info.address_space_id = address_space_id; 737 738 /* Walk the namespace from the root */ 739 740 (void)acpi_walk_namespace(ACPI_TYPE_LOCAL_REGION_FIELD, 741 ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 742 acpi_db_walk_for_fields, NULL, (void *)&info, 743 NULL); 744 745 return (AE_OK); 746 } 747 748 /******************************************************************************* 749 * 750 * FUNCTION: acpi_db_integrity_walk 751 * 752 * PARAMETERS: Callback from walk_namespace 753 * 754 * RETURN: Status 755 * 756 * DESCRIPTION: Examine one NS node for valid values. 757 * 758 ******************************************************************************/ 759 760 static acpi_status 761 acpi_db_integrity_walk(acpi_handle obj_handle, 762 u32 nesting_level, void *context, void **return_value) 763 { 764 struct acpi_integrity_info *info = 765 (struct acpi_integrity_info *)context; 766 struct acpi_namespace_node *node = 767 (struct acpi_namespace_node *)obj_handle; 768 union acpi_operand_object *object; 769 u8 alias = TRUE; 770 771 info->nodes++; 772 773 /* Verify the NS node, and dereference aliases */ 774 775 while (alias) { 776 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { 777 acpi_os_printf 778 ("Invalid Descriptor Type for Node %p [%s] - " 779 "is %2.2X should be %2.2X\n", node, 780 acpi_ut_get_descriptor_name(node), 781 ACPI_GET_DESCRIPTOR_TYPE(node), 782 ACPI_DESC_TYPE_NAMED); 783 return (AE_OK); 784 } 785 786 if ((node->type == ACPI_TYPE_LOCAL_ALIAS) || 787 (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { 788 node = (struct acpi_namespace_node *)node->object; 789 } else { 790 alias = FALSE; 791 } 792 } 793 794 if (node->type > ACPI_TYPE_LOCAL_MAX) { 795 acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n", 796 node, node->type); 797 return (AE_OK); 798 } 799 800 if (!acpi_ut_valid_nameseg(node->name.ascii)) { 801 acpi_os_printf("Invalid AcpiName for Node %p\n", node); 802 return (AE_OK); 803 } 804 805 object = acpi_ns_get_attached_object(node); 806 if (object) { 807 info->objects++; 808 if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { 809 acpi_os_printf 810 ("Invalid Descriptor Type for Object %p [%s]\n", 811 object, acpi_ut_get_descriptor_name(object)); 812 } 813 } 814 815 return (AE_OK); 816 } 817 818 /******************************************************************************* 819 * 820 * FUNCTION: acpi_db_check_integrity 821 * 822 * PARAMETERS: None 823 * 824 * RETURN: None 825 * 826 * DESCRIPTION: Check entire namespace for data structure integrity 827 * 828 ******************************************************************************/ 829 830 void acpi_db_check_integrity(void) 831 { 832 struct acpi_integrity_info info = { 0, 0 }; 833 834 /* Search all nodes in namespace */ 835 836 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 837 ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL, 838 (void *)&info, NULL); 839 840 acpi_os_printf("Verified %u namespace nodes with %u Objects\n", 841 info.nodes, info.objects); 842 } 843 844 /******************************************************************************* 845 * 846 * FUNCTION: acpi_db_walk_for_references 847 * 848 * PARAMETERS: Callback from walk_namespace 849 * 850 * RETURN: Status 851 * 852 * DESCRIPTION: Check if this namespace object refers to the target object 853 * that is passed in as the context value. 854 * 855 * Note: Currently doesn't check subobjects within the Node's object 856 * 857 ******************************************************************************/ 858 859 static acpi_status 860 acpi_db_walk_for_references(acpi_handle obj_handle, 861 u32 nesting_level, 862 void *context, void **return_value) 863 { 864 union acpi_operand_object *obj_desc = 865 (union acpi_operand_object *)context; 866 struct acpi_namespace_node *node = 867 (struct acpi_namespace_node *)obj_handle; 868 869 /* Check for match against the namespace node itself */ 870 871 if (node == (void *)obj_desc) { 872 acpi_os_printf("Object is a Node [%4.4s]\n", 873 acpi_ut_get_node_name(node)); 874 } 875 876 /* Check for match against the object attached to the node */ 877 878 if (acpi_ns_get_attached_object(node) == obj_desc) { 879 acpi_os_printf("Reference at Node->Object %p [%4.4s]\n", 880 node, acpi_ut_get_node_name(node)); 881 } 882 883 return (AE_OK); 884 } 885 886 /******************************************************************************* 887 * 888 * FUNCTION: acpi_db_find_references 889 * 890 * PARAMETERS: object_arg - String with hex value of the object 891 * 892 * RETURN: None 893 * 894 * DESCRIPTION: Search namespace for all references to the input object 895 * 896 ******************************************************************************/ 897 898 void acpi_db_find_references(char *object_arg) 899 { 900 union acpi_operand_object *obj_desc; 901 acpi_size address; 902 903 /* Convert string to object pointer */ 904 905 address = strtoul(object_arg, NULL, 16); 906 obj_desc = ACPI_TO_POINTER(address); 907 908 /* Search all nodes in namespace */ 909 910 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 911 ACPI_UINT32_MAX, acpi_db_walk_for_references, 912 NULL, (void *)obj_desc, NULL); 913 } 914 915 /******************************************************************************* 916 * 917 * FUNCTION: acpi_db_bus_walk 918 * 919 * PARAMETERS: Callback from walk_namespace 920 * 921 * RETURN: Status 922 * 923 * DESCRIPTION: Display info about device objects that have a corresponding 924 * _PRT method. 925 * 926 ******************************************************************************/ 927 928 static acpi_status 929 acpi_db_bus_walk(acpi_handle obj_handle, 930 u32 nesting_level, void *context, void **return_value) 931 { 932 struct acpi_namespace_node *node = 933 (struct acpi_namespace_node *)obj_handle; 934 acpi_status status; 935 struct acpi_buffer buffer; 936 struct acpi_namespace_node *temp_node; 937 struct acpi_device_info *info; 938 u32 i; 939 940 if ((node->type != ACPI_TYPE_DEVICE) && 941 (node->type != ACPI_TYPE_PROCESSOR)) { 942 return (AE_OK); 943 } 944 945 /* Exit if there is no _PRT under this device */ 946 947 status = acpi_get_handle(node, METHOD_NAME__PRT, 948 ACPI_CAST_PTR(acpi_handle, &temp_node)); 949 if (ACPI_FAILURE(status)) { 950 return (AE_OK); 951 } 952 953 /* Get the full path to this device object */ 954 955 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 956 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); 957 if (ACPI_FAILURE(status)) { 958 acpi_os_printf("Could Not get pathname for object %p\n", 959 obj_handle); 960 return (AE_OK); 961 } 962 963 status = acpi_get_object_info(obj_handle, &info); 964 if (ACPI_FAILURE(status)) { 965 return (AE_OK); 966 } 967 968 /* Display the full path */ 969 970 acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type); 971 ACPI_FREE(buffer.pointer); 972 973 if (info->flags & ACPI_PCI_ROOT_BRIDGE) { 974 acpi_os_printf(" - Is PCI Root Bridge"); 975 } 976 acpi_os_printf("\n"); 977 978 /* _PRT info */ 979 980 acpi_os_printf("_PRT: %p\n", temp_node); 981 982 /* Dump _ADR, _HID, _UID, _CID */ 983 984 if (info->valid & ACPI_VALID_ADR) { 985 acpi_os_printf("_ADR: %8.8X%8.8X\n", 986 ACPI_FORMAT_UINT64(info->address)); 987 } else { 988 acpi_os_printf("_ADR: <Not Present>\n"); 989 } 990 991 if (info->valid & ACPI_VALID_HID) { 992 acpi_os_printf("_HID: %s\n", info->hardware_id.string); 993 } else { 994 acpi_os_printf("_HID: <Not Present>\n"); 995 } 996 997 if (info->valid & ACPI_VALID_UID) { 998 acpi_os_printf("_UID: %s\n", info->unique_id.string); 999 } else { 1000 acpi_os_printf("_UID: <Not Present>\n"); 1001 } 1002 1003 if (info->valid & ACPI_VALID_CID) { 1004 for (i = 0; i < info->compatible_id_list.count; i++) { 1005 acpi_os_printf("_CID: %s\n", 1006 info->compatible_id_list.ids[i].string); 1007 } 1008 } else { 1009 acpi_os_printf("_CID: <Not Present>\n"); 1010 } 1011 1012 ACPI_FREE(info); 1013 return (AE_OK); 1014 } 1015 1016 /******************************************************************************* 1017 * 1018 * FUNCTION: acpi_db_get_bus_info 1019 * 1020 * PARAMETERS: None 1021 * 1022 * RETURN: None 1023 * 1024 * DESCRIPTION: Display info about system buses. 1025 * 1026 ******************************************************************************/ 1027 1028 void acpi_db_get_bus_info(void) 1029 { 1030 /* Search all nodes in namespace */ 1031 1032 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 1033 ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL, 1034 NULL); 1035 } 1036