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 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 83 void 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 147 static 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 195 void 196 acpi_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 380 void 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 445 void 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