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