linux/drivers/acpi/acpica/dbcmds.c
<<
>>
Prefs
   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
  17ACPI_MODULE_NAME("dbcmds")
  18
  19/* Local prototypes */
  20static void
  21acpi_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
  26static acpi_status
  27acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name);
  28
  29static acpi_status
  30acpi_db_resource_callback(struct acpi_resource *resource, void *context);
  31
  32static acpi_status
  33acpi_db_device_resources(acpi_handle obj_handle,
  34                         u32 nesting_level, void *context, void **return_value);
  35
  36static void acpi_db_do_one_sleep_state(u8 sleep_state);
  37
  38static 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
  53struct 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
 107acpi_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
 146static 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
 209error_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
 226void 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
 250void 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
 335void 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
 371void 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
 411void 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
 491void 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
 536dump_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
 562static void
 563acpi_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
 658static acpi_status
 659acpi_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);
 712exit2:
 713        ACPI_FREE(resource_buffer.pointer);
 714exit1:
 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
 732static acpi_status
 733acpi_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
 751static acpi_status
 752acpi_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
 820get_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
 892end_crs:
 893                ACPI_FREE(return_buffer.pointer);
 894        }
 895
 896        /* _PRS */
 897
 898get_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
 930get_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
 960cleanup:
 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
 979void 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
1028void 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
1070void 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
1092void 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