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 (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 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 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 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 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 459 void 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