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 14 ACPI_MODULE_NAME("dbobject") 15 16 /* Local prototypes */ 17 static 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 34 void 35 acpi_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 ((status & AE_CODE_MASK) == AE_CODE_CONTROL) { 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 92 void 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 156 static 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 204 void 205 acpi_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 refererence */ 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 389 void 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 obj_desc = walk_state->method_desc; 398 399 /* There are no locals for the module-level code case */ 400 401 if (node == acpi_gbl_root_node) { 402 return; 403 } 404 405 if (!node) { 406 acpi_os_printf 407 ("No method node (Executing subtree for buffer or opregion)\n"); 408 return; 409 } 410 411 if (node->type != ACPI_TYPE_METHOD) { 412 acpi_os_printf("Executing subtree for Buffer/Package/Region\n"); 413 return; 414 } 415 416 /* Are any locals actually set? */ 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 display_locals = TRUE; 422 break; 423 } 424 } 425 426 /* If any are set, only display the ones that are set */ 427 428 if (display_locals) { 429 acpi_os_printf 430 ("\nInitialized Local Variables for Method [%4.4s]:\n", 431 acpi_ut_get_node_name(node)); 432 433 for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) { 434 obj_desc = walk_state->local_variables[i].object; 435 if (obj_desc) { 436 acpi_os_printf(" Local%X: ", i); 437 acpi_db_display_internal_object(obj_desc, 438 walk_state); 439 } 440 } 441 } else { 442 acpi_os_printf 443 ("No Local Variables are initialized for Method [%4.4s]\n", 444 acpi_ut_get_node_name(node)); 445 } 446 } 447 448 /******************************************************************************* 449 * 450 * FUNCTION: acpi_db_decode_arguments 451 * 452 * PARAMETERS: walk_state - State for current method 453 * 454 * RETURN: None 455 * 456 * DESCRIPTION: Display all arguments for the currently running control method 457 * 458 ******************************************************************************/ 459 460 void acpi_db_decode_arguments(struct acpi_walk_state *walk_state) 461 { 462 u32 i; 463 union acpi_operand_object *obj_desc; 464 struct acpi_namespace_node *node; 465 u8 display_args = FALSE; 466 467 node = walk_state->method_node; 468 obj_desc = walk_state->method_desc; 469 470 /* There are no arguments for the module-level code case */ 471 472 if (node == acpi_gbl_root_node) { 473 return; 474 } 475 476 if (!node) { 477 acpi_os_printf 478 ("No method node (Executing subtree for buffer or opregion)\n"); 479 return; 480 } 481 482 if (node->type != ACPI_TYPE_METHOD) { 483 acpi_os_printf("Executing subtree for Buffer/Package/Region\n"); 484 return; 485 } 486 487 /* Are any arguments actually set? */ 488 489 for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { 490 obj_desc = walk_state->arguments[i].object; 491 if (obj_desc) { 492 display_args = TRUE; 493 break; 494 } 495 } 496 497 /* If any are set, only display the ones that are set */ 498 499 if (display_args) { 500 acpi_os_printf("Initialized Arguments for Method [%4.4s]: " 501 "(%X arguments defined for method invocation)\n", 502 acpi_ut_get_node_name(node), 503 node->object->method.param_count); 504 505 for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { 506 obj_desc = walk_state->arguments[i].object; 507 if (obj_desc) { 508 acpi_os_printf(" Arg%u: ", i); 509 acpi_db_display_internal_object(obj_desc, 510 walk_state); 511 } 512 } 513 } else { 514 acpi_os_printf 515 ("No Arguments are initialized for method [%4.4s]\n", 516 acpi_ut_get_node_name(node)); 517 } 518 } 519