1/*******************************************************************************
2 *
3 * Module Name: dbdisply - debug display commands
4 *              $Revision: 1.1.1.1 $
5 *
6 ******************************************************************************/
7
8/*
9 *  Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation; either version 2 of the License, or
14 *  (at your option) any later version.
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 *  GNU General Public License for more details.
20 *
21 *  You should have received a copy of the GNU General Public License
22 *  along with this program; if not, write to the Free Software
23 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26
27#include "acpi.h"
28#include "acparser.h"
29#include "amlcode.h"
30#include "acdispat.h"
31#include "acnamesp.h"
32#include "acparser.h"
33#include "acevents.h"
34#include "acinterp.h"
35#include "acdebug.h"
36
37
38#ifdef ENABLE_DEBUGGER
39
40
41#define _COMPONENT          ACPI_DEBUGGER
42	 MODULE_NAME         ("dbdisply")
43
44
45/******************************************************************************
46 *
47 * FUNCTION:    Acpi_db_get_pointer
48 *
49 * PARAMETERS:  Target          - Pointer to string to be converted
50 *
51 * RETURN:      Converted pointer
52 *
53 * DESCRIPTION: Convert an ascii pointer value to a real value
54 *
55 *****************************************************************************/
56
57void *
58acpi_db_get_pointer (
59	void                    *target)
60{
61	void                    *obj_ptr;
62
63
64#ifdef _IA16
65#include <stdio.h>
66
67	/* Have to handle 16-bit pointers of the form segment:offset */
68
69	if (!sscanf (target, "%p", &obj_ptr)) {
70		acpi_os_printf ("Invalid pointer: %s\n", target);
71		return (NULL);
72	}
73
74#else
75
76	/* Simple flat pointer */
77
78	obj_ptr = (void *) STRTOUL (target, NULL, 16);
79
80#endif
81
82	return (obj_ptr);
83}
84
85
86/*******************************************************************************
87 *
88 * FUNCTION:    Acpi_db_dump_parser_descriptor
89 *
90 * PARAMETERS:  Op              - A parser Op descriptor
91 *
92 * RETURN:      None
93 *
94 * DESCRIPTION: Display a formatted parser object
95 *
96 ******************************************************************************/
97
98void
99acpi_db_dump_parser_descriptor (
100	acpi_parse_object       *op)
101{
102	const acpi_opcode_info  *info;
103
104
105	info = acpi_ps_get_opcode_info (op->opcode);
106
107	acpi_os_printf ("Parser Op Descriptor:\n");
108	acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->opcode);
109
110	DEBUG_ONLY_MEMBERS (acpi_os_printf ("%20.20s : %s\n", "Opcode Name", info->name));
111
112	acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->value);
113	acpi_os_printf ("%20.20s : %p\n", "Parent", op->parent);
114	acpi_os_printf ("%20.20s : %p\n", "Next_op", op->next);
115}
116
117
118/*******************************************************************************
119 *
120 * FUNCTION:    Acpi_db_decode_and_display_object
121 *
122 * PARAMETERS:  Target          - String with object to be displayed.  Names
123 *                                and hex pointers are supported.
124 *              Output_type     - Byte, Word, Dword, or Qword (B|W|D|Q)
125 *
126 * RETURN:      None
127 *
128 * DESCRIPTION: Display a formatted ACPI object
129 *
130 ******************************************************************************/
131
132void
133acpi_db_decode_and_display_object (
134	NATIVE_CHAR             *target,
135	NATIVE_CHAR             *output_type)
136{
137	void                    *obj_ptr;
138	acpi_namespace_node     *node;
139	u32                     display = DB_BYTE_DISPLAY;
140	NATIVE_CHAR             buffer[80];
141	acpi_buffer             ret_buf;
142	acpi_status             status;
143	u32                     size;
144
145
146	if (!target) {
147		return;
148	}
149
150	/* Decode the output type */
151
152	if (output_type) {
153		STRUPR (output_type);
154		if (output_type[0] == 'W') {
155			display = DB_WORD_DISPLAY;
156		}
157		else if (output_type[0] == 'D') {
158			display = DB_DWORD_DISPLAY;
159		}
160		else if (output_type[0] == 'Q') {
161			display = DB_QWORD_DISPLAY;
162		}
163	}
164
165
166	ret_buf.length = sizeof (buffer);
167	ret_buf.pointer = buffer;
168
169	/* Differentiate between a number and a name */
170
171	if ((target[0] >= 0x30) && (target[0] <= 0x39)) {
172		obj_ptr = acpi_db_get_pointer (target);
173		if (!acpi_os_readable (obj_ptr, 16)) {
174			acpi_os_printf ("Address %p is invalid in this address space\n", obj_ptr);
175			return;
176		}
177
178		/* Decode the object type */
179
180		if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_NAMED)) {
181			/* This is a Node */
182
183			if (!acpi_os_readable (obj_ptr, sizeof (acpi_namespace_node))) {
184				acpi_os_printf ("Cannot read entire Named object at address %p\n", obj_ptr);
185				return;
186			}
187
188			node = obj_ptr;
189			goto dump_nte;
190		}
191
192		else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_INTERNAL)) {
193			/* This is an ACPI OBJECT */
194
195			if (!acpi_os_readable (obj_ptr, sizeof (acpi_operand_object))) {
196				acpi_os_printf ("Cannot read entire ACPI object at address %p\n", obj_ptr);
197				return;
198			}
199
200			acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX);
201			acpi_ex_dump_object_descriptor (obj_ptr, 1);
202		}
203
204		else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_PARSER)) {
205			/* This is an Parser Op object */
206
207			if (!acpi_os_readable (obj_ptr, sizeof (acpi_parse_object))) {
208				acpi_os_printf ("Cannot read entire Parser object at address %p\n", obj_ptr);
209				return;
210			}
211
212
213			acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_parse_object), display, ACPI_UINT32_MAX);
214			acpi_db_dump_parser_descriptor ((acpi_parse_object *) obj_ptr);
215		}
216
217		else {
218			size = 16;
219			if (acpi_os_readable (obj_ptr, 64)) {
220				size = 64;
221			}
222
223			/* Just dump some memory */
224
225			acpi_ut_dump_buffer (obj_ptr, size, display, ACPI_UINT32_MAX);
226		}
227
228		return;
229	}
230
231
232	/* The parameter is a name string that must be resolved to a Named obj */
233
234	node = acpi_db_local_ns_lookup (target);
235	if (!node) {
236		return;
237	}
238
239
240dump_nte:
241	/* Now dump the Named obj */
242
243	status = acpi_get_name (node, ACPI_FULL_PATHNAME, &ret_buf);
244	if (ACPI_FAILURE (status)) {
245		acpi_os_printf ("Could not convert name to pathname\n");
246	}
247
248	else {
249		acpi_os_printf ("Object (%p) Pathname: %s\n", node, ret_buf.pointer);
250	}
251
252	if (!acpi_os_readable (node, sizeof (acpi_namespace_node))) {
253		acpi_os_printf ("Invalid Named object at address %p\n", node);
254		return;
255	}
256
257	acpi_ut_dump_buffer ((void *) node, sizeof (acpi_namespace_node), display, ACPI_UINT32_MAX);
258	acpi_ex_dump_node (node, 1);
259
260	if (node->object) {
261		acpi_os_printf ("\n_attached Object (%p):\n", node->object);
262		if (!acpi_os_readable (node->object, sizeof (acpi_operand_object))) {
263			acpi_os_printf ("Invalid internal ACPI Object at address %p\n", node->object);
264			return;
265		}
266
267		acpi_ut_dump_buffer ((void *) node->object, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX);
268		acpi_ex_dump_object_descriptor (node->object, 1);
269	}
270}
271
272
273/*******************************************************************************
274 *
275 * FUNCTION:    Acpi_db_decode_internal_object
276 *
277 * PARAMETERS:  Obj_desc        - Object to be displayed
278 *
279 * RETURN:      None
280 *
281 * DESCRIPTION: Short display of an internal object.  Numbers and Strings.
282 *
283 ******************************************************************************/
284
285void
286acpi_db_decode_internal_object (
287	acpi_operand_object     *obj_desc)
288{
289	u32                     i;
290
291
292	if (!obj_desc) {
293		return;
294	}
295
296	acpi_os_printf (" %s", acpi_ut_get_type_name (obj_desc->common.type));
297
298	switch (obj_desc->common.type) {
299	case ACPI_TYPE_INTEGER:
300
301		acpi_os_printf (" %.8X%.8X", HIDWORD (obj_desc->integer.value),
302				 LODWORD (obj_desc->integer.value));
303		break;
304
305
306	case ACPI_TYPE_STRING:
307
308		acpi_os_printf ("(%d) \"%.24s",
309				obj_desc->string.length, obj_desc->string.pointer);
310
311		if (obj_desc->string.length > 24)
312		{
313			acpi_os_printf ("...");
314		}
315		else
316		{
317			acpi_os_printf ("\"");
318		}
319		break;
320
321
322	case ACPI_TYPE_BUFFER:
323
324		acpi_os_printf ("(%d)", obj_desc->buffer.length);
325		for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) {
326			acpi_os_printf (" %2.2X", obj_desc->buffer.pointer[i]);
327		}
328		break;
329	}
330}
331
332
333/*******************************************************************************
334 *
335 * FUNCTION:    Acpi_db_display_internal_object
336 *
337 * PARAMETERS:  Obj_desc        - Object to be displayed
338 *              Walk_state      - Current walk state
339 *
340 * RETURN:      None
341 *
342 * DESCRIPTION: Short display of an internal object
343 *
344 ******************************************************************************/
345
346void
347acpi_db_display_internal_object (
348	acpi_operand_object     *obj_desc,
349	acpi_walk_state         *walk_state)
350{
351	u8                      type;
352
353
354	acpi_os_printf ("%p ", obj_desc);
355
356	if (!obj_desc) {
357		acpi_os_printf ("<Null_obj>\n");
358		return;
359	}
360
361
362	/* Decode the object type */
363
364	else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_PARSER)) {
365		acpi_os_printf ("<Parser> ");
366	}
367
368	else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
369		acpi_os_printf ("<Node>          Name %4.4s Type-%s",
370				  &((acpi_namespace_node *)obj_desc)->name,
371				  acpi_ut_get_type_name (((acpi_namespace_node *) obj_desc)->type));
372		if (((acpi_namespace_node *) obj_desc)->flags & ANOBJ_METHOD_ARG) {
373			acpi_os_printf (" [Method Arg]");
374		}
375		if (((acpi_namespace_node *) obj_desc)->flags & ANOBJ_METHOD_LOCAL) {
376			acpi_os_printf (" [Method Local]");
377		}
378	}
379
380	else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
381		type = obj_desc->common.type;
382		if (type > INTERNAL_TYPE_MAX) {
383			acpi_os_printf (" Type %x [Invalid Type]", type);
384			return;
385		}
386
387		/* Decode the ACPI object type */
388
389		switch (obj_desc->common.type) {
390		case INTERNAL_TYPE_REFERENCE:
391			switch (obj_desc->reference.opcode) {
392			case AML_ZERO_OP:
393				acpi_os_printf ("[Const]         Zero (0) [Null Target]", 0);
394				break;
395
396			case AML_ONES_OP:
397				acpi_os_printf ("[Const]         Ones (0xFFFFFFFFFFFFFFFF) [No Limit]");
398				break;
399
400			case AML_ONE_OP:
401				acpi_os_printf ("[Const]         One (1)");
402				break;
403
404			case AML_REVISION_OP:
405				acpi_os_printf ("[Const]         Revision (%X)", ACPI_CA_SUPPORT_LEVEL);
406				break;
407
408			case AML_LOCAL_OP:
409				acpi_os_printf ("[Local%d]", obj_desc->reference.offset);
410				if (walk_state) {
411					obj_desc = walk_state->local_variables[obj_desc->reference.offset].object;
412					acpi_os_printf (" %p", obj_desc);
413					acpi_db_decode_internal_object (obj_desc);
414				}
415				break;
416
417			case AML_ARG_OP:
418				acpi_os_printf ("[Arg%d] ", obj_desc->reference.offset);
419				if (walk_state) {
420					obj_desc = walk_state->arguments[obj_desc->reference.offset].object;
421					acpi_os_printf (" %p", obj_desc);
422					acpi_db_decode_internal_object (obj_desc);
423				}
424				break;
425
426			case AML_DEBUG_OP:
427				acpi_os_printf ("[Debug] ");
428				break;
429
430			case AML_INDEX_OP:
431				acpi_os_printf ("[Index]   ");
432				acpi_db_decode_internal_object (obj_desc->reference.object);
433				break;
434
435			default:
436				break;
437
438			}
439			break;
440
441		default:
442			acpi_os_printf ("<Obj> ");
443			acpi_os_printf ("         ");
444			acpi_db_decode_internal_object (obj_desc);
445			break;
446		}
447	}
448
449	else {
450		acpi_os_printf ("<Not a valid ACPI Object Descriptor> ");
451	}
452
453	acpi_os_printf ("\n");
454}
455
456
457/*******************************************************************************
458 *
459 * FUNCTION:    Acpi_db_display_method_info
460 *
461 * PARAMETERS:  Start_op        - Root of the control method parse tree
462 *
463 * RETURN:      None
464 *
465 * DESCRIPTION: Display information about the current method
466 *
467 ******************************************************************************/
468
469void
470acpi_db_display_method_info (
471	acpi_parse_object       *start_op)
472{
473	acpi_walk_state         *walk_state;
474	acpi_operand_object     *obj_desc;
475	acpi_namespace_node     *node;
476	acpi_parse_object       *root_op;
477	acpi_parse_object       *op;
478	const acpi_opcode_info  *op_info;
479	u32                     num_ops = 0;
480	u32                     num_operands = 0;
481	u32                     num_operators = 0;
482	u32                     num_remaining_ops = 0;
483	u32                     num_remaining_operands = 0;
484	u32                     num_remaining_operators = 0;
485	u32                     num_args;
486	u32                     concurrency;
487	u8                      count_remaining = FALSE;
488
489
490	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
491	if (!walk_state) {
492		acpi_os_printf ("There is no method currently executing\n");
493		return;
494	}
495
496	obj_desc = walk_state->method_desc;
497	node = walk_state->method_node;
498
499	num_args = obj_desc->method.param_count;
500	concurrency = obj_desc->method.concurrency;
501
502	acpi_os_printf ("Currently executing control method is [%4.4s]\n", &node->name);
503	acpi_os_printf ("%X arguments, max concurrency = %X\n", num_args, concurrency);
504
505
506	root_op = start_op;
507	while (root_op->parent) {
508		root_op = root_op->parent;
509	}
510
511	op = root_op;
512
513	while (op) {
514		if (op == start_op) {
515			count_remaining = TRUE;
516		}
517
518		num_ops++;
519		if (count_remaining) {
520			num_remaining_ops++;
521		}
522
523		/* Decode the opcode */
524
525		op_info = acpi_ps_get_opcode_info (op->opcode);
526		switch (op_info->class) {
527		case AML_CLASS_ARGUMENT:
528			if (count_remaining) {
529				num_remaining_operands++;
530			}
531
532			num_operands++;
533			break;
534
535		case AML_CLASS_UNKNOWN:
536			/* Bad opcode or ASCII character */
537
538			continue;
539
540		default:
541			if (count_remaining) {
542				num_remaining_operators++;
543			}
544
545			num_operators++;
546			break;
547		}
548
549
550		op = acpi_ps_get_depth_next (start_op, op);
551	}
552
553	acpi_os_printf ("Method contains:     %X AML Opcodes - %X Operators, %X Operands\n",
554			 num_ops, num_operators, num_operands);
555
556	acpi_os_printf ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n",
557			 num_remaining_ops, num_remaining_operators, num_remaining_operands);
558}
559
560
561/*******************************************************************************
562 *
563 * FUNCTION:    Acpi_db_display_locals
564 *
565 * PARAMETERS:  None
566 *
567 * RETURN:      None
568 *
569 * DESCRIPTION: Display all locals for the currently running control method
570 *
571 ******************************************************************************/
572
573void
574acpi_db_display_locals (void)
575{
576	u32                     i;
577	acpi_walk_state         *walk_state;
578	acpi_operand_object     *obj_desc;
579	acpi_namespace_node     *node;
580
581
582	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
583	if (!walk_state) {
584		acpi_os_printf ("There is no method currently executing\n");
585		return;
586	}
587
588	obj_desc = walk_state->method_desc;
589	node = walk_state->method_node;
590
591
592	acpi_os_printf ("Local Variables for method [%4.4s]:\n", &node->name);
593
594	for (i = 0; i < MTH_NUM_LOCALS; i++) {
595		obj_desc = walk_state->local_variables[i].object;
596		acpi_os_printf ("Local%d: ", i);
597		acpi_db_display_internal_object (obj_desc, walk_state);
598	}
599}
600
601
602/*******************************************************************************
603 *
604 * FUNCTION:    Acpi_db_display_arguments
605 *
606 * PARAMETERS:  None
607 *
608 * RETURN:      None
609 *
610 * DESCRIPTION: Display all arguments for the currently running control method
611 *
612 ******************************************************************************/
613
614void
615acpi_db_display_arguments (void)
616{
617	u32                     i;
618	acpi_walk_state         *walk_state;
619	acpi_operand_object     *obj_desc;
620	u32                     num_args;
621	u32                     concurrency;
622	acpi_namespace_node     *node;
623
624
625	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
626	if (!walk_state) {
627		acpi_os_printf ("There is no method currently executing\n");
628		return;
629	}
630
631	obj_desc = walk_state->method_desc;
632	node = walk_state->method_node;
633
634	num_args = obj_desc->method.param_count;
635	concurrency = obj_desc->method.concurrency;
636
637	acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", &node->name, num_args, concurrency);
638
639	for (i = 0; i < num_args; i++) {
640		obj_desc = walk_state->arguments[i].object;
641		acpi_os_printf ("Arg%d: ", i);
642		acpi_db_display_internal_object (obj_desc, walk_state);
643	}
644}
645
646
647/*******************************************************************************
648 *
649 * FUNCTION:    Acpi_db_display_results
650 *
651 * PARAMETERS:  None
652 *
653 * RETURN:      None
654 *
655 * DESCRIPTION: Display current contents of a method result stack
656 *
657 ******************************************************************************/
658
659void
660acpi_db_display_results (void)
661{
662	u32                     i;
663	acpi_walk_state         *walk_state;
664	acpi_operand_object     *obj_desc;
665	u32                     num_results = 0;
666	acpi_namespace_node     *node;
667
668
669	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
670	if (!walk_state) {
671		acpi_os_printf ("There is no method currently executing\n");
672		return;
673	}
674
675	obj_desc = walk_state->method_desc;
676	node = walk_state->method_node;
677
678	if (walk_state->results) {
679		num_results = walk_state->results->results.num_results;
680	}
681
682	acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", &node->name, num_results);
683
684	for (i = 0; i < num_results; i++) {
685		obj_desc = walk_state->results->results.obj_desc[i];
686		acpi_os_printf ("Result%d: ", i);
687		acpi_db_display_internal_object (obj_desc, walk_state);
688	}
689}
690
691
692/*******************************************************************************
693 *
694 * FUNCTION:    Acpi_db_display_calling_tree
695 *
696 * PARAMETERS:  None
697 *
698 * RETURN:      None
699 *
700 * DESCRIPTION: Display current calling tree of nested control methods
701 *
702 ******************************************************************************/
703
704void
705acpi_db_display_calling_tree (void)
706{
707	u32                     i;
708	acpi_walk_state         *walk_state;
709	acpi_namespace_node     *node;
710
711
712	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
713	if (!walk_state) {
714		acpi_os_printf ("There is no method currently executing\n");
715		return;
716	}
717
718	node = walk_state->method_node;
719
720	acpi_os_printf ("Current Control Method Call Tree\n");
721
722	for (i = 0; walk_state; i++) {
723		node = walk_state->method_node;
724
725		acpi_os_printf ("  [%4.4s]\n", &node->name);
726
727		walk_state = walk_state->next;
728	}
729}
730
731
732/*******************************************************************************
733 *
734 * FUNCTION:    Acpi_db_display_result_object
735 *
736 * PARAMETERS:  Obj_desc        - Object to be displayed
737 *              Walk_state      - Current walk state
738 *
739 * RETURN:      None
740 *
741 * DESCRIPTION: Display the result of an AML opcode
742 *
743 ******************************************************************************/
744
745void
746acpi_db_display_result_object (
747	acpi_operand_object     *obj_desc,
748	acpi_walk_state         *walk_state)
749{
750
751	/* TBD: [Future] We don't always want to display the result.
752	 * For now, only display if single stepping
753	 * however, this output is very useful in other contexts also
754	 */
755	if (!acpi_gbl_cm_single_step) {
756		return;
757	}
758
759	acpi_os_printf ("Result_obj: ");
760	acpi_db_display_internal_object (obj_desc, walk_state);
761	acpi_os_printf ("\n");
762}
763
764
765/*******************************************************************************
766 *
767 * FUNCTION:    Acpi_db_display_argument_object
768 *
769 * PARAMETERS:  Obj_desc        - Object to be displayed
770 *              Walk_state      - Current walk state
771 *
772 * RETURN:      None
773 *
774 * DESCRIPTION: Display the result of an AML opcode
775 *
776 ******************************************************************************/
777
778void
779acpi_db_display_argument_object (
780	acpi_operand_object     *obj_desc,
781	acpi_walk_state         *walk_state)
782{
783
784
785	if (!acpi_gbl_cm_single_step) {
786		return;
787	}
788
789	acpi_os_printf ("Arg_obj: ");
790	acpi_db_display_internal_object (obj_desc, walk_state);
791}
792
793#endif /* ENABLE_DEBUGGER */
794
795