Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 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
 83void 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
147static 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
195void
196acpi_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
380void 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
445void 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}