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