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(format: "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(format: "\n");
74 acpi_db_decode_locals(walk_state);
75 acpi_os_printf(format: "\n");
76 acpi_db_decode_arguments(walk_state);
77 acpi_os_printf(format: "\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(format: " Uninitialized");
98 return;
99 }
100
101 if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
102 acpi_os_printf(format: " %p [%s]", obj_desc,
103 acpi_ut_get_descriptor_name(object: obj_desc));
104 return;
105 }
106
107 acpi_os_printf(format: " %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(format: " %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(format: "(%u) \"%.60s",
119 obj_desc->string.length,
120 obj_desc->string.pointer);
121
122 if (obj_desc->string.length > 60) {
123 acpi_os_printf(format: "...");
124 } else {
125 acpi_os_printf(format: "\"");
126 }
127 break;
128
129 case ACPI_TYPE_BUFFER:
130
131 acpi_os_printf(format: "(%u)", obj_desc->buffer.length);
132 for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) {
133 acpi_os_printf(format: " %2.2X", obj_desc->buffer.pointer[i]);
134 }
135 break;
136
137 default:
138
139 acpi_os_printf(format: " %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(format: "<Node> Name %4.4s",
160 acpi_ut_get_node_name(object: node));
161
162 if (node->flags & ANOBJ_METHOD_ARG) {
163 acpi_os_printf(format: " [Method Arg]");
164 }
165 if (node->flags & ANOBJ_METHOD_LOCAL) {
166 acpi_os_printf(format: " [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(format: " Device");
176 break;
177
178 case ACPI_TYPE_THERMAL:
179
180 acpi_os_printf(format: " Thermal Zone");
181 break;
182
183 default:
184
185 acpi_db_decode_internal_object(obj_desc: 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(format: "%p ", obj_desc);
211
212 if (!obj_desc) {
213 acpi_os_printf(format: "<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(format: "<Parser> ");
223 break;
224
225 case ACPI_DESC_TYPE_NAMED:
226
227 acpi_db_decode_node(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(format: " 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(format: "[%s] ",
244 acpi_ut_get_reference_name(object: obj_desc));
245
246 /* Decode the reference */
247
248 switch (obj_desc->reference.class) {
249 case ACPI_REFCLASS_LOCAL:
250
251 acpi_os_printf(format: "%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(format: "%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(format: "%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(format: "%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(format: "%p",
281 obj_desc->reference.
282 object);
283 acpi_db_decode_internal_object
284 (obj_desc: obj_desc->reference.object);
285 break;
286
287 case ACPI_TYPE_PACKAGE:
288
289 acpi_os_printf(format: "%p",
290 obj_desc->reference.
291 where);
292 if (!obj_desc->reference.where) {
293 acpi_os_printf
294 (format: " Uninitialized WHERE pointer");
295 } else {
296 acpi_db_decode_internal_object(obj_desc: *
297 (obj_desc->
298 reference.
299 where));
300 }
301 break;
302
303 default:
304
305 acpi_os_printf
306 (format: "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 (format: "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(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: 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(node: obj_desc->reference.node);
343 break;
344
345 case ACPI_REFCLASS_DEBUG:
346 case ACPI_REFCLASS_TABLE:
347
348 acpi_os_printf(format: "\n");
349 break;
350
351 default: /* Unknown reference class */
352
353 acpi_os_printf(format: "%2.2X\n",
354 obj_desc->reference.class);
355 break;
356 }
357 break;
358
359 default:
360
361 acpi_os_printf(format: "<Obj> ");
362 acpi_db_decode_internal_object(obj_desc);
363 break;
364 }
365 break;
366
367 default:
368
369 acpi_os_printf(format: "<Not a valid ACPI Object Descriptor> [%s]",
370 acpi_ut_get_descriptor_name(object: obj_desc));
371 break;
372 }
373
374 acpi_os_printf(format: "\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 (format: "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(format: "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 (format: "\nInitialized Local Variables for Method [%4.4s]:\n",
430 acpi_ut_get_node_name(object: 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(format: " Local%X: ", i);
436 acpi_db_display_internal_object(obj_desc,
437 walk_state);
438 }
439 }
440 } else {
441 acpi_os_printf
442 (format: "No Local Variables are initialized for Method [%4.4s]\n",
443 acpi_ut_get_node_name(object: 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 (format: "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(format: "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(format: "Initialized Arguments for Method [%4.4s]: "
499 "(%X arguments defined for method invocation)\n",
500 acpi_ut_get_node_name(object: 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(format: " Arg%u: ", i);
507 acpi_db_display_internal_object(obj_desc,
508 walk_state);
509 }
510 }
511 } else {
512 acpi_os_printf
513 (format: "No Arguments are initialized for method [%4.4s]\n",
514 acpi_ut_get_node_name(object: node));
515 }
516}
517

source code of linux/drivers/acpi/acpica/dbobject.c