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