1/*	$NetBSD$	*/
2
3/*-
4 * Copyright (c) 1999 Takanori Watanabe
5 * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	Id: debug.c,v 1.19 2000/08/16 18:15:00 iwasaki Exp
30 *	$FreeBSD: src/usr.sbin/acpi/amldb/debug.c,v 1.3 2000/11/09 06:24:40 iwasaki Exp $
31 */
32#include <sys/cdefs.h>
33__RCSID("$NetBSD$");
34
35#include <sys/param.h>
36
37#include <acpi_common.h>
38#include <aml/aml_name.h>
39#include <aml/aml_amlmem.h>
40#include <aml/aml_status.h>
41#include <aml/aml_env.h>
42#include <aml/aml_obj.h>
43#include <aml/aml_evalobj.h>
44#include <aml/aml_parse.h>
45#include <aml/aml_region.h>
46#include <aml/aml_store.h>
47#include <aml/aml_common.h>
48
49#include <assert.h>
50#include <err.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <unistd.h>
55
56#include "debug.h"
57
58static int
59print_named_object(struct aml_name *name, va_list ap)
60{
61
62	aml_print_curname(name);
63	printf("\n");
64
65	return (0);	/* always return success to continue the search */
66}
67
68void
69aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
70{
71#define CMDBUFLEN	512
72#define ARGBUFLEN	512
73	static	char lastcommand[CMDBUFLEN];
74	char	commandline[CMDBUFLEN];
75	char	argbuf[7][ARGBUFLEN];
76	char	*ptr, *method;
77	char	*np, *ep;
78	int 	i;
79	int	argnum;
80	struct	aml_name *name;
81	union	aml_object argv[7], *retval;
82
83	while (1) {
84		fputs("AML>", stderr);
85		fgets(commandline, 512, stdin);
86		commandline[512 - 1] = '\n';	/* safety */
87		if (feof(stdin)) {
88			commandline[0] = 'q';
89		}
90		if (commandline[0] == '\n') {
91			memcpy(commandline, lastcommand, sizeof commandline);
92		}
93		memcpy(lastcommand, commandline, sizeof commandline);
94		switch (commandline[0]) {
95		case 's':
96			if (env2 != NULL) {
97				env2->stat = aml_stat_step;
98			}
99			/* FALLTHROUGH */
100		case 'n':
101			env1->stat = aml_stat_step;
102			return;
103		case 'c':
104			env1->stat = aml_stat_none;
105			return;
106		case 'q':
107			env1->stat = aml_stat_panic;
108			return;
109		case 't':
110			/* NULL terminate */
111			ptr = &commandline[1];
112			while (ptr[0] != '\n')
113				ptr++;
114			ptr[0] = '\0';
115
116			/* move pointer to object name */
117			ptr = &commandline[1];
118			while (ptr[0] == ' ')
119				ptr++;
120
121			/* show current tree if no argument */
122			if (ptr[0] == '\0') {
123				aml_showtree(env1->curname, 0);
124				goto show_variables;
125			}
126			/* start from root? */
127			if (ptr[0] == '\\') {
128				if (ptr[1] == '\0') {
129					aml_showtree(aml_get_rootname(), 0);
130					goto show_variables;
131				}
132				if ((name = aml_find_from_namespace(aml_get_rootname(), ptr))) {
133					aml_showtree(name, 0);
134					goto show_variables;
135				}
136			}
137			if ((name = aml_find_from_namespace(env1->curname, ptr))) {
138				aml_showtree(name, 0);
139			}
140show_variables:
141			for (i = 0; i < 7; i++) {
142				struct aml_name *tmp =
143				aml_local_stack_getArgX(NULL, i);
144
145				if (tmp == NULL || tmp->property == NULL) {
146					break;
147				}
148				printf("  Arg%d    ", i);
149				aml_showobject(tmp->property);
150			}
151			for (i = 0; i < 8; i++) {
152				struct aml_name *tmp =
153				aml_local_stack_getLocalX(i);
154
155				if (tmp == NULL || tmp->property == NULL) {
156					continue;
157				}
158				printf("  Local%d  ", i);
159				aml_showobject(tmp->property);
160			}
161			break;
162		case 'i':
163			aml_debug_prompt_reginput =
164			    (aml_debug_prompt_reginput == 0) ? 1 : 0;
165			if (aml_debug_prompt_reginput)
166				fputs("REGION INPUT ON\n", stderr);
167			else
168				fputs("REGION INPUT OFF\n", stderr);
169			break;
170		case 'o':
171			aml_debug_prompt_regoutput =
172			    (aml_debug_prompt_regoutput == 0) ? 1 : 0;
173			if (aml_debug_prompt_regoutput)
174				fputs("REGION OUTPUT ON\n", stderr);
175			else
176				fputs("REGION OUTPUT OFF\n", stderr);
177			break;
178		case 'm':
179			memman_statistics(aml_memman);
180			break;
181		case 'r':
182			/* NULL terminate */
183			ptr = &commandline[1];
184			while (ptr[0] != '\n')
185				ptr++;
186			ptr[0] = '\0';
187
188			/* move pointer to method name */
189			ptr = &commandline[1];
190			while (ptr[0] == ' ')
191				ptr++;
192
193			if (ptr[0] == '\0') {
194				break;
195			}
196			name = aml_find_from_namespace(aml_get_rootname(), ptr);
197			if (name == NULL) {
198				printf("%s:%d:aml_dbgr: not found name %s\n",
199				    __FILE__, __LINE__, ptr);
200				break;
201			}
202			if (name->property == NULL ||
203			    name->property->type != aml_t_method) {
204				printf("%s:%d:aml_dbgr: not method %s\n",
205				    __FILE__, __LINE__, ptr);
206				break;
207			}
208			aml_showobject(name->property);
209			method = ptr;
210
211			argnum = name->property->meth.argnum & 0x07;
212			if (argnum) {
213				fputs("  Enter argument values "
214				      "(ex. number 1 / string foo). "
215				      "'q' to quit.\n", stderr);
216			}
217			/* get and parse argument values */
218			for (i = 0; i < argnum; i++) {
219retry:
220				fprintf(stderr, "  Arg%d ? ", i);
221				if (read(0, argbuf[i], ARGBUFLEN) == 0) {
222					fputs("\n", stderr);
223					goto retry;
224				}
225				argbuf[i][ARGBUFLEN - 1] = '\n';
226				if (argbuf[i][0] == 'q') {
227					goto finish_execution;
228				}
229				if (argbuf[i][0] == '\n') {
230					goto retry;
231				}
232				/* move pointer to the value */
233				ptr = &argbuf[i][0];
234				while (ptr[0] != ' ' && ptr[0] != '\n') {
235					ptr++;
236				}
237				while (ptr[0] == ' ') {
238					ptr++;
239				}
240				if (ptr[0] == '\n') {
241					goto retry;
242				}
243				switch (argbuf[i][0]) {
244				case 'n':
245					argv[i].type = aml_t_num;
246					np = ptr;
247					if (ptr[0] == '0' &&
248					    ptr[1] == 'x') {
249						argv[i].num.number = strtoq(ptr, &ep, 16);
250					} else {
251						argv[i].num.number = strtoq(ptr, &ep, 10);
252					}
253					if (np == ep) {
254						fputs("Wrong value for number.\n",
255						    stderr);
256						goto retry;
257					}
258					break;
259				case 's':
260					argv[i].type = aml_t_string;
261					argv[i].str.needfree = 0;
262					argv[i].str.string = (u_int8_t *)ptr;
263					/* NULL ternimate */
264					while (ptr[0] != '\n') {
265						ptr++;
266					}
267					ptr[0] = '\0';
268					break;
269				default:
270					fputs("Invalid data type "
271					      "(supports number or string only)\n",
272					    stderr);
273					goto retry;
274				}
275			}
276			bzero(lastcommand, sizeof lastcommand);
277			fprintf(stderr, "==== Running %s. ====\n", method);
278			aml_local_stack_push(aml_local_stack_create());
279			retval = aml_invoke_method_by_name(method, argnum, argv);
280			aml_showobject(retval);
281			aml_local_stack_delete(aml_local_stack_pop());
282			fprintf(stderr, "==== %s finished. ====\n", method);
283finish_execution:
284			break;
285		case 'f':
286			/* NULL terminate */
287			ptr = &commandline[1];
288			while (ptr[0] != '\n')
289				ptr++;
290			ptr[0] = '\0';
291
292			/* move pointer to object name */
293			ptr = &commandline[1];
294			while (ptr[0] == ' ')
295				ptr++;
296
297			aml_apply_foreach_found_objects(aml_get_rootname(),
298			    ptr, print_named_object);
299			break;
300		case 'h':
301			fputs("s	Single step\n"
302			      "n	Step program\n"
303			      "c	Continue program being debugged\n"
304			      "q	Quit method execution\n"
305			      "t	Show local name space tree and variables\n"
306			      "i	Toggle region input prompt\n"
307			      "o	Toggle region output prompt\n"
308			      "m	Show memory management statistics\n"
309			      "r	Run specified method\n"
310			      "f	Find named objects from namespace.\n"
311			      "h	Show this messsage\n", stderr);
312			break;
313		}
314	}
315}
316