import amldb(8) from ACPI For FreeBSD project.
Obtained from: ACPI For FreeBSD project
This commit is contained in:
parent
e1e9a4bf77
commit
01be5ae188
13
usr.sbin/acpi/amldb/Makefile
Normal file
13
usr.sbin/acpi/amldb/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# $Id: Makefile,v 1.5 2000/07/14 18:16:30 iwasaki Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= amldb
|
||||
SRCS= amldb.c debug.c region.c
|
||||
SRCS+= aml_parse.c aml_name.c aml_amlmem.c aml_memman.c aml_store.c aml_obj.c aml_evalobj.c aml_common.c
|
||||
NOMAN= yes
|
||||
#MAN8= amldb.8
|
||||
#DEBUG_FLAGS= -g
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys -I${.CURDIR}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
.PATH: ${.CURDIR}/../../../sys/dev/acpi/aml
|
188
usr.sbin/acpi/amldb/amldb.c
Normal file
188
usr.sbin/acpi/amldb/amldb.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: amldb.c,v 1.8 2000/08/08 14:12:24 iwasaki Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <dev/acpi/aml/aml_amlmem.h>
|
||||
#include <dev/acpi/aml/aml_common.h>
|
||||
#include <dev/acpi/aml/aml_env.h>
|
||||
#include <dev/acpi/aml/aml_parse.h>
|
||||
#include <dev/acpi/aml/aml_region.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
int regdump_enabled = 0;
|
||||
int memstat_enabled = 0;
|
||||
int showtree_enabled = 0;
|
||||
|
||||
static void aml_init_namespace();
|
||||
|
||||
void
|
||||
aml_init_namespace()
|
||||
{
|
||||
struct aml_environ env;
|
||||
struct aml_name *newname;
|
||||
|
||||
aml_new_name_group(AML_NAME_GROUP_OS_DEFINED);
|
||||
env.curname = aml_get_rootname();
|
||||
newname = aml_create_name(&env, "\\_OS_");
|
||||
newname->property = aml_alloc_object(aml_t_string, NULL);
|
||||
newname->property->str.needfree = 0;
|
||||
newname->property->str.string = "Microsoft Windows NT";
|
||||
}
|
||||
|
||||
static int
|
||||
load_dsdt(const char *dsdtfile)
|
||||
{
|
||||
struct aml_environ env;
|
||||
u_int8_t *code;
|
||||
struct stat sb;
|
||||
int fd;
|
||||
|
||||
printf("Loading %s...", dsdtfile);
|
||||
|
||||
fd = open(dsdtfile, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
perror("open");
|
||||
exit(-1);
|
||||
}
|
||||
if (fstat(fd, &sb) == -1) {
|
||||
perror("fstat");
|
||||
exit(-1);
|
||||
}
|
||||
if ((code = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == NULL) {
|
||||
perror("mmap");
|
||||
exit(-1);
|
||||
}
|
||||
aml_init_namespace();
|
||||
|
||||
aml_new_name_group((int)code);
|
||||
bzero(&env, sizeof(env));
|
||||
|
||||
/*
|
||||
* Microsoft asl.exe generates 0x23 byte additional info.
|
||||
* at the begining of the file, so just ignore it.
|
||||
*/
|
||||
if (strncmp(code, "DSDT", 4) == 0) {
|
||||
env.dp = code + 0x23;
|
||||
} else {
|
||||
env.dp = code;
|
||||
}
|
||||
env.end = code + sb.st_size;
|
||||
env.curname = aml_get_rootname();
|
||||
|
||||
aml_local_stack_push(aml_local_stack_create());
|
||||
aml_parse_objectlist(&env, 0);
|
||||
aml_local_stack_delete(aml_local_stack_pop());
|
||||
|
||||
assert(env.dp == env.end);
|
||||
env.dp = code;
|
||||
env.end = code + sb.st_size;
|
||||
|
||||
printf("done\n");
|
||||
|
||||
aml_debug = 1; /* debug print enabled */
|
||||
|
||||
if (showtree_enabled == 1) {
|
||||
aml_showtree(env.curname, 0);
|
||||
}
|
||||
do {
|
||||
aml_dbgr(&env, &env);
|
||||
} while (env.stat != aml_stat_panic);
|
||||
|
||||
aml_debug = 0; /* debug print disabled */
|
||||
|
||||
if (regdump_enabled == 1) {
|
||||
aml_simulation_regdump("region.dmp");
|
||||
}
|
||||
while (name_group_list->id != AML_NAME_GROUP_ROOT) {
|
||||
aml_delete_name_group(name_group_list);
|
||||
}
|
||||
|
||||
if (memstat_enabled == 1) {
|
||||
memman_statistics(aml_memman);
|
||||
}
|
||||
memman_freeall(aml_memman);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(const char *progname)
|
||||
{
|
||||
|
||||
printf("usage: %s [-d] [-s] [-t] [-h] dsdt_files...\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char c, *progname;
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
while ((c = getopt(argc, argv, "dsth")) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
regdump_enabled = 1;
|
||||
break;
|
||||
case 's':
|
||||
memstat_enabled = 1;
|
||||
break;
|
||||
case 't':
|
||||
showtree_enabled = 1;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage(progname);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0) {
|
||||
usage(progname);
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
load_dsdt(argv[i]);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
311
usr.sbin/acpi/amldb/debug.c
Normal file
311
usr.sbin/acpi/amldb/debug.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 Takanori Watanabe
|
||||
* Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: debug.c,v 1.19 2000/08/16 18:15:00 iwasaki Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/acpi.h>
|
||||
|
||||
#include <dev/acpi/aml/aml_name.h>
|
||||
#include <dev/acpi/aml/aml_amlmem.h>
|
||||
#include <dev/acpi/aml/aml_status.h>
|
||||
#include <dev/acpi/aml/aml_env.h>
|
||||
#include <dev/acpi/aml/aml_obj.h>
|
||||
#include <dev/acpi/aml/aml_evalobj.h>
|
||||
#include <dev/acpi/aml/aml_parse.h>
|
||||
#include <dev/acpi/aml/aml_region.h>
|
||||
#include <dev/acpi/aml/aml_store.h>
|
||||
#include <dev/acpi/aml/aml_common.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static int
|
||||
print_named_object(struct aml_name *name, va_list ap)
|
||||
{
|
||||
|
||||
aml_print_curname(name);
|
||||
printf("\n");
|
||||
|
||||
return (0); /* always return success to continue the search */
|
||||
}
|
||||
|
||||
void
|
||||
aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
|
||||
{
|
||||
#define CMDBUFLEN 512
|
||||
#define ARGBUFLEN 512
|
||||
static char lastcommand[CMDBUFLEN];
|
||||
char commandline[CMDBUFLEN];
|
||||
char argbuf[7][ARGBUFLEN];
|
||||
char *ptr, *method;
|
||||
char *np, *ep;
|
||||
int i;
|
||||
int argnum;
|
||||
struct aml_name *name;
|
||||
union aml_object argv[7], *retval;
|
||||
|
||||
while (1) {
|
||||
fputs("AML>", stderr);
|
||||
fgets(commandline, 512, stdin);
|
||||
commandline[512 - 1] = '\n'; /* safety */
|
||||
if (feof(stdin)) {
|
||||
commandline[0] = 'q';
|
||||
}
|
||||
if (commandline[0] == '\n') {
|
||||
memcpy(commandline, lastcommand, sizeof commandline);
|
||||
}
|
||||
memcpy(lastcommand, commandline, sizeof commandline);
|
||||
switch (commandline[0]) {
|
||||
case 's':
|
||||
if (env2 != NULL) {
|
||||
env2->stat = aml_stat_step;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 'n':
|
||||
env1->stat = aml_stat_step;
|
||||
return;
|
||||
case 'c':
|
||||
env1->stat = aml_stat_none;
|
||||
return;
|
||||
case 'q':
|
||||
env1->stat = aml_stat_panic;
|
||||
return;
|
||||
case 't':
|
||||
/* NULL terminate */
|
||||
ptr = &commandline[1];
|
||||
while (ptr[0] != '\n')
|
||||
ptr++;
|
||||
ptr[0] = '\0';
|
||||
|
||||
/* move pointer to object name */
|
||||
ptr = &commandline[1];
|
||||
while (ptr[0] == ' ')
|
||||
ptr++;
|
||||
|
||||
/* show current tree if no argument */
|
||||
if (ptr[0] == '\0') {
|
||||
aml_showtree(env1->curname, 0);
|
||||
goto show_variables;
|
||||
}
|
||||
/* start from root? */
|
||||
if (ptr[0] == '\\') {
|
||||
if (ptr[1] == '\0') {
|
||||
aml_showtree(aml_get_rootname(), 0);
|
||||
goto show_variables;
|
||||
}
|
||||
if ((name = aml_find_from_namespace(aml_get_rootname(), ptr))) {
|
||||
aml_showtree(name, 0);
|
||||
goto show_variables;
|
||||
}
|
||||
}
|
||||
if ((name = aml_find_from_namespace(env1->curname, ptr))) {
|
||||
aml_showtree(name, 0);
|
||||
}
|
||||
show_variables:
|
||||
for (i = 0; i < 7; i++) {
|
||||
struct aml_name *tmp =
|
||||
aml_local_stack_getArgX(NULL, i);
|
||||
|
||||
if (tmp == NULL || tmp->property == NULL) {
|
||||
break;
|
||||
}
|
||||
printf(" Arg%d ", i);
|
||||
aml_showobject(tmp->property);
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
struct aml_name *tmp =
|
||||
aml_local_stack_getLocalX(i);
|
||||
|
||||
if (tmp == NULL || tmp->property == NULL) {
|
||||
continue;
|
||||
}
|
||||
printf(" Local%d ", i);
|
||||
aml_showobject(tmp->property);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
aml_debug_prompt_reginput =
|
||||
(aml_debug_prompt_reginput == 0) ? 1 : 0;
|
||||
if (aml_debug_prompt_reginput)
|
||||
fputs("REGION INPUT ON\n", stderr);
|
||||
else
|
||||
fputs("REGION INPUT OFF\n", stderr);
|
||||
break;
|
||||
case 'o':
|
||||
aml_debug_prompt_regoutput =
|
||||
(aml_debug_prompt_regoutput == 0) ? 1 : 0;
|
||||
if (aml_debug_prompt_regoutput)
|
||||
fputs("REGION OUTPUT ON\n", stderr);
|
||||
else
|
||||
fputs("REGION OUTPUT OFF\n", stderr);
|
||||
break;
|
||||
case 'm':
|
||||
memman_statistics(aml_memman);
|
||||
break;
|
||||
case 'r':
|
||||
/* NULL terminate */
|
||||
ptr = &commandline[1];
|
||||
while (ptr[0] != '\n')
|
||||
ptr++;
|
||||
ptr[0] = '\0';
|
||||
|
||||
/* move pointer to method name */
|
||||
ptr = &commandline[1];
|
||||
while (ptr[0] == ' ')
|
||||
ptr++;
|
||||
|
||||
if (ptr[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
name = aml_find_from_namespace(aml_get_rootname(), ptr);
|
||||
if (name == NULL) {
|
||||
printf("%s:%d:aml_dbgr: not found name %s\n",
|
||||
__FILE__, __LINE__, ptr);
|
||||
break;
|
||||
}
|
||||
if (name->property == NULL ||
|
||||
name->property->type != aml_t_method) {
|
||||
printf("%s:%d:aml_dbgr: not method %s\n",
|
||||
__FILE__, __LINE__, ptr);
|
||||
break;
|
||||
}
|
||||
aml_showobject(name->property);
|
||||
method = ptr;
|
||||
|
||||
argnum = name->property->meth.argnum & 0x07;
|
||||
if (argnum) {
|
||||
fputs(" Enter argument values "
|
||||
"(ex. number 1 / string foo). "
|
||||
"'q' to quit.\n", stderr);
|
||||
}
|
||||
/* get and parse argument values */
|
||||
for (i = 0; i < argnum; i++) {
|
||||
retry:
|
||||
fprintf(stderr, " Arg%d ? ", i);
|
||||
if (read(0, argbuf[i], ARGBUFLEN) == 0) {
|
||||
fputs("\n", stderr);
|
||||
goto retry;
|
||||
}
|
||||
argbuf[i][ARGBUFLEN - 1] = '\n';
|
||||
if (argbuf[i][0] == 'q') {
|
||||
goto finish_execution;
|
||||
}
|
||||
if (argbuf[i][0] == '\n') {
|
||||
goto retry;
|
||||
}
|
||||
/* move pointer to the value */
|
||||
ptr = &argbuf[i][0];
|
||||
while (ptr[0] != ' ' && ptr[0] != '\n') {
|
||||
ptr++;
|
||||
}
|
||||
while (ptr[0] == ' ') {
|
||||
ptr++;
|
||||
}
|
||||
if (ptr[0] == '\n') {
|
||||
goto retry;
|
||||
}
|
||||
switch (argbuf[i][0]) {
|
||||
case 'n':
|
||||
argv[i].type = aml_t_num;
|
||||
np = ptr;
|
||||
if (ptr[0] == '0' &&
|
||||
ptr[1] == 'x') {
|
||||
argv[i].num.number = strtoq(ptr, &ep, 16);
|
||||
} else {
|
||||
argv[i].num.number = strtoq(ptr, &ep, 10);
|
||||
}
|
||||
if (np == ep) {
|
||||
fputs("Wrong value for number.\n",
|
||||
stderr);
|
||||
goto retry;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
argv[i].type = aml_t_string;
|
||||
argv[i].str.needfree = 0;
|
||||
argv[i].str.string = ptr;
|
||||
/* NULL ternimate */
|
||||
while (ptr[0] != '\n') {
|
||||
ptr++;
|
||||
}
|
||||
ptr[0] = '\0';
|
||||
break;
|
||||
default:
|
||||
fputs("Invalid data type "
|
||||
"(supports number or string only)\n",
|
||||
stderr);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
bzero(lastcommand, sizeof lastcommand);
|
||||
fprintf(stderr, "==== Running %s. ====\n", method);
|
||||
aml_local_stack_push(aml_local_stack_create());
|
||||
retval = aml_invoke_method_by_name(method, argnum, argv);
|
||||
aml_showobject(retval);
|
||||
aml_local_stack_delete(aml_local_stack_pop());
|
||||
fprintf(stderr, "==== %s finished. ====\n", method);
|
||||
finish_execution:
|
||||
break;
|
||||
case 'f':
|
||||
/* NULL terminate */
|
||||
ptr = &commandline[1];
|
||||
while (ptr[0] != '\n')
|
||||
ptr++;
|
||||
ptr[0] = '\0';
|
||||
|
||||
/* move pointer to object name */
|
||||
ptr = &commandline[1];
|
||||
while (ptr[0] == ' ')
|
||||
ptr++;
|
||||
|
||||
aml_apply_foreach_found_objects(aml_get_rootname(),
|
||||
ptr, print_named_object);
|
||||
break;
|
||||
case 'h':
|
||||
fputs("s Single step\n"
|
||||
"n Step program\n"
|
||||
"c Continue program being debugged\n"
|
||||
"q Quit method execution\n"
|
||||
"t Show local name space tree and variables\n"
|
||||
"i Toggle region input prompt\n"
|
||||
"o Toggle region output prompt\n"
|
||||
"m Show memory management statistics\n"
|
||||
"r Run specified method\n"
|
||||
"f Find named objects from namespace.\n"
|
||||
"h Show this messsage\n", stderr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
36
usr.sbin/acpi/amldb/debug.h
Normal file
36
usr.sbin/acpi/amldb/debug.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 Takanori Watanabe
|
||||
* Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: debug.h,v 1.8 2000/08/09 14:47:57 iwasaki Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
void aml_dbgr(struct aml_environ *, struct aml_environ *);
|
||||
|
||||
#endif /* !_DEBUG_H_ */
|
538
usr.sbin/acpi/amldb/region.c
Normal file
538
usr.sbin/acpi/amldb/region.c
Normal file
@ -0,0 +1,538 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: region.c,v 1.14 2000/08/08 14:12:25 iwasaki Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Region I/O subroutine
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <dev/acpi/aml/aml_amlmem.h>
|
||||
#include <dev/acpi/aml/aml_name.h>
|
||||
#include <dev/acpi/aml/aml_common.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
int aml_debug_prompt_regoutput = 0;
|
||||
int aml_debug_prompt_reginput = 1;
|
||||
|
||||
static void aml_simulation_regload(const char *dumpfile);
|
||||
|
||||
struct ACPIRegionContent {
|
||||
TAILQ_ENTRY(ACPIRegionContent) links;
|
||||
int regtype;
|
||||
u_int32_t addr;
|
||||
u_int8_t value;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(ACPIRegionContentList, ACPIRegionContent);
|
||||
struct ACPIRegionContentList RegionContentList;
|
||||
|
||||
static int aml_simulation_initialized = 0;
|
||||
|
||||
static void
|
||||
aml_simulation_init()
|
||||
{
|
||||
|
||||
aml_simulation_initialized = 1;
|
||||
TAILQ_INIT(&RegionContentList);
|
||||
aml_simulation_regload("region.ini");
|
||||
}
|
||||
|
||||
static int
|
||||
aml_simulate_regcontent_add(int regtype, u_int32_t addr, u_int8_t value)
|
||||
{
|
||||
struct ACPIRegionContent *rc;
|
||||
|
||||
rc = malloc(sizeof(struct ACPIRegionContent));
|
||||
if (rc == NULL) {
|
||||
return (-1); /* malloc fail */
|
||||
}
|
||||
rc->regtype = regtype;
|
||||
rc->addr = addr;
|
||||
rc->value = value;
|
||||
|
||||
TAILQ_INSERT_TAIL(&RegionContentList, rc, links);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aml_simulate_regcontent_read(int regtype, u_int32_t addr, u_int8_t *valuep)
|
||||
{
|
||||
struct ACPIRegionContent *rc;
|
||||
|
||||
if (!aml_simulation_initialized) {
|
||||
aml_simulation_init();
|
||||
}
|
||||
TAILQ_FOREACH(rc, &RegionContentList, links) {
|
||||
if (rc->regtype == regtype && rc->addr == addr) {
|
||||
*valuep = rc->value;
|
||||
return (1); /* found */
|
||||
}
|
||||
}
|
||||
|
||||
return (aml_simulate_regcontent_add(regtype, addr, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
aml_simulate_regcontent_write(int regtype, u_int32_t addr, u_int8_t *valuep)
|
||||
{
|
||||
struct ACPIRegionContent *rc;
|
||||
|
||||
if (!aml_simulation_initialized) {
|
||||
aml_simulation_init();
|
||||
}
|
||||
TAILQ_FOREACH(rc, &RegionContentList, links) {
|
||||
if (rc->regtype == regtype && rc->addr == addr) {
|
||||
rc->value = *valuep;
|
||||
return (1); /* exists */
|
||||
}
|
||||
}
|
||||
|
||||
return (aml_simulate_regcontent_add(regtype, addr, *valuep));
|
||||
}
|
||||
|
||||
static u_int32_t
|
||||
aml_simulate_prompt(char *msg, u_int32_t def_val)
|
||||
{
|
||||
char buf[16], *ep;
|
||||
u_int32_t val;
|
||||
|
||||
val = def_val;
|
||||
printf("DEBUG");
|
||||
if (msg != NULL) {
|
||||
printf("%s", msg);
|
||||
}
|
||||
printf("(default: 0x%x / %u) >>", val, val);
|
||||
fflush(stdout);
|
||||
|
||||
bzero(buf, sizeof buf);
|
||||
while (1) {
|
||||
if (read(0, buf, sizeof buf) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (buf[0] == '\n') {
|
||||
break; /* use default value */
|
||||
}
|
||||
if (buf[0] == '0' && buf[1] == 'x') {
|
||||
val = strtoq(buf, &ep, 16);
|
||||
} else {
|
||||
val = strtoq(buf, &ep, 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (val);
|
||||
}
|
||||
|
||||
static void
|
||||
aml_simulation_regload(const char *dumpfile)
|
||||
{
|
||||
char buf[256], *np, *ep;
|
||||
struct ACPIRegionContent rc;
|
||||
FILE *fp;
|
||||
|
||||
if (!aml_simulation_initialized) {
|
||||
return;
|
||||
}
|
||||
if ((fp = fopen(dumpfile, "r")) == NULL) {
|
||||
warn(dumpfile);
|
||||
return;
|
||||
}
|
||||
while (fgets(buf, sizeof buf, fp) != NULL) {
|
||||
np = buf;
|
||||
/* reading region type */
|
||||
rc.regtype = strtoq(np, &ep, 10);
|
||||
if (np == ep) {
|
||||
continue;
|
||||
}
|
||||
np = ep;
|
||||
|
||||
/* reading address */
|
||||
rc.addr = strtoq(np, &ep, 16);
|
||||
if (np == ep) {
|
||||
continue;
|
||||
}
|
||||
np = ep;
|
||||
|
||||
/* reading value */
|
||||
rc.value = strtoq(np, &ep, 16);
|
||||
if (np == ep) {
|
||||
continue;
|
||||
}
|
||||
aml_simulate_regcontent_write(rc.regtype, rc.addr, &rc.value);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#define ACPI_REGION_INPUT 0
|
||||
#define ACPI_REGION_OUTPUT 1
|
||||
|
||||
static int
|
||||
aml_simulate_region_io(int io, int regtype, u_int32_t flags, u_int32_t *valuep,
|
||||
u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen, int prompt)
|
||||
{
|
||||
char buf[64];
|
||||
u_int8_t val, tmp, masklow, maskhigh;
|
||||
u_int8_t offsetlow, offsethigh;
|
||||
u_int32_t addr, byteoffset, bytelen;
|
||||
int value, readval;
|
||||
int state, i;
|
||||
|
||||
value = *valuep;
|
||||
val = readval = 0;
|
||||
masklow = maskhigh = 0xff;
|
||||
state = 0;
|
||||
|
||||
byteoffset = bitoffset / 8;
|
||||
bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
|
||||
addr = baseaddr + byteoffset;
|
||||
offsetlow = bitoffset % 8;
|
||||
if (bytelen > 1) {
|
||||
offsethigh = (bitlen - (8 - offsetlow)) % 8;
|
||||
} else {
|
||||
offsethigh = 0;
|
||||
}
|
||||
|
||||
if (offsetlow) {
|
||||
masklow = (~((1 << bitlen) - 1) << offsetlow) | \
|
||||
~(0xff << offsetlow);
|
||||
printf("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n",
|
||||
offsetlow, masklow, ~masklow & 0xff);
|
||||
}
|
||||
if (offsethigh) {
|
||||
maskhigh = 0xff << offsethigh;
|
||||
printf("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n",
|
||||
offsethigh, maskhigh, ~maskhigh & 0xff);
|
||||
}
|
||||
for (i = bytelen; i > 0; i--, addr++) {
|
||||
val = 0;
|
||||
state = aml_simulate_regcontent_read(regtype, addr, &val);
|
||||
if (state == -1) {
|
||||
goto finish;
|
||||
}
|
||||
printf("\t[%d:0x%02x@0x%x]", regtype, val, addr);
|
||||
|
||||
switch (io) {
|
||||
case ACPI_REGION_INPUT:
|
||||
tmp = val;
|
||||
/* the lowest byte? */
|
||||
if (i == bytelen) {
|
||||
if (offsetlow) {
|
||||
readval = tmp & ~masklow;
|
||||
} else {
|
||||
readval = tmp;
|
||||
}
|
||||
} else {
|
||||
if (i == 1 && offsethigh) {
|
||||
tmp = tmp & ~maskhigh;
|
||||
}
|
||||
readval = (tmp << (8 * (bytelen - i))) | readval;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
/* goto to next byte... */
|
||||
if (i > 1) {
|
||||
continue;
|
||||
}
|
||||
/* final adjustment before finishing region access */
|
||||
if (offsetlow) {
|
||||
readval = readval >> offsetlow;
|
||||
}
|
||||
sprintf(buf, "[read(%d, 0x%x)&mask:0x%x]",
|
||||
regtype, addr, readval);
|
||||
if (prompt) {
|
||||
value = aml_simulate_prompt(buf, readval);
|
||||
if (readval != value) {
|
||||
state = aml_simulate_region_io(ACPI_REGION_OUTPUT,
|
||||
regtype, flags, &value, baseaddr,
|
||||
bitoffset, bitlen, 0);
|
||||
if (state == -1) {
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("\t%s\n", buf);
|
||||
value = readval;
|
||||
}
|
||||
*valuep = value;
|
||||
|
||||
break;
|
||||
case ACPI_REGION_OUTPUT:
|
||||
tmp = value & 0xff;
|
||||
/* the lowest byte? */
|
||||
if (i == bytelen) {
|
||||
if (offsetlow) {
|
||||
tmp = (val & masklow) | tmp << offsetlow;
|
||||
}
|
||||
value = value >> (8 - offsetlow);
|
||||
} else {
|
||||
if (i == 1 && offsethigh) {
|
||||
tmp = (val & maskhigh) | tmp;
|
||||
}
|
||||
value = value >> 8;
|
||||
}
|
||||
|
||||
if (prompt) {
|
||||
printf("\n");
|
||||
sprintf(buf, "[write(%d, 0x%02x, 0x%x)]",
|
||||
regtype, tmp, addr);
|
||||
val = aml_simulate_prompt(buf, tmp);
|
||||
} else {
|
||||
printf("->[%d:0x%02x@0x%x]\n",
|
||||
regtype, tmp, addr);
|
||||
val = tmp;
|
||||
}
|
||||
state = aml_simulate_regcontent_write(regtype,
|
||||
addr, &val);
|
||||
if (state == -1) {
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finish:
|
||||
return (state);
|
||||
}
|
||||
|
||||
static int
|
||||
aml_simulate_region_io_buffer(int io, int regtype, u_int32_t flags,
|
||||
u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen)
|
||||
{
|
||||
u_int8_t val;
|
||||
u_int8_t offsetlow, offsethigh;
|
||||
u_int32_t addr, byteoffset, bytelen;
|
||||
int state, i;
|
||||
|
||||
val = 0;
|
||||
offsetlow = offsethigh = 0;
|
||||
state = 0;
|
||||
|
||||
byteoffset = bitoffset / 8;
|
||||
bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
|
||||
addr = baseaddr + byteoffset;
|
||||
offsetlow = bitoffset % 8;
|
||||
assert(offsetlow == 0);
|
||||
|
||||
if (bytelen > 1) {
|
||||
offsethigh = (bitlen - (8 - offsetlow)) % 8;
|
||||
}
|
||||
assert(offsethigh == 0);
|
||||
|
||||
for (i = bytelen; i > 0; i--, addr++) {
|
||||
switch (io) {
|
||||
case ACPI_REGION_INPUT:
|
||||
val = 0;
|
||||
state = aml_simulate_regcontent_read(regtype, addr, &val);
|
||||
if (state == -1) {
|
||||
goto finish;
|
||||
}
|
||||
buffer[bytelen - i] = val;
|
||||
break;
|
||||
case ACPI_REGION_OUTPUT:
|
||||
val = buffer[bytelen - i];
|
||||
state = aml_simulate_regcontent_write(regtype,
|
||||
addr, &val);
|
||||
if (state == -1) {
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
finish:
|
||||
return (state);
|
||||
}
|
||||
|
||||
static u_int32_t
|
||||
aml_simulate_region_read(int regtype, u_int32_t flags, u_int32_t addr,
|
||||
u_int32_t bitoffset, u_int32_t bitlen)
|
||||
{
|
||||
int value;
|
||||
int state;
|
||||
|
||||
AML_DEBUGPRINT("\n[aml_region_read(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
|
||||
regtype, flags, addr, bitoffset, bitlen);
|
||||
state = aml_simulate_region_io(ACPI_REGION_INPUT, regtype, flags, &value,
|
||||
addr, bitoffset, bitlen, aml_debug_prompt_reginput);
|
||||
assert(state != -1);
|
||||
return (value);
|
||||
}
|
||||
|
||||
int
|
||||
aml_simulate_region_read_into_buffer(int regtype, u_int32_t flags,
|
||||
u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen, u_int8_t *buffer)
|
||||
{
|
||||
int state;
|
||||
|
||||
AML_DEBUGPRINT("\n[aml_region_read_into_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
|
||||
regtype, flags, addr, bitoffset, bitlen);
|
||||
state = aml_simulate_region_io_buffer(ACPI_REGION_INPUT, regtype, flags,
|
||||
buffer, addr, bitoffset, bitlen);
|
||||
assert(state != -1);
|
||||
return (state);
|
||||
}
|
||||
|
||||
int
|
||||
aml_simulate_region_write(int regtype, u_int32_t flags, u_int32_t value,
|
||||
u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
|
||||
{
|
||||
int state;
|
||||
|
||||
AML_DEBUGPRINT("\n[aml_region_write(%d, %d, 0x%x, 0x%x, 0x%x, 0x%x)]\n",
|
||||
regtype, flags, value, addr, bitoffset, bitlen);
|
||||
state = aml_simulate_region_io(ACPI_REGION_OUTPUT, regtype, flags,
|
||||
&value, addr, bitoffset, bitlen, aml_debug_prompt_regoutput);
|
||||
assert(state != -1);
|
||||
return (state);
|
||||
}
|
||||
|
||||
int
|
||||
aml_simulate_region_write_from_buffer(int regtype, u_int32_t flags,
|
||||
u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
|
||||
{
|
||||
int state;
|
||||
|
||||
AML_DEBUGPRINT("\n[aml_region_write_from_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",
|
||||
regtype, flags, addr, bitoffset, bitlen);
|
||||
state = aml_simulate_region_io_buffer(ACPI_REGION_OUTPUT, regtype,
|
||||
flags, buffer, addr, bitoffset, bitlen);
|
||||
assert(state != -1);
|
||||
return (state);
|
||||
}
|
||||
|
||||
int
|
||||
aml_simulate_region_bcopy(int regtype, u_int32_t flags, u_int32_t addr,
|
||||
u_int32_t bitoffset, u_int32_t bitlen,
|
||||
u_int32_t dflags, u_int32_t daddr,
|
||||
u_int32_t dbitoffset, u_int32_t dbitlen)
|
||||
{
|
||||
u_int32_t len, i;
|
||||
u_int32_t value;
|
||||
int state;
|
||||
|
||||
AML_DEBUGPRINT("\n[aml_region_bcopy(%d, %d, 0x%x, 0x%x, 0x%x, %d, 0x%x, 0x%x, 0x%x)]\n",
|
||||
regtype, flags, addr, bitoffset, bitlen,
|
||||
dflags, daddr, dbitoffset, dbitlen);
|
||||
|
||||
len = (bitlen > dbitlen) ? dbitlen : bitlen;
|
||||
len = len / 8 + ((len % 8) ? 1 : 0);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
state = aml_simulate_region_io(ACPI_REGION_INPUT, regtype,
|
||||
flags, &value, addr, bitoffset + i * 8, 8, 0);
|
||||
assert(state != -1);
|
||||
state = aml_simulate_region_io(ACPI_REGION_OUTPUT, regtype,
|
||||
dflags, &value, daddr, dbitoffset + i * 8, 8, 0);
|
||||
assert(state != -1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
|
||||
u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
|
||||
{
|
||||
|
||||
return (aml_simulate_region_read(regtype, flags, addr,
|
||||
bitoffset, bitlen));
|
||||
}
|
||||
|
||||
int
|
||||
aml_region_read_into_buffer(struct aml_environ *env, int regtype,
|
||||
u_int32_t flags, u_int32_t addr, u_int32_t bitoffset,
|
||||
u_int32_t bitlen, u_int8_t *buffer)
|
||||
{
|
||||
|
||||
return (aml_simulate_region_read_into_buffer(regtype, flags, addr,
|
||||
bitoffset, bitlen, buffer));
|
||||
}
|
||||
|
||||
int
|
||||
aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
|
||||
u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
|
||||
{
|
||||
|
||||
return (aml_simulate_region_write(regtype, flags, value, addr,
|
||||
bitoffset, bitlen));
|
||||
}
|
||||
|
||||
int
|
||||
aml_region_write_from_buffer(struct aml_environ *env, int regtype,
|
||||
u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
|
||||
u_int32_t bitlen)
|
||||
{
|
||||
|
||||
return (aml_simulate_region_write_from_buffer(regtype, flags, buffer,
|
||||
addr, bitoffset, bitlen));
|
||||
}
|
||||
|
||||
int
|
||||
aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags,
|
||||
u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
|
||||
u_int32_t dflags, u_int32_t daddr,
|
||||
u_int32_t dbitoffset, u_int32_t dbitlen)
|
||||
{
|
||||
|
||||
return (aml_simulate_region_bcopy(regtype, flags, addr, bitoffset,
|
||||
bitlen, dflags, daddr, dbitoffset, dbitlen));
|
||||
}
|
||||
|
||||
void
|
||||
aml_simulation_regdump(const char *dumpfile)
|
||||
{
|
||||
struct ACPIRegionContent *rc;
|
||||
FILE *fp;
|
||||
|
||||
if (!aml_simulation_initialized) {
|
||||
return;
|
||||
}
|
||||
if ((fp = fopen(dumpfile, "w")) == NULL) {
|
||||
warn(dumpfile);
|
||||
return;
|
||||
}
|
||||
while (!TAILQ_EMPTY(&RegionContentList)) {
|
||||
rc = TAILQ_FIRST(&RegionContentList);
|
||||
fprintf(fp, "%d 0x%x 0x%x\n",
|
||||
rc->regtype, rc->addr, rc->value);
|
||||
TAILQ_REMOVE(&RegionContentList, rc, links);
|
||||
free(rc);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
TAILQ_INIT(&RegionContentList);
|
||||
}
|
Loading…
Reference in New Issue
Block a user