import amldb(8) from ACPI For FreeBSD project.

Obtained from:  ACPI For FreeBSD project
This commit is contained in:
Mitsuru IWASAKI 2000-08-31 14:45:00 +00:00
parent e1e9a4bf77
commit 01be5ae188
5 changed files with 1086 additions and 0 deletions

View 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
View 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
View 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;
}
}
}

View 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_ */

View 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);
}