1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /******************************************************************************* 3 * 4 * Module Name: dbcmds - Miscellaneous debug commands and output routines 5 * 6 ******************************************************************************/ 7 8 #include <acpi/acpi.h> 9 #include "accommon.h" 10 #include "acevents.h" 11 #include "acdebug.h" 12 #include "acnamesp.h" 13 #include "acresrc.h" 14 #include "actables.h" 15 16 #define _COMPONENT ACPI_CA_DEBUGGER 17 ACPI_MODULE_NAME("dbcmds") 18 19 /* Local prototypes */ 20 static void 21 acpi_dm_compare_aml_resources(u8 *aml1_buffer, 22 acpi_rsdesc_size aml1_buffer_length, 23 u8 *aml2_buffer, 24 acpi_rsdesc_size aml2_buffer_length); 25 26 static acpi_status 27 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name); 28 29 static acpi_status 30 acpi_db_resource_callback(struct acpi_resource *resource, void *context); 31 32 static acpi_status 33 acpi_db_device_resources(acpi_handle obj_handle, 34 u32 nesting_level, void *context, void **return_value); 35 36 static void acpi_db_do_one_sleep_state(u8 sleep_state); 37 38 static char *acpi_db_trace_method_name = NULL; 39 40 /******************************************************************************* 41 * 42 * FUNCTION: acpi_db_convert_to_node 43 * 44 * PARAMETERS: in_string - String to convert 45 * 46 * RETURN: Pointer to a NS node 47 * 48 * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or 49 * alphanumeric strings. 50 * 51 ******************************************************************************/ 52 53 struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string) 54 { 55 struct acpi_namespace_node *node; 56 acpi_size address; 57 58 if ((*in_string >= 0x30) && (*in_string <= 0x39)) { 59 60 /* Numeric argument, convert */ 61 62 address = strtoul(in_string, NULL, 16); 63 node = ACPI_TO_POINTER(address); 64 if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) { 65 acpi_os_printf("Address %p is invalid", node); 66 return (NULL); 67 } 68 69 /* Make sure pointer is valid NS node */ 70 71 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { 72 acpi_os_printf 73 ("Address %p is not a valid namespace node [%s]\n", 74 node, acpi_ut_get_descriptor_name(node)); 75 return (NULL); 76 } 77 } else { 78 /* 79 * Alpha argument: The parameter is a name string that must be 80 * resolved to a Namespace object. 81 */ 82 node = acpi_db_local_ns_lookup(in_string); 83 if (!node) { 84 acpi_os_printf 85 ("Could not find [%s] in namespace, defaulting to root node\n", 86 in_string); 87 node = acpi_gbl_root_node; 88 } 89 } 90 91 return (node); 92 } 93 94 /******************************************************************************* 95 * 96 * FUNCTION: acpi_db_sleep 97 * 98 * PARAMETERS: object_arg - Desired sleep state (0-5). NULL means 99 * invoke all possible sleep states. 100 * 101 * RETURN: Status 102 * 103 * DESCRIPTION: Simulate sleep/wake sequences 104 * 105 ******************************************************************************/ 106 107 acpi_status acpi_db_sleep(char *object_arg) 108 { 109 u8 sleep_state; 110 u32 i; 111 112 ACPI_FUNCTION_TRACE(acpi_db_sleep); 113 114 /* Null input (no arguments) means to invoke all sleep states */ 115 116 if (!object_arg) { 117 acpi_os_printf("Invoking all possible sleep states, 0-%d\n", 118 ACPI_S_STATES_MAX); 119 120 for (i = 0; i <= ACPI_S_STATES_MAX; i++) { 121 acpi_db_do_one_sleep_state((u8)i); 122 } 123 124 return_ACPI_STATUS(AE_OK); 125 } 126 127 /* Convert argument to binary and invoke the sleep state */ 128 129 sleep_state = (u8)strtoul(object_arg, NULL, 0); 130 acpi_db_do_one_sleep_state(sleep_state); 131 return_ACPI_STATUS(AE_OK); 132 } 133 134 /******************************************************************************* 135 * 136 * FUNCTION: acpi_db_do_one_sleep_state 137 * 138 * PARAMETERS: sleep_state - Desired sleep state (0-5) 139 * 140 * RETURN: None 141 * 142 * DESCRIPTION: Simulate a sleep/wake sequence 143 * 144 ******************************************************************************/ 145 146 static void acpi_db_do_one_sleep_state(u8 sleep_state) 147 { 148 acpi_status status; 149 u8 sleep_type_a; 150 u8 sleep_type_b; 151 152 /* Validate parameter */ 153 154 if (sleep_state > ACPI_S_STATES_MAX) { 155 acpi_os_printf("Sleep state %d out of range (%d max)\n", 156 sleep_state, ACPI_S_STATES_MAX); 157 return; 158 } 159 160 acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n", 161 sleep_state, acpi_gbl_sleep_state_names[sleep_state]); 162 163 /* Get the values for the sleep type registers (for display only) */ 164 165 status = 166 acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b); 167 if (ACPI_FAILURE(status)) { 168 acpi_os_printf("Could not evaluate [%s] method, %s\n", 169 acpi_gbl_sleep_state_names[sleep_state], 170 acpi_format_exception(status)); 171 return; 172 } 173 174 acpi_os_printf 175 ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n", 176 sleep_state, sleep_type_a, sleep_type_b); 177 178 /* Invoke the various sleep/wake interfaces */ 179 180 acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n", 181 sleep_state); 182 status = acpi_enter_sleep_state_prep(sleep_state); 183 if (ACPI_FAILURE(status)) { 184 goto error_exit; 185 } 186 187 acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state); 188 status = acpi_enter_sleep_state(sleep_state); 189 if (ACPI_FAILURE(status)) { 190 goto error_exit; 191 } 192 193 acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n", 194 sleep_state); 195 status = acpi_leave_sleep_state_prep(sleep_state); 196 if (ACPI_FAILURE(status)) { 197 goto error_exit; 198 } 199 200 acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n", 201 sleep_state); 202 status = acpi_leave_sleep_state(sleep_state); 203 if (ACPI_FAILURE(status)) { 204 goto error_exit; 205 } 206 207 return; 208 209 error_exit: 210 ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d", 211 sleep_state)); 212 } 213 214 /******************************************************************************* 215 * 216 * FUNCTION: acpi_db_display_locks 217 * 218 * PARAMETERS: None 219 * 220 * RETURN: None 221 * 222 * DESCRIPTION: Display information about internal mutexes. 223 * 224 ******************************************************************************/ 225 226 void acpi_db_display_locks(void) 227 { 228 u32 i; 229 230 for (i = 0; i < ACPI_MAX_MUTEX; i++) { 231 acpi_os_printf("%26s : %s\n", acpi_ut_get_mutex_name(i), 232 acpi_gbl_mutex_info[i].thread_id == 233 ACPI_MUTEX_NOT_ACQUIRED ? "Locked" : "Unlocked"); 234 } 235 } 236 237 /******************************************************************************* 238 * 239 * FUNCTION: acpi_db_display_table_info 240 * 241 * PARAMETERS: table_arg - Name of table to be displayed 242 * 243 * RETURN: None 244 * 245 * DESCRIPTION: Display information about loaded tables. Current 246 * implementation displays all loaded tables. 247 * 248 ******************************************************************************/ 249 250 void acpi_db_display_table_info(char *table_arg) 251 { 252 u32 i; 253 struct acpi_table_desc *table_desc; 254 acpi_status status; 255 256 /* Header */ 257 258 acpi_os_printf("Idx ID Status Type " 259 "TableHeader (Sig, Address, Length, Misc)\n"); 260 261 /* Walk the entire root table list */ 262 263 for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { 264 table_desc = &acpi_gbl_root_table_list.tables[i]; 265 266 /* Index and Table ID */ 267 268 acpi_os_printf("%3u %.2u ", i, table_desc->owner_id); 269 270 /* Decode the table flags */ 271 272 if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) { 273 acpi_os_printf("NotLoaded "); 274 } else { 275 acpi_os_printf(" Loaded "); 276 } 277 278 switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { 279 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: 280 281 acpi_os_printf("External/virtual "); 282 break; 283 284 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: 285 286 acpi_os_printf("Internal/physical "); 287 break; 288 289 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: 290 291 acpi_os_printf("Internal/virtual "); 292 break; 293 294 default: 295 296 acpi_os_printf("INVALID TYPE "); 297 break; 298 } 299 300 /* Make sure that the table is mapped */ 301 302 status = acpi_tb_validate_table(table_desc); 303 if (ACPI_FAILURE(status)) { 304 return; 305 } 306 307 /* Dump the table header */ 308 309 if (table_desc->pointer) { 310 acpi_tb_print_table_header(table_desc->address, 311 table_desc->pointer); 312 } else { 313 /* If the pointer is null, the table has been unloaded */ 314 315 ACPI_INFO(("%4.4s - Table has been unloaded", 316 table_desc->signature.ascii)); 317 } 318 } 319 } 320 321 /******************************************************************************* 322 * 323 * FUNCTION: acpi_db_unload_acpi_table 324 * 325 * PARAMETERS: object_name - Namespace pathname for an object that 326 * is owned by the table to be unloaded 327 * 328 * RETURN: None 329 * 330 * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned 331 * by the table. 332 * 333 ******************************************************************************/ 334 335 void acpi_db_unload_acpi_table(char *object_name) 336 { 337 struct acpi_namespace_node *node; 338 acpi_status status; 339 340 /* Translate name to an Named object */ 341 342 node = acpi_db_convert_to_node(object_name); 343 if (!node) { 344 return; 345 } 346 347 status = acpi_unload_parent_table(ACPI_CAST_PTR(acpi_handle, node)); 348 if (ACPI_SUCCESS(status)) { 349 acpi_os_printf("Parent of [%s] (%p) unloaded and uninstalled\n", 350 object_name, node); 351 } else { 352 acpi_os_printf("%s, while unloading parent table of [%s]\n", 353 acpi_format_exception(status), object_name); 354 } 355 } 356 357 /******************************************************************************* 358 * 359 * FUNCTION: acpi_db_send_notify 360 * 361 * PARAMETERS: name - Name of ACPI object where to send notify 362 * value - Value of the notify to send. 363 * 364 * RETURN: None 365 * 366 * DESCRIPTION: Send an ACPI notification. The value specified is sent to the 367 * named object as an ACPI notify. 368 * 369 ******************************************************************************/ 370 371 void acpi_db_send_notify(char *name, u32 value) 372 { 373 struct acpi_namespace_node *node; 374 acpi_status status; 375 376 /* Translate name to an Named object */ 377 378 node = acpi_db_convert_to_node(name); 379 if (!node) { 380 return; 381 } 382 383 /* Dispatch the notify if legal */ 384 385 if (acpi_ev_is_notify_object(node)) { 386 status = acpi_ev_queue_notify_request(node, value); 387 if (ACPI_FAILURE(status)) { 388 acpi_os_printf("Could not queue notify\n"); 389 } 390 } else { 391 acpi_os_printf("Named object [%4.4s] Type %s, " 392 "must be Device/Thermal/Processor type\n", 393 acpi_ut_get_node_name(node), 394 acpi_ut_get_type_name(node->type)); 395 } 396 } 397 398 /******************************************************************************* 399 * 400 * FUNCTION: acpi_db_display_interfaces 401 * 402 * PARAMETERS: action_arg - Null, "install", or "remove" 403 * interface_name_arg - Name for install/remove options 404 * 405 * RETURN: None 406 * 407 * DESCRIPTION: Display or modify the global _OSI interface list 408 * 409 ******************************************************************************/ 410 411 void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg) 412 { 413 struct acpi_interface_info *next_interface; 414 char *sub_string; 415 acpi_status status; 416 417 /* If no arguments, just display current interface list */ 418 419 if (!action_arg) { 420 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, 421 ACPI_WAIT_FOREVER); 422 423 next_interface = acpi_gbl_supported_interfaces; 424 while (next_interface) { 425 if (!(next_interface->flags & ACPI_OSI_INVALID)) { 426 acpi_os_printf("%s\n", next_interface->name); 427 } 428 429 next_interface = next_interface->next; 430 } 431 432 acpi_os_release_mutex(acpi_gbl_osi_mutex); 433 return; 434 } 435 436 /* If action_arg exists, so must interface_name_arg */ 437 438 if (!interface_name_arg) { 439 acpi_os_printf("Missing Interface Name argument\n"); 440 return; 441 } 442 443 /* Uppercase the action for match below */ 444 445 acpi_ut_strupr(action_arg); 446 447 /* install - install an interface */ 448 449 sub_string = strstr("INSTALL", action_arg); 450 if (sub_string) { 451 status = acpi_install_interface(interface_name_arg); 452 if (ACPI_FAILURE(status)) { 453 acpi_os_printf("%s, while installing \"%s\"\n", 454 acpi_format_exception(status), 455 interface_name_arg); 456 } 457 return; 458 } 459 460 /* remove - remove an interface */ 461 462 sub_string = strstr("REMOVE", action_arg); 463 if (sub_string) { 464 status = acpi_remove_interface(interface_name_arg); 465 if (ACPI_FAILURE(status)) { 466 acpi_os_printf("%s, while removing \"%s\"\n", 467 acpi_format_exception(status), 468 interface_name_arg); 469 } 470 return; 471 } 472 473 /* Invalid action_arg */ 474 475 acpi_os_printf("Invalid action argument: %s\n", action_arg); 476 return; 477 } 478 479 /******************************************************************************* 480 * 481 * FUNCTION: acpi_db_display_template 482 * 483 * PARAMETERS: buffer_arg - Buffer name or address 484 * 485 * RETURN: None 486 * 487 * DESCRIPTION: Dump a buffer that contains a resource template 488 * 489 ******************************************************************************/ 490 491 void acpi_db_display_template(char *buffer_arg) 492 { 493 struct acpi_namespace_node *node; 494 acpi_status status; 495 struct acpi_buffer return_buffer; 496 497 /* Translate buffer_arg to an Named object */ 498 499 node = acpi_db_convert_to_node(buffer_arg); 500 if (!node || (node == acpi_gbl_root_node)) { 501 acpi_os_printf("Invalid argument: %s\n", buffer_arg); 502 return; 503 } 504 505 /* We must have a buffer object */ 506 507 if (node->type != ACPI_TYPE_BUFFER) { 508 acpi_os_printf 509 ("Not a Buffer object, cannot be a template: %s\n", 510 buffer_arg); 511 return; 512 } 513 514 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 515 return_buffer.pointer = acpi_gbl_db_buffer; 516 517 /* Attempt to convert the raw buffer to a resource list */ 518 519 status = acpi_rs_create_resource_list(node->object, &return_buffer); 520 521 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 522 acpi_dbg_level |= ACPI_LV_RESOURCES; 523 524 if (ACPI_FAILURE(status)) { 525 acpi_os_printf 526 ("Could not convert Buffer to a resource list: %s, %s\n", 527 buffer_arg, acpi_format_exception(status)); 528 goto dump_buffer; 529 } 530 531 /* Now we can dump the resource list */ 532 533 acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource, 534 return_buffer.pointer)); 535 536 dump_buffer: 537 acpi_os_printf("\nRaw data buffer:\n"); 538 acpi_ut_debug_dump_buffer((u8 *)node->object->buffer.pointer, 539 node->object->buffer.length, 540 DB_BYTE_DISPLAY, ACPI_UINT32_MAX); 541 542 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 543 return; 544 } 545 546 /******************************************************************************* 547 * 548 * FUNCTION: acpi_dm_compare_aml_resources 549 * 550 * PARAMETERS: aml1_buffer - Contains first resource list 551 * aml1_buffer_length - Length of first resource list 552 * aml2_buffer - Contains second resource list 553 * aml2_buffer_length - Length of second resource list 554 * 555 * RETURN: None 556 * 557 * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in 558 * order to isolate a miscompare to an individual resource) 559 * 560 ******************************************************************************/ 561 562 static void 563 acpi_dm_compare_aml_resources(u8 *aml1_buffer, 564 acpi_rsdesc_size aml1_buffer_length, 565 u8 *aml2_buffer, 566 acpi_rsdesc_size aml2_buffer_length) 567 { 568 u8 *aml1; 569 u8 *aml2; 570 u8 *aml1_end; 571 u8 *aml2_end; 572 acpi_rsdesc_size aml1_length; 573 acpi_rsdesc_size aml2_length; 574 acpi_rsdesc_size offset = 0; 575 u8 resource_type; 576 u32 count = 0; 577 u32 i; 578 579 /* Compare overall buffer sizes (may be different due to size rounding) */ 580 581 if (aml1_buffer_length != aml2_buffer_length) { 582 acpi_os_printf("**** Buffer length mismatch in converted " 583 "AML: Original %X, New %X ****\n", 584 aml1_buffer_length, aml2_buffer_length); 585 } 586 587 aml1 = aml1_buffer; 588 aml2 = aml2_buffer; 589 aml1_end = aml1_buffer + aml1_buffer_length; 590 aml2_end = aml2_buffer + aml2_buffer_length; 591 592 /* Walk the descriptor lists, comparing each descriptor */ 593 594 while ((aml1 < aml1_end) && (aml2 < aml2_end)) { 595 596 /* Get the lengths of each descriptor */ 597 598 aml1_length = acpi_ut_get_descriptor_length(aml1); 599 aml2_length = acpi_ut_get_descriptor_length(aml2); 600 resource_type = acpi_ut_get_resource_type(aml1); 601 602 /* Check for descriptor length match */ 603 604 if (aml1_length != aml2_length) { 605 acpi_os_printf 606 ("**** Length mismatch in descriptor [%.2X] type %2.2X, " 607 "Offset %8.8X Len1 %X, Len2 %X ****\n", count, 608 resource_type, offset, aml1_length, aml2_length); 609 } 610 611 /* Check for descriptor byte match */ 612 613 else if (memcmp(aml1, aml2, aml1_length)) { 614 acpi_os_printf 615 ("**** Data mismatch in descriptor [%.2X] type %2.2X, " 616 "Offset %8.8X ****\n", count, resource_type, 617 offset); 618 619 for (i = 0; i < aml1_length; i++) { 620 if (aml1[i] != aml2[i]) { 621 acpi_os_printf 622 ("Mismatch at byte offset %.2X: is %2.2X, " 623 "should be %2.2X\n", i, aml2[i], 624 aml1[i]); 625 } 626 } 627 } 628 629 /* Exit on end_tag descriptor */ 630 631 if (resource_type == ACPI_RESOURCE_NAME_END_TAG) { 632 return; 633 } 634 635 /* Point to next descriptor in each buffer */ 636 637 count++; 638 offset += aml1_length; 639 aml1 += aml1_length; 640 aml2 += aml2_length; 641 } 642 } 643 644 /******************************************************************************* 645 * 646 * FUNCTION: acpi_dm_test_resource_conversion 647 * 648 * PARAMETERS: node - Parent device node 649 * name - resource method name (_CRS) 650 * 651 * RETURN: Status 652 * 653 * DESCRIPTION: Compare the original AML with a conversion of the AML to 654 * internal resource list, then back to AML. 655 * 656 ******************************************************************************/ 657 658 static acpi_status 659 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name) 660 { 661 acpi_status status; 662 struct acpi_buffer return_buffer; 663 struct acpi_buffer resource_buffer; 664 struct acpi_buffer new_aml; 665 union acpi_object *original_aml; 666 667 acpi_os_printf("Resource Conversion Comparison:\n"); 668 669 new_aml.length = ACPI_ALLOCATE_LOCAL_BUFFER; 670 return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 671 resource_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 672 673 /* Get the original _CRS AML resource template */ 674 675 status = acpi_evaluate_object(node, name, NULL, &return_buffer); 676 if (ACPI_FAILURE(status)) { 677 acpi_os_printf("Could not obtain %s: %s\n", 678 name, acpi_format_exception(status)); 679 return (status); 680 } 681 682 /* Get the AML resource template, converted to internal resource structs */ 683 684 status = acpi_get_current_resources(node, &resource_buffer); 685 if (ACPI_FAILURE(status)) { 686 acpi_os_printf("AcpiGetCurrentResources failed: %s\n", 687 acpi_format_exception(status)); 688 goto exit1; 689 } 690 691 /* Convert internal resource list to external AML resource template */ 692 693 status = acpi_rs_create_aml_resources(&resource_buffer, &new_aml); 694 if (ACPI_FAILURE(status)) { 695 acpi_os_printf("AcpiRsCreateAmlResources failed: %s\n", 696 acpi_format_exception(status)); 697 goto exit2; 698 } 699 700 /* Compare original AML to the newly created AML resource list */ 701 702 original_aml = return_buffer.pointer; 703 704 acpi_dm_compare_aml_resources(original_aml->buffer.pointer, 705 (acpi_rsdesc_size)original_aml->buffer. 706 length, new_aml.pointer, 707 (acpi_rsdesc_size)new_aml.length); 708 709 /* Cleanup and exit */ 710 711 ACPI_FREE(new_aml.pointer); 712 exit2: 713 ACPI_FREE(resource_buffer.pointer); 714 exit1: 715 ACPI_FREE(return_buffer.pointer); 716 return (status); 717 } 718 719 /******************************************************************************* 720 * 721 * FUNCTION: acpi_db_resource_callback 722 * 723 * PARAMETERS: acpi_walk_resource_callback 724 * 725 * RETURN: Status 726 * 727 * DESCRIPTION: Simple callback to exercise acpi_walk_resources and 728 * acpi_walk_resource_buffer. 729 * 730 ******************************************************************************/ 731 732 static acpi_status 733 acpi_db_resource_callback(struct acpi_resource *resource, void *context) 734 { 735 736 return (AE_OK); 737 } 738 739 /******************************************************************************* 740 * 741 * FUNCTION: acpi_db_device_resources 742 * 743 * PARAMETERS: acpi_walk_callback 744 * 745 * RETURN: Status 746 * 747 * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object. 748 * 749 ******************************************************************************/ 750 751 static acpi_status 752 acpi_db_device_resources(acpi_handle obj_handle, 753 u32 nesting_level, void *context, void **return_value) 754 { 755 struct acpi_namespace_node *node; 756 struct acpi_namespace_node *prt_node = NULL; 757 struct acpi_namespace_node *crs_node = NULL; 758 struct acpi_namespace_node *prs_node = NULL; 759 struct acpi_namespace_node *aei_node = NULL; 760 char *parent_path; 761 struct acpi_buffer return_buffer; 762 acpi_status status; 763 764 node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); 765 parent_path = acpi_ns_get_normalized_pathname(node, TRUE); 766 if (!parent_path) { 767 return (AE_NO_MEMORY); 768 } 769 770 /* Get handles to the resource methods for this device */ 771 772 (void)acpi_get_handle(node, METHOD_NAME__PRT, 773 ACPI_CAST_PTR(acpi_handle, &prt_node)); 774 (void)acpi_get_handle(node, METHOD_NAME__CRS, 775 ACPI_CAST_PTR(acpi_handle, &crs_node)); 776 (void)acpi_get_handle(node, METHOD_NAME__PRS, 777 ACPI_CAST_PTR(acpi_handle, &prs_node)); 778 (void)acpi_get_handle(node, METHOD_NAME__AEI, 779 ACPI_CAST_PTR(acpi_handle, &aei_node)); 780 781 if (!prt_node && !crs_node && !prs_node && !aei_node) { 782 goto cleanup; /* Nothing to do */ 783 } 784 785 acpi_os_printf("\nDevice: %s\n", parent_path); 786 787 /* Prepare for a return object of arbitrary size */ 788 789 return_buffer.pointer = acpi_gbl_db_buffer; 790 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 791 792 /* _PRT */ 793 794 if (prt_node) { 795 acpi_os_printf("Evaluating _PRT\n"); 796 797 status = 798 acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer); 799 if (ACPI_FAILURE(status)) { 800 acpi_os_printf("Could not evaluate _PRT: %s\n", 801 acpi_format_exception(status)); 802 goto get_crs; 803 } 804 805 return_buffer.pointer = acpi_gbl_db_buffer; 806 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 807 808 status = acpi_get_irq_routing_table(node, &return_buffer); 809 if (ACPI_FAILURE(status)) { 810 acpi_os_printf("GetIrqRoutingTable failed: %s\n", 811 acpi_format_exception(status)); 812 goto get_crs; 813 } 814 815 acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer)); 816 } 817 818 /* _CRS */ 819 820 get_crs: 821 if (crs_node) { 822 acpi_os_printf("Evaluating _CRS\n"); 823 824 return_buffer.pointer = acpi_gbl_db_buffer; 825 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 826 827 status = 828 acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer); 829 if (ACPI_FAILURE(status)) { 830 acpi_os_printf("Could not evaluate _CRS: %s\n", 831 acpi_format_exception(status)); 832 goto get_prs; 833 } 834 835 /* This code exercises the acpi_walk_resources interface */ 836 837 status = acpi_walk_resources(node, METHOD_NAME__CRS, 838 acpi_db_resource_callback, NULL); 839 if (ACPI_FAILURE(status)) { 840 acpi_os_printf("AcpiWalkResources failed: %s\n", 841 acpi_format_exception(status)); 842 goto get_prs; 843 } 844 845 /* Get the _CRS resource list (test ALLOCATE buffer) */ 846 847 return_buffer.pointer = NULL; 848 return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 849 850 status = acpi_get_current_resources(node, &return_buffer); 851 if (ACPI_FAILURE(status)) { 852 acpi_os_printf("AcpiGetCurrentResources failed: %s\n", 853 acpi_format_exception(status)); 854 goto get_prs; 855 } 856 857 /* This code exercises the acpi_walk_resource_buffer interface */ 858 859 status = acpi_walk_resource_buffer(&return_buffer, 860 acpi_db_resource_callback, 861 NULL); 862 if (ACPI_FAILURE(status)) { 863 acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n", 864 acpi_format_exception(status)); 865 goto end_crs; 866 } 867 868 /* Dump the _CRS resource list */ 869 870 acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource, 871 return_buffer. 872 pointer)); 873 874 /* 875 * Perform comparison of original AML to newly created AML. This 876 * tests both the AML->Resource conversion and the Resource->AML 877 * conversion. 878 */ 879 (void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS); 880 881 /* Execute _SRS with the resource list */ 882 883 acpi_os_printf("Evaluating _SRS\n"); 884 885 status = acpi_set_current_resources(node, &return_buffer); 886 if (ACPI_FAILURE(status)) { 887 acpi_os_printf("AcpiSetCurrentResources failed: %s\n", 888 acpi_format_exception(status)); 889 goto end_crs; 890 } 891 892 end_crs: 893 ACPI_FREE(return_buffer.pointer); 894 } 895 896 /* _PRS */ 897 898 get_prs: 899 if (prs_node) { 900 acpi_os_printf("Evaluating _PRS\n"); 901 902 return_buffer.pointer = acpi_gbl_db_buffer; 903 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 904 905 status = 906 acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer); 907 if (ACPI_FAILURE(status)) { 908 acpi_os_printf("Could not evaluate _PRS: %s\n", 909 acpi_format_exception(status)); 910 goto get_aei; 911 } 912 913 return_buffer.pointer = acpi_gbl_db_buffer; 914 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 915 916 status = acpi_get_possible_resources(node, &return_buffer); 917 if (ACPI_FAILURE(status)) { 918 acpi_os_printf("AcpiGetPossibleResources failed: %s\n", 919 acpi_format_exception(status)); 920 goto get_aei; 921 } 922 923 acpi_rs_dump_resource_list(ACPI_CAST_PTR 924 (struct acpi_resource, 925 acpi_gbl_db_buffer)); 926 } 927 928 /* _AEI */ 929 930 get_aei: 931 if (aei_node) { 932 acpi_os_printf("Evaluating _AEI\n"); 933 934 return_buffer.pointer = acpi_gbl_db_buffer; 935 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 936 937 status = 938 acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer); 939 if (ACPI_FAILURE(status)) { 940 acpi_os_printf("Could not evaluate _AEI: %s\n", 941 acpi_format_exception(status)); 942 goto cleanup; 943 } 944 945 return_buffer.pointer = acpi_gbl_db_buffer; 946 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; 947 948 status = acpi_get_event_resources(node, &return_buffer); 949 if (ACPI_FAILURE(status)) { 950 acpi_os_printf("AcpiGetEventResources failed: %s\n", 951 acpi_format_exception(status)); 952 goto cleanup; 953 } 954 955 acpi_rs_dump_resource_list(ACPI_CAST_PTR 956 (struct acpi_resource, 957 acpi_gbl_db_buffer)); 958 } 959 960 cleanup: 961 ACPI_FREE(parent_path); 962 return (AE_OK); 963 } 964 965 /******************************************************************************* 966 * 967 * FUNCTION: acpi_db_display_resources 968 * 969 * PARAMETERS: object_arg - String object name or object pointer. 970 * NULL or "*" means "display resources for 971 * all devices" 972 * 973 * RETURN: None 974 * 975 * DESCRIPTION: Display the resource objects associated with a device. 976 * 977 ******************************************************************************/ 978 979 void acpi_db_display_resources(char *object_arg) 980 { 981 struct acpi_namespace_node *node; 982 983 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); 984 acpi_dbg_level |= ACPI_LV_RESOURCES; 985 986 /* Asterisk means "display resources for all devices" */ 987 988 if (!object_arg || (!strcmp(object_arg, "*"))) { 989 (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 990 ACPI_UINT32_MAX, 991 acpi_db_device_resources, NULL, NULL, 992 NULL); 993 } else { 994 /* Convert string to object pointer */ 995 996 node = acpi_db_convert_to_node(object_arg); 997 if (node) { 998 if (node->type != ACPI_TYPE_DEVICE) { 999 acpi_os_printf 1000 ("%4.4s: Name is not a device object (%s)\n", 1001 node->name.ascii, 1002 acpi_ut_get_type_name(node->type)); 1003 } else { 1004 (void)acpi_db_device_resources(node, 0, NULL, 1005 NULL); 1006 } 1007 } 1008 } 1009 1010 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); 1011 } 1012 1013 #if (!ACPI_REDUCED_HARDWARE) 1014 /******************************************************************************* 1015 * 1016 * FUNCTION: acpi_db_generate_gpe 1017 * 1018 * PARAMETERS: gpe_arg - Raw GPE number, ascii string 1019 * block_arg - GPE block number, ascii string 1020 * 0 or 1 for FADT GPE blocks 1021 * 1022 * RETURN: None 1023 * 1024 * DESCRIPTION: Simulate firing of a GPE 1025 * 1026 ******************************************************************************/ 1027 1028 void acpi_db_generate_gpe(char *gpe_arg, char *block_arg) 1029 { 1030 u32 block_number = 0; 1031 u32 gpe_number; 1032 struct acpi_gpe_event_info *gpe_event_info; 1033 1034 gpe_number = strtoul(gpe_arg, NULL, 0); 1035 1036 /* 1037 * If no block arg, or block arg == 0 or 1, use the FADT-defined 1038 * GPE blocks. 1039 */ 1040 if (block_arg) { 1041 block_number = strtoul(block_arg, NULL, 0); 1042 if (block_number == 1) { 1043 block_number = 0; 1044 } 1045 } 1046 1047 gpe_event_info = 1048 acpi_ev_get_gpe_event_info(ACPI_TO_POINTER(block_number), 1049 gpe_number); 1050 if (!gpe_event_info) { 1051 acpi_os_printf("Invalid GPE\n"); 1052 return; 1053 } 1054 1055 (void)acpi_ev_gpe_dispatch(NULL, gpe_event_info, gpe_number); 1056 } 1057 1058 /******************************************************************************* 1059 * 1060 * FUNCTION: acpi_db_generate_sci 1061 * 1062 * PARAMETERS: None 1063 * 1064 * RETURN: None 1065 * 1066 * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch. 1067 * 1068 ******************************************************************************/ 1069 1070 void acpi_db_generate_sci(void) 1071 { 1072 acpi_ev_sci_dispatch(); 1073 } 1074 1075 #endif /* !ACPI_REDUCED_HARDWARE */ 1076 1077 /******************************************************************************* 1078 * 1079 * FUNCTION: acpi_db_trace 1080 * 1081 * PARAMETERS: enable_arg - ENABLE/AML to enable tracer 1082 * DISABLE to disable tracer 1083 * method_arg - Method to trace 1084 * once_arg - Whether trace once 1085 * 1086 * RETURN: None 1087 * 1088 * DESCRIPTION: Control method tracing facility 1089 * 1090 ******************************************************************************/ 1091 1092 void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg) 1093 { 1094 u32 debug_level = 0; 1095 u32 debug_layer = 0; 1096 u32 flags = 0; 1097 1098 acpi_ut_strupr(enable_arg); 1099 acpi_ut_strupr(once_arg); 1100 1101 if (method_arg) { 1102 if (acpi_db_trace_method_name) { 1103 ACPI_FREE(acpi_db_trace_method_name); 1104 acpi_db_trace_method_name = NULL; 1105 } 1106 1107 acpi_db_trace_method_name = 1108 ACPI_ALLOCATE(strlen(method_arg) + 1); 1109 if (!acpi_db_trace_method_name) { 1110 acpi_os_printf("Failed to allocate method name (%s)\n", 1111 method_arg); 1112 return; 1113 } 1114 1115 strcpy(acpi_db_trace_method_name, method_arg); 1116 } 1117 1118 if (!strcmp(enable_arg, "ENABLE") || 1119 !strcmp(enable_arg, "METHOD") || !strcmp(enable_arg, "OPCODE")) { 1120 if (!strcmp(enable_arg, "ENABLE")) { 1121 1122 /* Inherit current console settings */ 1123 1124 debug_level = acpi_gbl_db_console_debug_level; 1125 debug_layer = acpi_dbg_layer; 1126 } else { 1127 /* Restrict console output to trace points only */ 1128 1129 debug_level = ACPI_LV_TRACE_POINT; 1130 debug_layer = ACPI_EXECUTER; 1131 } 1132 1133 flags = ACPI_TRACE_ENABLED; 1134 1135 if (!strcmp(enable_arg, "OPCODE")) { 1136 flags |= ACPI_TRACE_OPCODE; 1137 } 1138 1139 if (once_arg && !strcmp(once_arg, "ONCE")) { 1140 flags |= ACPI_TRACE_ONESHOT; 1141 } 1142 } 1143 1144 (void)acpi_debug_trace(acpi_db_trace_method_name, 1145 debug_level, debug_layer, flags); 1146 } 1147