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
acpi_db_dump_method_info(acpi_status status,struct acpi_walk_state * walk_state)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 
acpi_db_decode_internal_object(union acpi_operand_object * obj_desc)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 
acpi_db_decode_node(struct acpi_namespace_node * node)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
acpi_db_display_internal_object(union acpi_operand_object * obj_desc,struct acpi_walk_state * walk_state)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 
acpi_db_decode_locals(struct acpi_walk_state * walk_state)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 
acpi_db_decode_arguments(struct acpi_walk_state * walk_state)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