linux/drivers/acpi/acpica/dbobject.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/*******************************************************************************
   3 *
   4 * Module Name: dbobject - ACPI object decode and display
   5 *
   6 ******************************************************************************/
   7
   8#include <acpi/acpi.h>
   9#include "accommon.h"
  10#include "acnamesp.h"
  11#include "acdebug.h"
  12
  13#define _COMPONENT          ACPI_CA_DEBUGGER
  14ACPI_MODULE_NAME("dbobject")
  15
  16/* Local prototypes */
  17static void acpi_db_decode_node(struct acpi_namespace_node *node);
  18
  19/*******************************************************************************
  20 *
  21 * FUNCTION:    acpi_db_dump_method_info
  22 *
  23 * PARAMETERS:  status          - Method execution status
  24 *              walk_state      - Current state of the parse tree walk
  25 *
  26 * RETURN:      None
  27 *
  28 * DESCRIPTION: Called when a method has been aborted because of an error.
  29 *              Dumps the method execution stack, and the method locals/args,
  30 *              and disassembles the AML opcode that failed.
  31 *
  32 ******************************************************************************/
  33
  34void
  35acpi_db_dump_method_info(acpi_status status, struct acpi_walk_state *walk_state)
  36{
  37        struct acpi_thread_state *thread;
  38        struct acpi_namespace_node *node;
  39
  40        node = walk_state->method_node;
  41
  42        /* There are no locals or arguments for the module-level code case */
  43
  44        if (node == acpi_gbl_root_node) {
  45                return;
  46        }
  47
  48        /* Ignore control codes, they are not errors */
  49
  50        if (ACPI_CNTL_EXCEPTION(status)) {
  51                return;
  52        }
  53
  54        /* We may be executing a deferred opcode */
  55
  56        if (walk_state->deferred_node) {
  57                acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
  58                return;
  59        }
  60
  61        /*
  62         * If there is no Thread, we are not actually executing a method.
  63         * This can happen when the iASL compiler calls the interpreter
  64         * to perform constant folding.
  65         */
  66        thread = walk_state->thread;
  67        if (!thread) {
  68                return;
  69        }
  70
  71        /* Display the method locals and arguments */
  72
  73        acpi_os_printf("\n");
  74        acpi_db_decode_locals(walk_state);
  75        acpi_os_printf("\n");
  76        acpi_db_decode_arguments(walk_state);
  77        acpi_os_printf("\n");
  78}
  79
  80/*******************************************************************************
  81 *
  82 * FUNCTION:    acpi_db_decode_internal_object
  83 *
  84 * PARAMETERS:  obj_desc        - Object to be displayed
  85 *
  86 * RETURN:      None
  87 *
  88 * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers.
  89 *
  90 ******************************************************************************/
  91
  92void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc)
  93{
  94        u32 i;
  95
  96        if (!obj_desc) {
  97                acpi_os_printf(" Uninitialized");
  98                return;
  99        }
 100
 101        if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
 102                acpi_os_printf(" %p [%s]", obj_desc,
 103                               acpi_ut_get_descriptor_name(obj_desc));
 104                return;
 105        }
 106
 107        acpi_os_printf(" %s", acpi_ut_get_object_type_name(obj_desc));
 108
 109        switch (obj_desc->common.type) {
 110        case ACPI_TYPE_INTEGER:
 111
 112                acpi_os_printf(" %8.8X%8.8X",
 113                               ACPI_FORMAT_UINT64(obj_desc->integer.value));
 114                break;
 115
 116        case ACPI_TYPE_STRING:
 117
 118                acpi_os_printf("(%u) \"%.60s",
 119                               obj_desc->string.length,
 120                               obj_desc->string.pointer);
 121
 122                if (obj_desc->string.length > 60) {
 123                        acpi_os_printf("...");
 124                } else {
 125                        acpi_os_printf("\"");
 126                }
 127                break;
 128
 129        case ACPI_TYPE_BUFFER:
 130
 131                acpi_os_printf("(%u)", obj_desc->buffer.length);
 132                for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) {
 133                        acpi_os_printf(" %2.2X", obj_desc->buffer.pointer[i]);
 134                }
 135                break;
 136
 137        default:
 138
 139                acpi_os_printf(" %p", obj_desc);
 140                break;
 141        }
 142}
 143
 144/*******************************************************************************
 145 *
 146 * FUNCTION:    acpi_db_decode_node
 147 *
 148 * PARAMETERS:  node        - Object to be displayed
 149 *
 150 * RETURN:      None
 151 *
 152 * DESCRIPTION: Short display of a namespace node
 153 *
 154 ******************************************************************************/
 155
 156static void acpi_db_decode_node(struct acpi_namespace_node *node)
 157{
 158
 159        acpi_os_printf("<Node>          Name %4.4s",
 160                       acpi_ut_get_node_name(node));
 161
 162        if (node->flags & ANOBJ_METHOD_ARG) {
 163                acpi_os_printf(" [Method Arg]");
 164        }
 165        if (node->flags & ANOBJ_METHOD_LOCAL) {
 166                acpi_os_printf(" [Method Local]");
 167        }
 168
 169        switch (node->type) {
 170
 171                /* These types have no attached object */
 172
 173        case ACPI_TYPE_DEVICE:
 174
 175                acpi_os_printf(" Device");
 176                break;
 177
 178        case ACPI_TYPE_THERMAL:
 179
 180                acpi_os_printf(" Thermal Zone");
 181                break;
 182
 183        default:
 184
 185                acpi_db_decode_internal_object(acpi_ns_get_attached_object
 186                                               (node));
 187                break;
 188        }
 189}
 190
 191/*******************************************************************************
 192 *
 193 * FUNCTION:    acpi_db_display_internal_object
 194 *
 195 * PARAMETERS:  obj_desc        - Object to be displayed
 196 *              walk_state      - Current walk state
 197 *
 198 * RETURN:      None
 199 *
 200 * DESCRIPTION: Short display of an internal object
 201 *
 202 ******************************************************************************/
 203
 204void
 205acpi_db_display_internal_object(union acpi_operand_object *obj_desc,
 206                                struct acpi_walk_state *walk_state)
 207{
 208        u8 type;
 209
 210        acpi_os_printf("%p ", obj_desc);
 211
 212        if (!obj_desc) {
 213                acpi_os_printf("<Null Object>\n");
 214                return;
 215        }
 216
 217        /* Decode the object type */
 218
 219        switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
 220        case ACPI_DESC_TYPE_PARSER:
 221
 222                acpi_os_printf("<Parser> ");
 223                break;
 224
 225        case ACPI_DESC_TYPE_NAMED:
 226
 227                acpi_db_decode_node((struct acpi_namespace_node *)obj_desc);
 228                break;
 229
 230        case ACPI_DESC_TYPE_OPERAND:
 231
 232                type = obj_desc->common.type;
 233                if (type > ACPI_TYPE_LOCAL_MAX) {
 234                        acpi_os_printf(" Type %X [Invalid Type]", (u32)type);
 235                        return;
 236                }
 237
 238                /* Decode the ACPI object type */
 239
 240                switch (obj_desc->common.type) {
 241                case ACPI_TYPE_LOCAL_REFERENCE:
 242
 243                        acpi_os_printf("[%s] ",
 244                                       acpi_ut_get_reference_name(obj_desc));
 245
 246                        /* Decode the reference */
 247
 248                        switch (obj_desc->reference.class) {
 249                        case ACPI_REFCLASS_LOCAL:
 250
 251                                acpi_os_printf("%X ",
 252                                               obj_desc->reference.value);
 253                                if (walk_state) {
 254                                        obj_desc = walk_state->local_variables
 255                                            [obj_desc->reference.value].object;
 256                                        acpi_os_printf("%p", obj_desc);
 257                                        acpi_db_decode_internal_object
 258                                            (obj_desc);
 259                                }
 260                                break;
 261
 262                        case ACPI_REFCLASS_ARG:
 263
 264                                acpi_os_printf("%X ",
 265                                               obj_desc->reference.value);
 266                                if (walk_state) {
 267                                        obj_desc = walk_state->arguments
 268                                            [obj_desc->reference.value].object;
 269                                        acpi_os_printf("%p", obj_desc);
 270                                        acpi_db_decode_internal_object
 271                                            (obj_desc);
 272                                }
 273                                break;
 274
 275                        case ACPI_REFCLASS_INDEX:
 276
 277                                switch (obj_desc->reference.target_type) {
 278                                case ACPI_TYPE_BUFFER_FIELD:
 279
 280                                        acpi_os_printf("%p",
 281                                                       obj_desc->reference.
 282                                                       object);
 283                                        acpi_db_decode_internal_object
 284                                            (obj_desc->reference.object);
 285                                        break;
 286
 287                                case ACPI_TYPE_PACKAGE:
 288
 289                                        acpi_os_printf("%p",
 290                                                       obj_desc->reference.
 291                                                       where);
 292                                        if (!obj_desc->reference.where) {
 293                                                acpi_os_printf
 294                                                    (" Uninitialized WHERE pointer");
 295                                        } else {
 296                                                acpi_db_decode_internal_object(*
 297                                                                               (obj_desc->
 298                                                                                reference.
 299                                                                                where));
 300                                        }
 301                                        break;
 302
 303                                default:
 304
 305                                        acpi_os_printf
 306                                            ("Unknown index target type");
 307                                        break;
 308                                }
 309                                break;
 310
 311                        case ACPI_REFCLASS_REFOF:
 312
 313                                if (!obj_desc->reference.object) {
 314                                        acpi_os_printf
 315                                            ("Uninitialized reference subobject pointer");
 316                                        break;
 317                                }
 318
 319                                /* Reference can be to a Node or an Operand object */
 320
 321                                switch (ACPI_GET_DESCRIPTOR_TYPE
 322                                        (obj_desc->reference.object)) {
 323                                case ACPI_DESC_TYPE_NAMED:
 324
 325                                        acpi_db_decode_node(obj_desc->reference.
 326                                                            object);
 327                                        break;
 328
 329                                case ACPI_DESC_TYPE_OPERAND:
 330
 331                                        acpi_db_decode_internal_object
 332                                            (obj_desc->reference.object);
 333                                        break;
 334
 335                                default:
 336                                        break;
 337                                }
 338                                break;
 339
 340                        case ACPI_REFCLASS_NAME:
 341
 342                                acpi_db_decode_node(obj_desc->reference.node);
 343                                break;
 344
 345                        case ACPI_REFCLASS_DEBUG:
 346                        case ACPI_REFCLASS_TABLE:
 347
 348                                acpi_os_printf("\n");
 349                                break;
 350
 351                        default:        /* Unknown reference class */
 352
 353                                acpi_os_printf("%2.2X\n",
 354                                               obj_desc->reference.class);
 355                                break;
 356                        }
 357                        break;
 358
 359                default:
 360
 361                        acpi_os_printf("<Obj>          ");
 362                        acpi_db_decode_internal_object(obj_desc);
 363                        break;
 364                }
 365                break;
 366
 367        default:
 368
 369                acpi_os_printf("<Not a valid ACPI Object Descriptor> [%s]",
 370                               acpi_ut_get_descriptor_name(obj_desc));
 371                break;
 372        }
 373
 374        acpi_os_printf("\n");
 375}
 376
 377/*******************************************************************************
 378 *
 379 * FUNCTION:    acpi_db_decode_locals
 380 *
 381 * PARAMETERS:  walk_state      - State for current method
 382 *
 383 * RETURN:      None
 384 *
 385 * DESCRIPTION: Display all locals for the currently running control method
 386 *
 387 ******************************************************************************/
 388
 389void acpi_db_decode_locals(struct acpi_walk_state *walk_state)
 390{
 391        u32 i;
 392        union acpi_operand_object *obj_desc;
 393        struct acpi_namespace_node *node;
 394        u8 display_locals = FALSE;
 395
 396        node = walk_state->method_node;
 397
 398        /* There are no locals for the module-level code case */
 399
 400        if (node == acpi_gbl_root_node) {
 401                return;
 402        }
 403
 404        if (!node) {
 405                acpi_os_printf
 406                    ("No method node (Executing subtree for buffer or opregion)\n");
 407                return;
 408        }
 409
 410        if (node->type != ACPI_TYPE_METHOD) {
 411                acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
 412                return;
 413        }
 414
 415        /* Are any locals actually set? */
 416
 417        for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
 418                obj_desc = walk_state->local_variables[i].object;
 419                if (obj_desc) {
 420                        display_locals = TRUE;
 421                        break;
 422                }
 423        }
 424
 425        /* If any are set, only display the ones that are set */
 426
 427        if (display_locals) {
 428                acpi_os_printf
 429                    ("\nInitialized Local Variables for Method [%4.4s]:\n",
 430                     acpi_ut_get_node_name(node));
 431
 432                for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
 433                        obj_desc = walk_state->local_variables[i].object;
 434                        if (obj_desc) {
 435                                acpi_os_printf("  Local%X: ", i);
 436                                acpi_db_display_internal_object(obj_desc,
 437                                                                walk_state);
 438                        }
 439                }
 440        } else {
 441                acpi_os_printf
 442                    ("No Local Variables are initialized for Method [%4.4s]\n",
 443                     acpi_ut_get_node_name(node));
 444        }
 445}
 446
 447/*******************************************************************************
 448 *
 449 * FUNCTION:    acpi_db_decode_arguments
 450 *
 451 * PARAMETERS:  walk_state      - State for current method
 452 *
 453 * RETURN:      None
 454 *
 455 * DESCRIPTION: Display all arguments for the currently running control method
 456 *
 457 ******************************************************************************/
 458
 459void acpi_db_decode_arguments(struct acpi_walk_state *walk_state)
 460{
 461        u32 i;
 462        union acpi_operand_object *obj_desc;
 463        struct acpi_namespace_node *node;
 464        u8 display_args = FALSE;
 465
 466        node = walk_state->method_node;
 467
 468        /* There are no arguments for the module-level code case */
 469
 470        if (node == acpi_gbl_root_node) {
 471                return;
 472        }
 473
 474        if (!node) {
 475                acpi_os_printf
 476                    ("No method node (Executing subtree for buffer or opregion)\n");
 477                return;
 478        }
 479
 480        if (node->type != ACPI_TYPE_METHOD) {
 481                acpi_os_printf("Executing subtree for Buffer/Package/Region\n");
 482                return;
 483        }
 484
 485        /* Are any arguments actually set? */
 486
 487        for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
 488                obj_desc = walk_state->arguments[i].object;
 489                if (obj_desc) {
 490                        display_args = TRUE;
 491                        break;
 492                }
 493        }
 494
 495        /* If any are set, only display the ones that are set */
 496
 497        if (display_args) {
 498                acpi_os_printf("Initialized Arguments for Method [%4.4s]:  "
 499                               "(%X arguments defined for method invocation)\n",
 500                               acpi_ut_get_node_name(node),
 501                               node->object->method.param_count);
 502
 503                for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
 504                        obj_desc = walk_state->arguments[i].object;
 505                        if (obj_desc) {
 506                                acpi_os_printf("  Arg%u:   ", i);
 507                                acpi_db_display_internal_object(obj_desc,
 508                                                                walk_state);
 509                        }
 510                }
 511        } else {
 512                acpi_os_printf
 513                    ("No Arguments are initialized for method [%4.4s]\n",
 514                     acpi_ut_get_node_name(node));
 515        }
 516}
 517