1*2e0bf311Sandvar /* $NetBSD: debug.c,v 1.2 2021/08/17 22:00:33 andvar Exp $ */
253e202c1Schristos
353e202c1Schristos /*-
453e202c1Schristos * Copyright (c) 1999 Takanori Watanabe
553e202c1Schristos * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
653e202c1Schristos * All rights reserved.
753e202c1Schristos *
853e202c1Schristos * Redistribution and use in source and binary forms, with or without
953e202c1Schristos * modification, are permitted provided that the following conditions
1053e202c1Schristos * are met:
1153e202c1Schristos * 1. Redistributions of source code must retain the above copyright
1253e202c1Schristos * notice, this list of conditions and the following disclaimer.
1353e202c1Schristos * 2. Redistributions in binary form must reproduce the above copyright
1453e202c1Schristos * notice, this list of conditions and the following disclaimer in the
1553e202c1Schristos * documentation and/or other materials provided with the distribution.
1653e202c1Schristos *
1753e202c1Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1853e202c1Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953e202c1Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053e202c1Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2153e202c1Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253e202c1Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353e202c1Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453e202c1Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553e202c1Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653e202c1Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753e202c1Schristos * SUCH DAMAGE.
2853e202c1Schristos *
2953e202c1Schristos * Id: debug.c,v 1.19 2000/08/16 18:15:00 iwasaki Exp
3053e202c1Schristos * $FreeBSD: src/usr.sbin/acpi/amldb/debug.c,v 1.3 2000/11/09 06:24:40 iwasaki Exp $
3153e202c1Schristos */
3253e202c1Schristos #include <sys/cdefs.h>
33*2e0bf311Sandvar __RCSID("$NetBSD: debug.c,v 1.2 2021/08/17 22:00:33 andvar Exp $");
3453e202c1Schristos
3553e202c1Schristos #include <sys/param.h>
3653e202c1Schristos
3753e202c1Schristos #include <acpi_common.h>
3853e202c1Schristos #include <aml/aml_name.h>
3953e202c1Schristos #include <aml/aml_amlmem.h>
4053e202c1Schristos #include <aml/aml_status.h>
4153e202c1Schristos #include <aml/aml_env.h>
4253e202c1Schristos #include <aml/aml_obj.h>
4353e202c1Schristos #include <aml/aml_evalobj.h>
4453e202c1Schristos #include <aml/aml_parse.h>
4553e202c1Schristos #include <aml/aml_region.h>
4653e202c1Schristos #include <aml/aml_store.h>
4753e202c1Schristos #include <aml/aml_common.h>
4853e202c1Schristos
4953e202c1Schristos #include <assert.h>
5053e202c1Schristos #include <err.h>
5153e202c1Schristos #include <stdio.h>
5253e202c1Schristos #include <stdlib.h>
5353e202c1Schristos #include <string.h>
5453e202c1Schristos #include <unistd.h>
5553e202c1Schristos
5653e202c1Schristos #include "debug.h"
5753e202c1Schristos
5853e202c1Schristos static int
print_named_object(struct aml_name * name,va_list ap)5953e202c1Schristos print_named_object(struct aml_name *name, va_list ap)
6053e202c1Schristos {
6153e202c1Schristos
6253e202c1Schristos aml_print_curname(name);
6353e202c1Schristos printf("\n");
6453e202c1Schristos
6553e202c1Schristos return (0); /* always return success to continue the search */
6653e202c1Schristos }
6753e202c1Schristos
6853e202c1Schristos void
aml_dbgr(struct aml_environ * env1,struct aml_environ * env2)6953e202c1Schristos aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
7053e202c1Schristos {
7153e202c1Schristos #define CMDBUFLEN 512
7253e202c1Schristos #define ARGBUFLEN 512
7353e202c1Schristos static char lastcommand[CMDBUFLEN];
7453e202c1Schristos char commandline[CMDBUFLEN];
7553e202c1Schristos char argbuf[7][ARGBUFLEN];
7653e202c1Schristos char *ptr, *method;
7753e202c1Schristos char *np, *ep;
7853e202c1Schristos int i;
7953e202c1Schristos int argnum;
8053e202c1Schristos struct aml_name *name;
8153e202c1Schristos union aml_object argv[7], *retval;
8253e202c1Schristos
8353e202c1Schristos while (1) {
8453e202c1Schristos fputs("AML>", stderr);
8553e202c1Schristos fgets(commandline, 512, stdin);
8653e202c1Schristos commandline[512 - 1] = '\n'; /* safety */
8753e202c1Schristos if (feof(stdin)) {
8853e202c1Schristos commandline[0] = 'q';
8953e202c1Schristos }
9053e202c1Schristos if (commandline[0] == '\n') {
9153e202c1Schristos memcpy(commandline, lastcommand, sizeof commandline);
9253e202c1Schristos }
9353e202c1Schristos memcpy(lastcommand, commandline, sizeof commandline);
9453e202c1Schristos switch (commandline[0]) {
9553e202c1Schristos case 's':
9653e202c1Schristos if (env2 != NULL) {
9753e202c1Schristos env2->stat = aml_stat_step;
9853e202c1Schristos }
9953e202c1Schristos /* FALLTHROUGH */
10053e202c1Schristos case 'n':
10153e202c1Schristos env1->stat = aml_stat_step;
10253e202c1Schristos return;
10353e202c1Schristos case 'c':
10453e202c1Schristos env1->stat = aml_stat_none;
10553e202c1Schristos return;
10653e202c1Schristos case 'q':
10753e202c1Schristos env1->stat = aml_stat_panic;
10853e202c1Schristos return;
10953e202c1Schristos case 't':
11053e202c1Schristos /* NULL terminate */
11153e202c1Schristos ptr = &commandline[1];
11253e202c1Schristos while (ptr[0] != '\n')
11353e202c1Schristos ptr++;
11453e202c1Schristos ptr[0] = '\0';
11553e202c1Schristos
11653e202c1Schristos /* move pointer to object name */
11753e202c1Schristos ptr = &commandline[1];
11853e202c1Schristos while (ptr[0] == ' ')
11953e202c1Schristos ptr++;
12053e202c1Schristos
12153e202c1Schristos /* show current tree if no argument */
12253e202c1Schristos if (ptr[0] == '\0') {
12353e202c1Schristos aml_showtree(env1->curname, 0);
12453e202c1Schristos goto show_variables;
12553e202c1Schristos }
12653e202c1Schristos /* start from root? */
12753e202c1Schristos if (ptr[0] == '\\') {
12853e202c1Schristos if (ptr[1] == '\0') {
12953e202c1Schristos aml_showtree(aml_get_rootname(), 0);
13053e202c1Schristos goto show_variables;
13153e202c1Schristos }
13253e202c1Schristos if ((name = aml_find_from_namespace(aml_get_rootname(), ptr))) {
13353e202c1Schristos aml_showtree(name, 0);
13453e202c1Schristos goto show_variables;
13553e202c1Schristos }
13653e202c1Schristos }
13753e202c1Schristos if ((name = aml_find_from_namespace(env1->curname, ptr))) {
13853e202c1Schristos aml_showtree(name, 0);
13953e202c1Schristos }
14053e202c1Schristos show_variables:
14153e202c1Schristos for (i = 0; i < 7; i++) {
14253e202c1Schristos struct aml_name *tmp =
14353e202c1Schristos aml_local_stack_getArgX(NULL, i);
14453e202c1Schristos
14553e202c1Schristos if (tmp == NULL || tmp->property == NULL) {
14653e202c1Schristos break;
14753e202c1Schristos }
14853e202c1Schristos printf(" Arg%d ", i);
14953e202c1Schristos aml_showobject(tmp->property);
15053e202c1Schristos }
15153e202c1Schristos for (i = 0; i < 8; i++) {
15253e202c1Schristos struct aml_name *tmp =
15353e202c1Schristos aml_local_stack_getLocalX(i);
15453e202c1Schristos
15553e202c1Schristos if (tmp == NULL || tmp->property == NULL) {
15653e202c1Schristos continue;
15753e202c1Schristos }
15853e202c1Schristos printf(" Local%d ", i);
15953e202c1Schristos aml_showobject(tmp->property);
16053e202c1Schristos }
16153e202c1Schristos break;
16253e202c1Schristos case 'i':
16353e202c1Schristos aml_debug_prompt_reginput =
16453e202c1Schristos (aml_debug_prompt_reginput == 0) ? 1 : 0;
16553e202c1Schristos if (aml_debug_prompt_reginput)
16653e202c1Schristos fputs("REGION INPUT ON\n", stderr);
16753e202c1Schristos else
16853e202c1Schristos fputs("REGION INPUT OFF\n", stderr);
16953e202c1Schristos break;
17053e202c1Schristos case 'o':
17153e202c1Schristos aml_debug_prompt_regoutput =
17253e202c1Schristos (aml_debug_prompt_regoutput == 0) ? 1 : 0;
17353e202c1Schristos if (aml_debug_prompt_regoutput)
17453e202c1Schristos fputs("REGION OUTPUT ON\n", stderr);
17553e202c1Schristos else
17653e202c1Schristos fputs("REGION OUTPUT OFF\n", stderr);
17753e202c1Schristos break;
17853e202c1Schristos case 'm':
17953e202c1Schristos memman_statistics(aml_memman);
18053e202c1Schristos break;
18153e202c1Schristos case 'r':
18253e202c1Schristos /* NULL terminate */
18353e202c1Schristos ptr = &commandline[1];
18453e202c1Schristos while (ptr[0] != '\n')
18553e202c1Schristos ptr++;
18653e202c1Schristos ptr[0] = '\0';
18753e202c1Schristos
18853e202c1Schristos /* move pointer to method name */
18953e202c1Schristos ptr = &commandline[1];
19053e202c1Schristos while (ptr[0] == ' ')
19153e202c1Schristos ptr++;
19253e202c1Schristos
19353e202c1Schristos if (ptr[0] == '\0') {
19453e202c1Schristos break;
19553e202c1Schristos }
19653e202c1Schristos name = aml_find_from_namespace(aml_get_rootname(), ptr);
19753e202c1Schristos if (name == NULL) {
19853e202c1Schristos printf("%s:%d:aml_dbgr: not found name %s\n",
19953e202c1Schristos __FILE__, __LINE__, ptr);
20053e202c1Schristos break;
20153e202c1Schristos }
20253e202c1Schristos if (name->property == NULL ||
20353e202c1Schristos name->property->type != aml_t_method) {
20453e202c1Schristos printf("%s:%d:aml_dbgr: not method %s\n",
20553e202c1Schristos __FILE__, __LINE__, ptr);
20653e202c1Schristos break;
20753e202c1Schristos }
20853e202c1Schristos aml_showobject(name->property);
20953e202c1Schristos method = ptr;
21053e202c1Schristos
21153e202c1Schristos argnum = name->property->meth.argnum & 0x07;
21253e202c1Schristos if (argnum) {
21353e202c1Schristos fputs(" Enter argument values "
21453e202c1Schristos "(ex. number 1 / string foo). "
21553e202c1Schristos "'q' to quit.\n", stderr);
21653e202c1Schristos }
21753e202c1Schristos /* get and parse argument values */
21853e202c1Schristos for (i = 0; i < argnum; i++) {
21953e202c1Schristos retry:
22053e202c1Schristos fprintf(stderr, " Arg%d ? ", i);
22153e202c1Schristos if (read(0, argbuf[i], ARGBUFLEN) == 0) {
22253e202c1Schristos fputs("\n", stderr);
22353e202c1Schristos goto retry;
22453e202c1Schristos }
22553e202c1Schristos argbuf[i][ARGBUFLEN - 1] = '\n';
22653e202c1Schristos if (argbuf[i][0] == 'q') {
22753e202c1Schristos goto finish_execution;
22853e202c1Schristos }
22953e202c1Schristos if (argbuf[i][0] == '\n') {
23053e202c1Schristos goto retry;
23153e202c1Schristos }
23253e202c1Schristos /* move pointer to the value */
23353e202c1Schristos ptr = &argbuf[i][0];
23453e202c1Schristos while (ptr[0] != ' ' && ptr[0] != '\n') {
23553e202c1Schristos ptr++;
23653e202c1Schristos }
23753e202c1Schristos while (ptr[0] == ' ') {
23853e202c1Schristos ptr++;
23953e202c1Schristos }
24053e202c1Schristos if (ptr[0] == '\n') {
24153e202c1Schristos goto retry;
24253e202c1Schristos }
24353e202c1Schristos switch (argbuf[i][0]) {
24453e202c1Schristos case 'n':
24553e202c1Schristos argv[i].type = aml_t_num;
24653e202c1Schristos np = ptr;
24753e202c1Schristos if (ptr[0] == '0' &&
24853e202c1Schristos ptr[1] == 'x') {
24953e202c1Schristos argv[i].num.number = strtoq(ptr, &ep, 16);
25053e202c1Schristos } else {
25153e202c1Schristos argv[i].num.number = strtoq(ptr, &ep, 10);
25253e202c1Schristos }
25353e202c1Schristos if (np == ep) {
25453e202c1Schristos fputs("Wrong value for number.\n",
25553e202c1Schristos stderr);
25653e202c1Schristos goto retry;
25753e202c1Schristos }
25853e202c1Schristos break;
25953e202c1Schristos case 's':
26053e202c1Schristos argv[i].type = aml_t_string;
26153e202c1Schristos argv[i].str.needfree = 0;
26253e202c1Schristos argv[i].str.string = (u_int8_t *)ptr;
26353e202c1Schristos /* NULL ternimate */
26453e202c1Schristos while (ptr[0] != '\n') {
26553e202c1Schristos ptr++;
26653e202c1Schristos }
26753e202c1Schristos ptr[0] = '\0';
26853e202c1Schristos break;
26953e202c1Schristos default:
27053e202c1Schristos fputs("Invalid data type "
27153e202c1Schristos "(supports number or string only)\n",
27253e202c1Schristos stderr);
27353e202c1Schristos goto retry;
27453e202c1Schristos }
27553e202c1Schristos }
27653e202c1Schristos bzero(lastcommand, sizeof lastcommand);
27753e202c1Schristos fprintf(stderr, "==== Running %s. ====\n", method);
27853e202c1Schristos aml_local_stack_push(aml_local_stack_create());
27953e202c1Schristos retval = aml_invoke_method_by_name(method, argnum, argv);
28053e202c1Schristos aml_showobject(retval);
28153e202c1Schristos aml_local_stack_delete(aml_local_stack_pop());
28253e202c1Schristos fprintf(stderr, "==== %s finished. ====\n", method);
28353e202c1Schristos finish_execution:
28453e202c1Schristos break;
28553e202c1Schristos case 'f':
28653e202c1Schristos /* NULL terminate */
28753e202c1Schristos ptr = &commandline[1];
28853e202c1Schristos while (ptr[0] != '\n')
28953e202c1Schristos ptr++;
29053e202c1Schristos ptr[0] = '\0';
29153e202c1Schristos
29253e202c1Schristos /* move pointer to object name */
29353e202c1Schristos ptr = &commandline[1];
29453e202c1Schristos while (ptr[0] == ' ')
29553e202c1Schristos ptr++;
29653e202c1Schristos
29753e202c1Schristos aml_apply_foreach_found_objects(aml_get_rootname(),
29853e202c1Schristos ptr, print_named_object);
29953e202c1Schristos break;
30053e202c1Schristos case 'h':
30153e202c1Schristos fputs("s Single step\n"
30253e202c1Schristos "n Step program\n"
30353e202c1Schristos "c Continue program being debugged\n"
30453e202c1Schristos "q Quit method execution\n"
30553e202c1Schristos "t Show local name space tree and variables\n"
30653e202c1Schristos "i Toggle region input prompt\n"
30753e202c1Schristos "o Toggle region output prompt\n"
30853e202c1Schristos "m Show memory management statistics\n"
30953e202c1Schristos "r Run specified method\n"
31053e202c1Schristos "f Find named objects from namespace.\n"
311*2e0bf311Sandvar "h Show this message\n", stderr);
31253e202c1Schristos break;
31353e202c1Schristos }
31453e202c1Schristos }
31553e202c1Schristos }
316