diff options
Diffstat (limited to 'usr.sbin')
37 files changed, 8691 insertions, 2 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 5a5e534a034..bda04d16a03 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.119 2005/05/28 01:38:14 ho Exp $ +# $OpenBSD: Makefile,v 1.120 2005/06/02 20:09:39 tholo Exp $ .include <bsd.own.mk> @@ -17,7 +17,7 @@ SUBDIR= ac accton adduser amd arp authpf bgpctl bgpd bind chroot \ SUBDIR+=faithd ndp rip6query route6d rtadvd rtsold traceroute6 # Arch dependent tools, with manpages -SUBDIR+=bad144 apm apmd fdformat memconfig +SUBDIR+=bad144 acpid acpidump apm apmd fdformat memconfig SUBDIR+=eeprom gpioctl hotplugd SUBDIR+=wsconscfg wsfontload diff --git a/usr.sbin/acpid/Makefile b/usr.sbin/acpid/Makefile new file mode 100644 index 00000000000..98dd722d6da --- /dev/null +++ b/usr.sbin/acpid/Makefile @@ -0,0 +1,23 @@ +# $OpenBSD: Makefile,v 1.1 2005/06/02 20:09:39 tholo Exp $ + +.if (${MACHINE} == "i386") || (${MACHINE} == "amd64") +PROG= acpid +SRCS= main.c script.c +CFLAGS+= -Wall -pedantic +CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes +CFLAGS+= -Wmissing-declarations +CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual +CFLAGS+= -Wsign-compare +.else +NOPROG= yes +.endif + +MAN= acpid.8 +MANSUBDIR= i386 amd64 + +.if make(install) +SUBDIR+= samples +.endif + +.include <bsd.prog.mk> +.include <bsd.subdir.mk> diff --git a/usr.sbin/acpid/acpi.h b/usr.sbin/acpid/acpi.h new file mode 100644 index 00000000000..b03a17a4c34 --- /dev/null +++ b/usr.sbin/acpid/acpi.h @@ -0,0 +1,18 @@ +/* $OpenBSD: acpi.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/* + * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +void run_script(const char *); diff --git a/usr.sbin/acpid/acpid.8 b/usr.sbin/acpid/acpid.8 new file mode 100644 index 00000000000..99343062685 --- /dev/null +++ b/usr.sbin/acpid/acpid.8 @@ -0,0 +1,83 @@ +.\" $OpenBSD: acpid.8,v 1.1 2005/06/02 20:09:39 tholo Exp $ +.\" +.\" Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd May 27, 2005 +.Dt ACPID 8 +.Os +.Sh NAME +.Nm acpid +.Nd Advanced Configuration and Power Interface daemon +.Sh SYNOPSIS +.Nm acpid +.Op Fl d +.Sh DESCRIPTION +.Nm +monitors the advanced configuration and power interface (ACPI) device, +acting of signaled events. +For suspend and poweroff request events delivered by the BIOS, +.Nm +runs the appropriate program (if one exists). +.Pp +If the +.Fl d +flag is specified, +.Nm +enters debug mode, logging to facility +.Dv LOG_LOCAL1 +and staying in the foreground on the controlling terminal. +.Pp +Actions can be configured for the following two events: +.Cm suspend +and +.Cm powerdown . +The suspend actions are run when the sleep button is pressed, while +the powerdown action is run when the power button is pressed. +.Sh FILES +.Pa /etc/acpi/suspend +and +.Pa /etc/acpi/powerdown +are the files that contain the host's customized actions. +Each file must be an executable binary or shell script suitable +for execution by the +.Xr execve 2 +function. +If you wish to have the same program or script control all transitions, it +may determine which transition is in progress by examining its +.Va argv[0] +which is set to one of +.Ar suspend +and +.Ar powerdown . +.Pp +.Pa /dev/acpi +is the default device used to control the ACPI kernel driver. +.Sh SEE ALSO +.Xr execve 2 , +.Xr syslog 3 , +.Xr apm 4 , +.Xr speaker 4 , +.Xr apm 8 , +.Xr apmd 8 , +.Xr syslogd 8 +.Sh REFERENCES +Advanced Configuration and Power Interface Specification (Revision 3.0), +Hewlett-Packard Corporation, Intel Corporation, Microsoft Corporation, +Phoenix Technologies Ltd and Toshiba Corporation. +.Sh HISTORY +The +.Nm +command appeared in +.Ox 3.8 . diff --git a/usr.sbin/acpid/main.c b/usr.sbin/acpid/main.c new file mode 100644 index 00000000000..787f0a3c884 --- /dev/null +++ b/usr.sbin/acpid/main.c @@ -0,0 +1,135 @@ +/* $OpenBSD: main.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/* + * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/event.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <err.h> +#include <syslog.h> +#include <machine/bus.h> +#include <sys/device.h> +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> + +#include "pathnames.h" +#include "acpi.h" + +void sigexit(int); +void usage(void); +void run_script(const char *); + +int debug = 0; + +const char acpidev[] = _PATH_ACPI_DEV; + +extern char *__progname; + +void +sigexit(int sig) +{ +} + +void +usage(void) +{ + fprintf(stderr, + "usage: %s [-d]\n", + __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + const char *fname = acpidev; + int acpi_fd, ch; + int kq; + struct kevent ev[2]; + + while ((ch = getopt(argc, argv, "qadsepmf:t:S:")) != -1) + switch(ch) { + case 'd': + debug = 1; + break; + case '?': + default: + usage(); + } + + argc -= optind; + argv += optind; + + if (debug) + openlog(__progname, LOG_CONS, LOG_LOCAL1); + else { + daemon(0, 0); + openlog(__progname, LOG_CONS, LOG_DAEMON); + setlogmask(LOG_UPTO(LOG_NOTICE)); + } + + (void) signal(SIGTERM, sigexit); + (void) signal(SIGHUP, sigexit); + (void) signal(SIGINT, sigexit); + + if ((acpi_fd = open(fname, O_RDONLY)) == -1) + err(1, "open"); + + if (fcntl(acpi_fd, F_SETFD, 1) == -1) + err(1, "fcntl"); + + kq = kqueue(); + if (kq <= 0) + err(1, "kqueue"); + + EV_SET(&ev[0], acpi_fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, + 0, 0, NULL); + if (kevent(kq, ev, 1, NULL, 0, NULL) < 0) + err(1, "kevent"); + + for (;;) { + int rv; + + if ((rv = kevent(kq, NULL, 0, ev, 1, NULL)) < 0) + break; + + if (!rv) + continue; + + if (ev->ident == (u_int)acpi_fd) { + syslog(LOG_DEBUG, "acpi event %04x index %d", + ACPI_EVENT_TYPE(ev->data), + ACPI_EVENT_INDEX(ev->data)); + + switch (ACPI_EVENT_TYPE(ev->data)) { + case ACPI_EV_PWRBTN: + run_script("power-button"); + break; + case ACPI_EV_SLPBTN: + run_script("sleep-button"); + break; + default: + break; + } + + } + } + err(1, "kevent"); +} diff --git a/usr.sbin/acpid/pathnames.h b/usr.sbin/acpid/pathnames.h new file mode 100644 index 00000000000..17d8d24415d --- /dev/null +++ b/usr.sbin/acpid/pathnames.h @@ -0,0 +1,19 @@ +/* $OpenBSD: pathnames.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/* + * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _PATH_ACPI_DEV "/dev/acpi" +#define _PATH_ETC_ACPI "/etc/acpi" diff --git a/usr.sbin/acpid/samples/Makefile b/usr.sbin/acpid/samples/Makefile new file mode 100644 index 00000000000..d722dd75343 --- /dev/null +++ b/usr.sbin/acpid/samples/Makefile @@ -0,0 +1,7 @@ +# $OpenBSD: Makefile,v 1.1 2005/06/02 20:09:39 tholo Exp $ + +FILES= power-button +TARGETDIR= /etc/acpi + +install: + $(INSTALL) -c -m 0755 ${FILES} ${DESTDIR}${TARGETDIR} diff --git a/usr.sbin/acpid/samples/power-button b/usr.sbin/acpid/samples/power-button new file mode 100644 index 00000000000..38d6b6ab921 --- /dev/null +++ b/usr.sbin/acpid/samples/power-button @@ -0,0 +1,3 @@ +#! /bin/sh + +shutdown -hp now diff --git a/usr.sbin/acpid/script.c b/usr.sbin/acpid/script.c new file mode 100644 index 00000000000..2100582a199 --- /dev/null +++ b/usr.sbin/acpid/script.c @@ -0,0 +1,54 @@ +/* $OpenBSD: script.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/* + * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include "pathnames.h" +#include "acpi.h" + +void +run_script(const char *script) +{ + char path[MAXPATHLEN]; + int status; + pid_t pid; + + strlcpy(path, _PATH_ETC_ACPI, sizeof(path)); + strlcat(path, "/", sizeof(path)); + strlcat(path, script, sizeof(path)); + + if (access(path, X_OK)) { + strlcpy(path, _PATH_ETC_ACPI, sizeof(path)); + strlcat(path, "/default", sizeof(path)); + + if (access(path, X_OK)) + return; + } + + switch (pid = fork()) { + case -1: + return; + case 0: + execl(path, script, (char *)NULL); + break; + default: + wait4(pid, &status, 0, NULL); + break; + } +} diff --git a/usr.sbin/acpidump/Makefile b/usr.sbin/acpidump/Makefile new file mode 100644 index 00000000000..ebd0ae5776d --- /dev/null +++ b/usr.sbin/acpidump/Makefile @@ -0,0 +1,14 @@ +# $OpenBSD: Makefile,v 1.1 2005/06/02 20:09:39 tholo Exp $ + +PROG= acpidump +SRCS= acpi.c acpi_user.c asl_dump.c aml_dump.c acpidump.c +SRCS+= aml_name.c aml_parse.c aml_amlmem.c aml_memman.c aml_obj.c +SRCS+= aml_common.c aml_evalobj.c aml_store.c +MAN= acpidump.8 + +VPATH= ${.CURDIR}/aml +CFLAGS= -I${.CURDIR} + +BINDIR?=/usr/sbin + +.include <bsd.prog.mk> diff --git a/usr.sbin/acpidump/acpi.c b/usr.sbin/acpidump/acpi.c new file mode 100644 index 00000000000..f26cd57695f --- /dev/null +++ b/usr.sbin/acpidump/acpi.c @@ -0,0 +1,440 @@ +/* $OpenBSD: acpi.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1998 Doug Rabson + * Copyright (c) 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: acpi.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/acpidump/acpi.c,v 1.3 2000/11/08 02:37:00 iwasaki Exp $ + */ +#include <sys/types.h> +#include <sys/stat.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#include "acpidump.h" + +#include "aml/aml_env.h" +#include "aml/aml_common.h" + +#define BEGIN_COMMENT "/*\n" +#define END_COMMENT " */\n" + +struct ACPIsdt dsdt_header = { + "DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678 +}; + +static void +acpi_trim_string(char *s, size_t length) +{ + + /* Trim trailing spaces and NULLs */ + while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) + s[length-- - 1] = '\0'; +} + +static void +acpi_print_dsdt_definition(void) +{ + int len; + char *p; + char oemid[6 + 1]; + char oemtblid[8 + 1]; + + acpi_trim_string(dsdt_header.oemid, 6); + acpi_trim_string(dsdt_header.oemtblid, 8); + strncpy(oemid, dsdt_header.oemid, 6); + oemid[6] = '\0'; + strncpy(oemtblid, dsdt_header.oemtblid, 8); + oemtblid[8] = '\0'; + + printf("DefinitionBlock (\n" + "\"acpi_dsdt.aml\",\t//Output filename\n" + "\"DSDT\",\t\t\t//Signature\n" + "0x%x,\t\t\t//DSDT Revision\n" + "\"%s\",\t\t\t//OEMID\n" + "\"%s\",\t\t//TABLE ID\n" + "0x%x\t\t\t//OEM Revision\n)\n", + dsdt_header.rev, oemid, oemtblid, dsdt_header.oemrev); +} + +static void +acpi_print_string(char *s, size_t length) +{ + int c; + + /* Trim trailing spaces and NULLs */ + while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) + length--; + + while (length--) { + c = *s++; + putchar(c); + } +} + +static void +acpi_handle_dsdt(struct ACPIsdt *dsdp) +{ + u_int8_t *dp; + u_int8_t *end; + extern struct aml_environ asl_env; + + acpi_print_dsdt(dsdp); + + dp = (u_int8_t *)dsdp->body; + end = (u_int8_t *)dsdp + dsdp->len; + + acpi_dump_dsdt(dp, end); +} + +static void +acpi_handle_facp(struct FACPbody *facp) +{ + struct ACPIsdt *dsdp; + + acpi_print_facp(facp); + dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr); + if (acpi_checksum(dsdp, dsdp->len)) + errx(1, "DSDT is corrupt\n"); + acpi_handle_dsdt(dsdp); + aml_dump(dsdp); +} + +static void +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"; +} + +/* + * Public interfaces + */ + +void +acpi_dump_dsdt(u_int8_t *dp, u_int8_t *end) +{ + extern struct aml_environ asl_env; + + acpi_print_dsdt_definition(); + + /* 1st stage: parse only w/o printing */ + init_namespace(); + aml_new_name_group((long)dp); + bzero(&asl_env, sizeof(asl_env)); + + asl_env.dp = dp; + asl_env.end = end; + asl_env.curname = aml_get_rootname(); + + aml_local_stack_push(aml_local_stack_create()); + aml_parse_objectlist(&asl_env, 0); + aml_local_stack_delete(aml_local_stack_pop()); + + assert(asl_env.dp == asl_env.end); + asl_env.dp = dp; + + /* 2nd stage: dump whole object list */ + printf("\n{\n"); + asl_dump_objectlist(&dp, end, 0); + printf("\n}\n"); + assert(dp == end); +} +void +acpi_print_sdt(struct ACPIsdt *sdp) +{ + + printf(BEGIN_COMMENT); + acpi_print_string(sdp->signature, 4); + printf(": Length=%d, Revision=%d, Checksum=%d,\n", + sdp->len, sdp->rev, sdp->check); + printf("\tOEMID="); + acpi_print_string(sdp->oemid, 6); + printf(", OEM Table ID="); + acpi_print_string(sdp->oemtblid, 8); + printf(", OEM Revision=0x%x,\n", sdp->oemrev); + printf("\tCreator ID="); + acpi_print_string(sdp->creator, 4); + printf(", Creator Revision=0x%x\n", sdp->crerev); + printf(END_COMMENT); + if (!memcmp(sdp->signature, "DSDT", 4)) { + memcpy(&dsdt_header, sdp, sizeof(dsdt_header)); + } +} + +void +acpi_print_rsdt(struct ACPIsdt *rsdp) +{ + int i, entries; + + acpi_print_sdt(rsdp); + entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); + printf(BEGIN_COMMENT); + printf("\tEntries={ "); + for (i = 0; i < entries; i++) { + if (i > 0) + printf(", "); + printf("0x%08x", rsdp->body[i]); + } + printf(" }\n"); + printf(END_COMMENT); +} + +void +acpi_print_facp(struct FACPbody *facp) +{ + char sep; + + printf(BEGIN_COMMENT); + printf("\tDSDT=0x%x\n", facp->dsdt_ptr); + printf("\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC"); + printf("\tSCI_INT=%d\n", facp->sci_int); + printf("\tSMI_CMD=0x%x, ", facp->smi_cmd); + printf("ACPI_ENABLE=0x%x, ", facp->acpi_enable); + printf("ACPI_DISABLE=0x%x, ", facp->acpi_disable); + printf("S4BIOS_REQ=0x%x\n", facp->s4biosreq); + if (facp->pm1a_evt_blk) + printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", + facp->pm1a_evt_blk, + facp->pm1a_evt_blk + facp->pm1_evt_len - 1); + if (facp->pm1b_evt_blk) + printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", + facp->pm1b_evt_blk, + facp->pm1b_evt_blk + facp->pm1_evt_len - 1); + if (facp->pm1a_cnt_blk) + printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", + facp->pm1a_cnt_blk, + facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1); + if (facp->pm1b_cnt_blk) + printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", + facp->pm1b_cnt_blk, + facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1); + if (facp->pm2_cnt_blk) + printf("\tPM2_CNT_BLK=0x%x-0x%x\n", + facp->pm2_cnt_blk, + facp->pm2_cnt_blk + facp->pm2_cnt_len - 1); + if (facp->pm_tmr_blk) + printf("\tPM2_TMR_BLK=0x%x-0x%x\n", + facp->pm_tmr_blk, + facp->pm_tmr_blk + facp->pm_tmr_len - 1); + if (facp->gpe0_blk) + printf("\tPM2_GPE0_BLK=0x%x-0x%x\n", + facp->gpe0_blk, + facp->gpe0_blk + facp->gpe0_len - 1); + if (facp->gpe1_blk) + printf("\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", + facp->gpe1_blk, + facp->gpe1_blk + facp->gpe1_len - 1, + facp->gpe1_base); + printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", + facp->p_lvl2_lat, facp->p_lvl3_lat); + printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", + facp->flush_size, facp->flush_stride); + printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", + facp->duty_off, facp->duty_width); + printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", + facp->day_alrm, facp->mon_alrm, facp->century); + printf("\tFlags="); + sep = '{'; + +#define PRINTFLAG(xx) do { \ + if (facp->flags & ACPI_FACP_FLAG_## xx) { \ + printf("%c%s", sep, #xx); sep = ','; \ + } \ +} while (0) + + PRINTFLAG(WBINVD); + PRINTFLAG(WBINVD_FLUSH); + PRINTFLAG(PROC_C1); + PRINTFLAG(P_LVL2_UP); + PRINTFLAG(PWR_BUTTON); + PRINTFLAG(SLP_BUTTON); + PRINTFLAG(FIX_RTC); + PRINTFLAG(RTC_S4); + PRINTFLAG(TMR_VAL_EXT); + PRINTFLAG(DCK_CAP); + +#undef PRINTFLAG + + printf("}\n"); + printf(END_COMMENT); +} + +void +acpi_print_dsdt(struct ACPIsdt *dsdp) +{ + + acpi_print_sdt(dsdp); +} + +int +acpi_checksum(void *p, size_t length) +{ + u_int8_t *bp; + u_int8_t sum; + + bp = p; + sum = 0; + while (length--) + sum += *bp++; + + return (sum); +} + +struct ACPIsdt * +acpi_map_sdt(vm_offset_t pa) +{ + struct ACPIsdt *sp; + + sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); + sp = acpi_map_physical(pa, sp->len); + return (sp); +} + +void +acpi_print_rsd_ptr(struct ACPIrsdp *rp) +{ + + printf(BEGIN_COMMENT); + printf("RSD PTR: Checksum=%d, OEMID=", rp->sum); + acpi_print_string(rp->oem, 6); + printf(", RsdtAddress=0x%08x\n", rp->addr); + printf(END_COMMENT); +} + +void +acpi_handle_rsdt(struct ACPIsdt *rsdp) +{ + int i; + int entries; + struct ACPIsdt *sdp; + + entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); + acpi_print_rsdt(rsdp); + for (i = 0; i < entries; i++) { + sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]); + if (acpi_checksum(sdp, sdp->len)) + errx(1, "RSDT entry %d is corrupt\n", i); + if (!memcmp(sdp->signature, "FACP", 4)) { + acpi_handle_facp((struct FACPbody *) sdp->body); + } else { + acpi_print_sdt(sdp); + } + } +} + +/* + * Dummy functions + */ + +void +aml_dbgr(struct aml_environ *env1, struct aml_environ *env2) +{ + /* do nothing */ +} + +int +aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, + u_int32_t *valuep) +{ + return (0); +} + +int +aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, + u_int32_t value) +{ + return (0); +} + +u_int32_t +aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value) +{ + return (0); +} + +u_int32_t +aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value) +{ + return (0); +} + +int +aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value, + struct aml_region_handle *h) +{ + 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 (0); +} + +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 (0); +} + +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 (0); +} + +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 (0); +} + +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 (0); +} + diff --git a/usr.sbin/acpidump/acpi_user.c b/usr.sbin/acpidump/acpi_user.c new file mode 100644 index 00000000000..bd924fa4393 --- /dev/null +++ b/usr.sbin/acpidump/acpi_user.c @@ -0,0 +1,169 @@ +/* $OpenBSD: acpi_user.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Doug Rabson + * Copyright (c) 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: acpi_user.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/acpidump/acpi_user.c,v 1.3 2000/11/08 02:37:00 iwasaki Exp $ + */ +#ifdef __FreeBSD__ +#include <sys/param.h> +#else +#include <sys/types.h> +#define PAGE_MASK (0x1000-1) /*For I386*/ +#define trunc_page(x) ((x) & ~PAGE_MASK) +#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) +#endif + +#include <sys/mman.h> +#include <sys/queue.h> +#include <sys/stat.h> + +#include <err.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "acpidump.h" + +static int acpi_mem_fd = -1; + +struct acpi_user_mapping { + LIST_ENTRY(acpi_user_mapping) link; + vm_offset_t pa; + caddr_t va; + size_t size; +}; + +LIST_HEAD(acpi_user_mapping_list, acpi_user_mapping) maplist; + +static void +acpi_user_init() +{ + + if (acpi_mem_fd == -1) { + acpi_mem_fd = open("/dev/mem", O_RDONLY); + if (acpi_mem_fd == -1) + err(1, "opening /dev/mem"); + LIST_INIT(&maplist); + } +} + +static struct acpi_user_mapping * +acpi_user_find_mapping(vm_offset_t pa, size_t size) +{ + struct acpi_user_mapping *map; + + /* First search for an existing mapping */ + for (map = LIST_FIRST(&maplist); map; map = LIST_NEXT(map, link)) { + if (map->pa <= pa && map->size >= pa + size - map->pa) + return (map); + } + + /* Then create a new one */ + size = round_page(pa + size) - trunc_page(pa); + pa = trunc_page(pa); + map = malloc(sizeof(struct acpi_user_mapping)); + if (!map) + errx(1, "out of memory"); + map->pa = pa; + map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa); + map->size = size; + if ((long) map->va == -1) + err(1, "can't map address"); + LIST_INSERT_HEAD(&maplist, map, link); + + return (map); +} + +/* + * Public interfaces + */ + +struct ACPIrsdp * +acpi_find_rsd_ptr() +{ + int i; + u_int8_t buf[sizeof(struct ACPIrsdp)]; + + acpi_user_init(); + for (i = 0; i < 1024 * 1024; i += 16) { + read(acpi_mem_fd, buf, 16); + if (!memcmp(buf, "RSD PTR ", 8)) { + /* Read the rest of the structure */ + read(acpi_mem_fd, buf + 16, sizeof(struct ACPIrsdp) - 16); + + /* Verify checksum before accepting it. */ + if (acpi_checksum(buf, sizeof(struct ACPIrsdp))) + continue; + return (acpi_map_physical(i, sizeof(struct ACPIrsdp))); + } + } + + return (0); +} + +void * +acpi_map_physical(vm_offset_t pa, size_t size) +{ + struct acpi_user_mapping *map; + + map = acpi_user_find_mapping(pa, size); + return (map->va + (pa - map->pa)); +} + +void +acpi_load_dsdt(char *dumpfile, u_int8_t **dpp, u_int8_t **endp) +{ + u_int8_t *dp; + u_int8_t *end; + struct stat sb; + + if ((acpi_mem_fd = open(dumpfile, O_RDONLY)) == -1) { + errx(1, "opening %s\n", dumpfile); + } + + LIST_INIT(&maplist); + + if (fstat(acpi_mem_fd, &sb) == -1) { + errx(1, "fstat %s\n", dumpfile); + } + + dp = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, acpi_mem_fd, 0); + if (dp == NULL) { + errx(1, "mmap %s\n", dumpfile); + } + + if (strncmp(dp, "DSDT", 4) == 0) { + memcpy(&dsdt_header, dp, SIZEOF_SDT_HDR); + dp += SIZEOF_SDT_HDR; + sb.st_size -= SIZEOF_SDT_HDR; + } + + end = (u_int8_t *) dp + sb.st_size; + *dpp = dp; + *endp = end; +} diff --git a/usr.sbin/acpidump/acpidump.8 b/usr.sbin/acpidump/acpidump.8 new file mode 100644 index 00000000000..bf235989f9e --- /dev/null +++ b/usr.sbin/acpidump/acpidump.8 @@ -0,0 +1,170 @@ +.\" $OpenBSD: acpidump.8,v 1.1 2005/06/02 20:09:39 tholo Exp $ +.\" +.\" Copyright (c) 1999 Doug Rabson <dfr@FreeBSD.org> +.\" Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> +.\" Copyright (c) 2000 Yasuo YOKOYAMA <yokoyama@jp.FreeBSD.org> +.\" Copyright (c) 2000 Hiroki Sato <hrs@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 REGENTS 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 REGENTS 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. +.\" +.\" $FreeBSD: src/usr.sbin/acpi/acpidump/acpidump.8,v 1.9 2001/09/05 19:21:25 dd Exp $ +.\" +.Dd August 31, 2000 +.Dt ACPIDUMP 8 +.Os +.Sh NAME +.Nm acpidump +.Nd dump ACPI tables +.Sh SYNOPSIS +.Nm +.Nm +.Op Fl o Ar dsdt_file_for_output +.Nm +.Op Fl f Ar dsdt_file_for_input +.Sh DESCRIPTION +The +.Nm +command analyzes ACPI tables in physical memory and dumps them to standard output. +In addition, +.Nm +can disassemble some contents of the tables in AML +(ACPI Machine Language) +and dump them in ASL +(ACPI Source Language). +.Pp +ACPI tables have an notably essential data block called DSDT +(Differentiated System Description Table), +that includes information used on the kernel side such as +detail information about PnP hardware, procedures for controlling +a power management support and so on. +.Nm +can extract a DSDT data block from physical memory and store it into +a DSDT data file, and also can generate an output in ASL +from a given DSDT data file. +.Pp +When +.Nm +is invoked with no option, it will search ACPI tables from physical +memory via a special file +.Pa /dev/mem +and dump them. First, it searches Root System Description Pointer, +that has a signature +.Qq RSD PTR\ \& , +and then gets RSDT +(Root System Description Table), +which includes a list of pointers to physical memory addresses +for other tables. +RSDT itself and all other tables linked from RSDT are generically +called SDT +(System Description Table) +and their header has the common format which consists of items +such as Signature, Length, Revision, Checksum, OEMID, OEM Table ID, +OEM Revision, Creator ID and Creator Revision. +.Nm +dumps contents of these SDTs. +For further information about formats of each table, +see chapter 5: ACPI Software Programming Model, +.Dq Advanced Configuration and Power Interface Specification Revision 1.0b +from Intel/Microsoft/Toshiba. +.Pp +There is always a pointer to a physical memory address in RSDT for FACP +(Fixed ACPI Description Table). +FACP defines static system information about power management support +(ACPI Hardware Register Implementation) +such as interrupt mode +(INT_MODEL), +SCI interrupt number, SMI command port +(SMI_CMD) +and location of ACPI registers. +FACP also has a pointer to a physical memory address for DSDT, +which includes information used on the kernel side such as +PnP, power management support and so on. +While the other tables are described in fixed format, +DSDT consists of AML data which compiled from sources +written in free formated ASL, description language for ACPI. +When +.Nm +outputs DSDT, it disassembles the AML data and +translates them into ASL. +.Sh OPTIONS +The following options are supported by +.Nm : +.Bl -tag -width indent +.It Fl o Ar dsdt_file_for_output +Stores DSDT data block from physical memory into a file specified in +.Ar dsdt_file_for_output +in addition to behavior with no option. +.It Fl f Ar dsdt_file_for_input +Interprets AML data in DSDT from a file specified in +.Ar dsdt_file_for_input +and dumps them in ASL to standard output. +.It Fl h +Displays usage and exit. +.El +.Sh EXAMPLES +This is an example to get a dump of SDTs and a DSDT data file +simultaneously on a machine that supports ACPI BIOS. +.Bd -literal -offset indent +# acpidump -o foo.dsdt > foo.asl +.Ed +.Sh BUGS +In the current implementation, +.Nm +doesn't dump any information of Firmware ACPI Control Structure +(FACS) +specified by a pointer in FACP. +.Sh FILES +.Bl -tag -width /dev/mem +.It Pa /dev/mem +.El +.Sh SEE ALSO +.\" .Xr acpi 4 , +.Xr mem 4 , +.\" .Xr acpiconf 8 , +..\" Xr amldb 8 +.Pp +.Dq Advanced Configuration and Power Interface Specification +.Bd -literal -offset indent -compact +Intel +Microsoft +Toshiba +Revision 1.0b +.Ed +<URL:http://www.teleport.com/~acpi/> +.Sh AUTHORS +.An Doug Rabson Aq dfr@FreeBSD.org +.An Mitsuru IWASAKI Aq iwasaki@FreeBSD.org +.An Yasuo YOKOYAMA Aq yokoyama@jp.FreeBSD.org +.Pp +Some contributions made by +.An Chitoshi Ohsawa Aq ohsawa@catv1.ccn-net.ne.jp , +.An Takayasu IWANASHI Aq takayasu@wendy.a.perfect-liberty.or.jp , +.An Yoshihiko SARUMARU Aq mistral@imasy.or.jp , +.An Hiroki Sato Aq hrs@FreeBSD.org , +and +.An Michael Lucas Aq mwlucas@blackhelicopters.org . +.Sh HISTORY +The +.Nm +command appeared in +.Fx 5.0 . diff --git a/usr.sbin/acpidump/acpidump.c b/usr.sbin/acpidump/acpidump.c new file mode 100644 index 00000000000..82c562efc32 --- /dev/null +++ b/usr.sbin/acpidump/acpidump.c @@ -0,0 +1,105 @@ +/* $OpenBSD: acpidump.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 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: acpidump.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/acpidump/acpidump.c,v 1.3 2000/11/08 02:37:00 iwasaki Exp $ + */ + +#include <sys/types.h> + +#include <assert.h> +#include <err.h> +#include <stdio.h> +#include <unistd.h> + +#include "acpidump.h" + +static void +asl_dump_from_file(char *file) +{ + u_int8_t *dp; + u_int8_t *end; + struct ACPIsdt *dsdt; + + acpi_load_dsdt(file, &dp, &end); + acpi_dump_dsdt(dp, end); +} + +static void +asl_dump_from_devmem() +{ + struct ACPIrsdp *rp; + struct ACPIsdt *rsdp; + + rp = acpi_find_rsd_ptr(); + if (!rp) + errx(1, "Can't find ACPI information\n"); + + acpi_print_rsd_ptr(rp); + rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->addr); + if (memcmp(rsdp->signature, "RSDT", 4) || + acpi_checksum(rsdp, rsdp->len)) + errx(1, "RSDT is corrupted\n"); + + acpi_handle_rsdt(rsdp); +} + +static void +usage(const char *progname) +{ + + printf("usage:\t%s [-o dsdt_file_for_output]\n", progname); + printf("\t%s [-f dsdt_file_for_input]\n", progname); + printf("\t%s [-h]\n", progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char c, *progname; + + progname = argv[0]; + while ((c = getopt(argc, argv, "f:o:h")) != -1) { + switch (c) { + case 'f': + asl_dump_from_file(optarg); + return (0); + case 'o': + aml_dumpfile = optarg; + break; + case 'h': + usage(progname); + break; + default: + argc -= optind; + argv += optind; + } + } + + asl_dump_from_devmem(); + return (0); +} diff --git a/usr.sbin/acpidump/acpidump.h b/usr.sbin/acpidump/acpidump.h new file mode 100644 index 00000000000..4d1ce79966e --- /dev/null +++ b/usr.sbin/acpidump/acpidump.h @@ -0,0 +1,184 @@ +/* $OpenBSD: acpidump.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Doug Rabson + * Copyright (c) 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: acpidump.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/acpidump/acpidump.h,v 1.2 2000/11/08 02:37:00 iwasaki Exp $ + */ + +#ifndef _ACPIDUMP_H_ +#define _ACPIDUMP_H_ +#include <stdlib.h> + +typedef unsigned long vm_offset_t; + +/* Generic Address structure */ +struct ACPIgas { + u_int8_t address_space_id; +#define ACPI_GAS_MEMORY 0 +#define ACPI_GAS_IO 1 +#define ACPI_GAS_PCI 2 +#define ACPI_GAS_EMBEDDED 3 +#define ACPI_GAS_SMBUS 4 +#define ACPI_GAS_FIXED 0x7f + u_int8_t register_bit_width; + u_int8_t register_bit_offset; + u_int8_t res; + u_int64_t address; +} __attribute__((packed)); + +/* Root System Description Pointer */ +struct ACPIrsdp { + u_char signature[8]; + u_char sum; + u_char oem[6]; + u_char res; + u_int32_t addr; +} __attribute__((packed)); + +/* System Description Table */ +struct ACPIsdt { + u_char signature[4]; + u_int32_t len; + u_char rev; + u_char check; + u_char oemid[6]; + u_char oemtblid[8]; + u_int32_t oemrev; + u_char creator[4]; + u_int32_t crerev; +#define SIZEOF_SDT_HDR 36 /* struct size except body */ + u_int32_t body[1];/* This member should be casted */ +} __attribute__((packed)); + +/* Fixed ACPI Description Table (body) */ +struct FACPbody { + u_int32_t facs_ptr; + u_int32_t dsdt_ptr; + u_int8_t int_model; +#define ACPI_FACP_INTMODEL_PIC 0 /* Standard PC-AT PIC */ +#define ACPI_FACP_INTMODEL_APIC 1 /* Multiple APIC */ + u_char reserved1; + u_int16_t sci_int; + u_int32_t smi_cmd; + u_int8_t acpi_enable; + u_int8_t acpi_disable; + u_int8_t s4biosreq; + u_int8_t reserved2; + u_int32_t pm1a_evt_blk; + u_int32_t pm1b_evt_blk; + u_int32_t pm1a_cnt_blk; + u_int32_t pm1b_cnt_blk; + u_int32_t pm2_cnt_blk; + u_int32_t pm_tmr_blk; + u_int32_t gpe0_blk; + u_int32_t gpe1_blk; + u_int8_t pm1_evt_len; + u_int8_t pm1_cnt_len; + u_int8_t pm2_cnt_len; + u_int8_t pm_tmr_len; + u_int8_t gpe0_len; + u_int8_t gpe1_len; + u_int8_t gpe1_base; + u_int8_t reserved3; + u_int16_t p_lvl2_lat; + u_int16_t p_lvl3_lat; + u_int16_t flush_size; + u_int16_t flush_stride; + u_int8_t duty_off; + u_int8_t duty_width; + u_int8_t day_alrm; + u_int8_t mon_alrm; + u_int8_t century; + u_int16_t iapc_boot_arch; + u_char reserved4[1]; + u_int32_t flags; +#define ACPI_FACP_FLAG_WBINVD 1 /* WBINVD is correctly supported */ +#define ACPI_FACP_FLAG_WBINVD_FLUSH 2 /* WBINVD flushes caches */ +#define ACPI_FACP_FLAG_PROC_C1 4 /* C1 power state supported */ +#define ACPI_FACP_FLAG_P_LVL2_UP 8 /* C2 power state works on SMP */ +#define ACPI_FACP_FLAG_PWR_BUTTON 16 /* Power button uses control method */ +#define ACPI_FACP_FLAG_SLP_BUTTON 32 /* Sleep button uses control method */ +#define ACPI_FACP_FLAG_FIX_RTC 64 /* RTC wakeup not supported */ +#define ACPI_FACP_FLAG_RTC_S4 128 /* RTC can wakeup from S4 state */ +#define ACPI_FACP_FLAG_TMR_VAL_EXT 256 /* TMR_VAL is 32bit */ +#define ACPI_FACP_FLAG_DCK_CAP 512 /* Can support docking */ + struct ACPIgas reset_reg; + u_int8_t reset_value; + u_int8_t reserved5[3]; + u_int64_t x_firmware_ctrl; + u_int64_t x_dsdt; + struct ACPIgas x_pm1a_evt_blk; + struct ACPIgas x_pm1b_evt_blk; + struct ACPIgas x_pm1a_cnt_blk; + struct ACPIgas x_pm1b_cnt_blk; + struct ACPIgas x_pm2_cnt_blk; + struct ACPIgas x_pm_tmr_blk; + struct ACPIgas x_gpe0_blk; + struct ACPIgas x_gpe1_blk; +} __attribute__((packed)); + +/* Firmware ACPI Control Structure */ +struct FACS { + u_char signature[4]; + u_int32_t len; + u_char hard_sig[4]; + /* + * NOTE This should be filled with physical address below 1MB!! + * sigh.... + */ + u_int32_t firm_wake_vec; + u_int32_t g_lock; /* bit field */ + /* 5.2.6.1 Global Lock */ +#define ACPI_GLOBAL_LOCK_PENDING 1 +#define ACPI_GLOBAL_LOCK_OWNED 2 + u_int32_t flags; /* bit field */ +#define ACPI_FACS_FLAG_S4BIOS_F 1 /* Supports S4BIOS_SEQ */ + char reserved[40]; +} __attribute__((packed)); + +void *acpi_map_physical(vm_offset_t, size_t); +struct ACPIrsdp *acpi_find_rsd_ptr(void); +int acpi_checksum(void *, size_t); +struct ACPIsdt *acpi_map_sdt(vm_offset_t); +void acpi_print_rsd_ptr(struct ACPIrsdp *); +void acpi_print_sdt(struct ACPIsdt *); +void acpi_print_rsdt(struct ACPIsdt *); +void acpi_print_facp(struct FACPbody *); +void acpi_print_dsdt(struct ACPIsdt *); + +void asl_dump_termobj(u_int8_t **, int); +void asl_dump_objectlist(u_int8_t **, u_int8_t *, int); + +void aml_dump(struct ACPIsdt *); + +void acpi_handle_rsdt(struct ACPIsdt *); +void acpi_load_dsdt(char *, u_int8_t **, u_int8_t **); +void acpi_dump_dsdt(u_int8_t *, u_int8_t *); +extern char *aml_dumpfile; +extern struct ACPIsdt dsdt_header; + +#endif /* !_ACPIDUMP_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_amlmem.c b/usr.sbin/acpidump/aml/aml_amlmem.c new file mode 100644 index 00000000000..b696465ba64 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_amlmem.c @@ -0,0 +1,91 @@ +/* $OpenBSD: aml_amlmem.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_amlmem.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_amlmem.c,v 1.2 2000/11/09 06:24:45 iwasaki Exp $ + */ + +/* + * AML Namespace Memory Management + */ +#include <sys/types.h> +#include <aml/aml_env.h> +#include <aml/aml_memman.h> +#include <aml/aml_name.h> + +MEMMAN_INITIALSTORAGE_DESC(struct aml_namestr, _aml_namestr_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_num, _aml_num_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_string, _aml_string_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_buffer, _aml_buffer_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_package, _aml_package_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_field, _aml_field_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_method, _aml_method_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_mutex, _aml_mutex_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_opregion, _aml_opregion_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_powerres, _aml_powerres_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_processor, _aml_processor_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_bufferfield, _aml_bufferfield_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_event, _aml_event_storage); +MEMMAN_INITIALSTORAGE_DESC(enum aml_objtype, _aml_objtype_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_name, _aml_name_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_name_group, _aml_name_group_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_objref, _aml_objref_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_regfield, _aml_regfield_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_environ, _aml_environ_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_local_stack, _aml_local_stack_storage); +MEMMAN_INITIALSTORAGE_DESC(struct aml_mutex_queue, _aml_mutex_queue_storage); + +struct memman_blockman aml_blockman[] = { + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_namestr), _aml_namestr_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_num), _aml_num_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_string), _aml_string_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_buffer), _aml_buffer_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_package), _aml_package_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_field), _aml_field_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_method), _aml_method_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_mutex), _aml_mutex_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_opregion), _aml_opregion_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_powerres), _aml_powerres_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_processor), _aml_processor_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_bufferfield), _aml_bufferfield_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_event), _aml_event_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(enum aml_objtype), _aml_objtype_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_name), _aml_name_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_name_group), _aml_name_group_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_objref), _aml_objref_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_regfield), _aml_regfield_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_environ), _aml_environ_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_local_stack), _aml_local_stack_storage), + MEMMAN_MEMBLOCK_DESC(sizeof(struct aml_mutex_queue), _aml_mutex_queue_storage), +}; + +struct memman_histogram aml_histogram[MEMMAN_HISTOGRAM_SIZE]; + +static struct memman _aml_memman = MEMMAN_MEMMANAGER_DESC(aml_blockman, 21, + aml_histogram, 1); + +struct memman *aml_memman = &_aml_memman; + diff --git a/usr.sbin/acpidump/aml/aml_amlmem.h b/usr.sbin/acpidump/aml/aml_amlmem.h new file mode 100644 index 00000000000..354c6522547 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_amlmem.h @@ -0,0 +1,66 @@ +/* $OpenBSD: aml_amlmem.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_amlmem.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_amlmem.h,v 1.2 2000/11/09 06:24:45 iwasaki Exp $ + */ + +#ifndef _AML_AMLMEM_H_ +#define _AML_AMLMEM_H_ + +/* + * AML Namespace Memory Management + */ + +#include <aml/aml_memman.h> + +enum { + memid_aml_namestr = 0, + memid_aml_num, + memid_aml_string, + memid_aml_buffer, + memid_aml_package, + memid_aml_field, + memid_aml_method, + memid_aml_mutex, + memid_aml_opregion, + memid_aml_powerres, + memid_aml_processor, + memid_aml_bufferfield, + memid_aml_event, + memid_aml_objtype, + memid_aml_name, + memid_aml_name_group, + memid_aml_objref, + memid_aml_regfield, + memid_aml_environ, + memid_aml_local_stack, + memid_aml_mutex_queue, +}; + +extern struct memman *aml_memman; + +#endif /* !_AML_AMLMEM_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_common.c b/usr.sbin/acpidump/aml/aml_common.c new file mode 100644 index 00000000000..32a97d9ac78 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_common.c @@ -0,0 +1,734 @@ +/* $OpenBSD: aml_common.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_common.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_common.c,v 1.6 2000/11/09 06:24:45 iwasaki Exp $ + */ +#include <sys/types.h> +#ifndef _KERNEL +#include <assert.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#else /* _KERNEL */ +#include "opt_acpi.h" +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#ifndef ACPI_NO_OSDFUNC_INLINE +#include <machine/acpica_osd.h> +#endif /* !ACPI_NO_OSDFUNC_INLINE */ +#endif /* !_KERNEL */ + +#include <aml/aml_common.h> +#include <aml/aml_env.h> +#include <aml/aml_evalobj.h> +#include <aml/aml_name.h> +#include <aml/aml_obj.h> +#include <aml/aml_parse.h> +#include <aml/aml_status.h> +#include <aml/aml_store.h> + +/* for debugging */ +#ifdef AML_DEBUG +int aml_debug = 1; +#else /* !AML_DEBUG */ +int aml_debug = 0; +#endif /* AML_DEBUG */ +#ifdef _KERNEL +SYSCTL_INT(_debug, OID_AUTO, aml_debug, CTLFLAG_RW, &aml_debug, 1, ""); +#endif /* _KERNEL */ + +static void aml_print_nameseg(u_int8_t *dp); + +static void +aml_print_nameseg(u_int8_t *dp) +{ + + if (dp[3] != '_') { + AML_DEBUGPRINT("%c%c%c%c", dp[0], dp[1], dp[2], dp[3]); + } else if (dp[2] != '_') { + AML_DEBUGPRINT("%c%c%c_", dp[0], dp[1], dp[2]); + } else if (dp[1] != '_') { + AML_DEBUGPRINT("%c%c__", dp[0], dp[1]); + } else if (dp[0] != '_') { + AML_DEBUGPRINT("%c___", dp[0]); + } +} + +void +aml_print_namestring(u_int8_t *dp) +{ + int segcount; + int i; + + if (dp[0] == '\\') { + AML_DEBUGPRINT("%c", dp[0]); + dp++; + } else if (dp[0] == '^') { + while (dp[0] == '^') { + AML_DEBUGPRINT("%c", dp[0]); + dp++; + } + } + if (dp[0] == 0x00) { /* NullName */ + /* AML_DEBUGPRINT("<null>"); */ + dp++; + } else if (dp[0] == 0x2e) { /* DualNamePrefix */ + aml_print_nameseg(dp + 1); + AML_DEBUGPRINT("%c", '.'); + aml_print_nameseg(dp + 5); + } else if (dp[0] == 0x2f) { /* MultiNamePrefix */ + segcount = dp[1]; + for (i = 0, dp += 2; i < segcount; i++, dp += 4) { + if (i > 0) { + AML_DEBUGPRINT("%c", '.'); + } + aml_print_nameseg(dp); + } + } else /* NameSeg */ + aml_print_nameseg(dp); +} + +int +aml_print_curname(struct aml_name *name) +{ + struct aml_name *root; + + root = aml_get_rootname(); + if (name == root) { + AML_DEBUGPRINT("\\"); + return (0); + } else { + aml_print_curname(name->parent); + } + aml_print_nameseg(name->name); + AML_DEBUGPRINT("."); + return (0); +} + +void +aml_print_indent(int indent) +{ + int i; + + for (i = 0; i < indent; i++) + AML_DEBUGPRINT(" "); +} + +void +aml_showobject(union aml_object * obj) +{ + int debug; + int i; + + if (obj == NULL) { + printf("NO object\n"); + return; + } + debug = aml_debug; + aml_debug = 1; + switch (obj->type) { + case aml_t_num: + printf("Num:0x%x\n", obj->num.number); + break; + case aml_t_processor: + printf("Processor:No %d,Port 0x%x length 0x%x\n", + obj->proc.id, obj->proc.addr, obj->proc.len); + break; + case aml_t_mutex: + printf("Mutex:Level %d\n", obj->mutex.level); + break; + case aml_t_powerres: + printf("PowerResource:Level %d Order %d\n", + obj->pres.level, obj->pres.order); + break; + case aml_t_opregion: + printf("OprationRegion:Busspace%d, Offset 0x%x Length 0x%x\n", + obj->opregion.space, obj->opregion.offset, + obj->opregion.length); + break; + case aml_t_field: + printf("Fieldelement:flag 0x%x offset 0x%x len 0x%x {", + obj->field.flags, obj->field.bitoffset, + obj->field.bitlen); + switch (obj->field.f.ftype) { + case f_t_field: + aml_print_namestring(obj->field.f.fld.regname); + break; + case f_t_index: + aml_print_namestring(obj->field.f.ifld.indexname); + printf(" "); + aml_print_namestring(obj->field.f.ifld.dataname); + break; + case f_t_bank: + aml_print_namestring(obj->field.f.bfld.regname); + printf(" "); + aml_print_namestring(obj->field.f.bfld.bankname); + printf("0x%x", obj->field.f.bfld.bankvalue); + break; + } + printf("}\n"); + break; + case aml_t_method: + printf("Method: Arg %d From %p To %p\n", obj->meth.argnum, + obj->meth.from, obj->meth.to); + break; + case aml_t_buffer: + printf("Buffer: size:0x%x Data %p\n", obj->buffer.size, + obj->buffer.data); + break; + case aml_t_device: + printf("Device\n"); + break; + case aml_t_bufferfield: + printf("Bufferfield:offset 0x%x len 0x%x Origin %p\n", + obj->bfld.bitoffset, obj->bfld.bitlen, obj->bfld.origin); + break; + case aml_t_string: + printf("String:%s\n", obj->str.string); + break; + case aml_t_package: + printf("Package:elements %d \n", obj->package.elements); + for (i = 0; i < obj->package.elements; i++) { + if (obj->package.objects[i] == NULL) { + break; + } + if (obj->package.objects[i]->type < 0) { + continue; + } + printf(" "); + aml_showobject(obj->package.objects[i]); + } + break; + case aml_t_therm: + printf("Thermalzone\n"); + break; + case aml_t_event: + printf("Event\n"); + break; + case aml_t_ddbhandle: + printf("DDBHANDLE\n"); + break; + case aml_t_objref: + if (obj->objref.alias == 1) { + printf("Alias"); + } else { + printf("Object reference"); + if (obj->objref.offset >= 0) { + printf(" (offset 0x%x)", obj->objref.offset); + } + } + printf(" of "); + aml_showobject(obj->objref.ref); + break; + default: + printf("UNK ID=%d\n", obj->type); + } + + aml_debug = debug; +} + +void +aml_showtree(struct aml_name * aname, int lev) +{ + int i; + struct aml_name *ptr; + char name[5]; + + for (i = 0; i < lev; i++) { + printf(" "); + } + strncpy(name, aname->name, 4); + name[4] = 0; + printf("%s ", name); + if (aname->property != NULL) { + aml_showobject(aname->property); + } else { + printf("\n"); + } + for (ptr = aname->child; ptr; ptr = ptr->brother) + aml_showtree(ptr, lev + 1); +} + +/* + * Common Region I/O Stuff + */ + +static __inline u_int64_t +aml_adjust_bitmask(u_int32_t flags, u_int32_t bitlen) +{ + u_int64_t bitmask; + + switch (AML_FIELDFLAGS_ACCESSTYPE(flags)) { + case AML_FIELDFLAGS_ACCESS_ANYACC: + if (bitlen <= 8) { + bitmask = 0x000000ff; + break; + } + if (bitlen <= 16) { + bitmask = 0x0000ffff; + break; + } + bitmask = 0xffffffff; + break; + case AML_FIELDFLAGS_ACCESS_BYTEACC: + bitmask = 0x000000ff; + break; + case AML_FIELDFLAGS_ACCESS_WORDACC: + bitmask = 0x0000ffff; + break; + case AML_FIELDFLAGS_ACCESS_DWORDACC: + default: + bitmask = 0xffffffff; + break; + } + + switch (bitlen) { + case 16: + bitmask |= 0x0000ffff; + break; + case 32: + bitmask |= 0xffffffff; + break; + } + + return (bitmask); +} + +u_int32_t +aml_adjust_readvalue(u_int32_t flags, u_int32_t bitoffset, u_int32_t bitlen, + u_int32_t orgval) +{ + u_int32_t offset, retval; + u_int64_t bitmask; + + offset = bitoffset; /* XXX bitoffset may change in this function! */ + bitmask = aml_adjust_bitmask(flags, bitlen); + retval = (orgval >> offset) & (~(bitmask << bitlen)) & bitmask; + + return (retval); +} + +u_int32_t +aml_adjust_updatevalue(u_int32_t flags, u_int32_t bitoffset, u_int32_t bitlen, + u_int32_t orgval, u_int32_t value) +{ + u_int32_t offset, retval; + u_int64_t bitmask; + + offset = bitoffset; /* XXX bitoffset may change in this function! */ + bitmask = aml_adjust_bitmask(flags, bitlen); + retval = orgval; + switch (AML_FIELDFLAGS_UPDATERULE(flags)) { + case AML_FIELDFLAGS_UPDATE_PRESERVE: + retval &= (~(((u_int64_t)1 << bitlen) - 1) << offset) | + (~(bitmask << offset)); + break; + case AML_FIELDFLAGS_UPDATE_WRITEASONES: + retval = (~(((u_int64_t)1 << bitlen) - 1) << offset) | + (~(bitmask << offset)); + retval &= bitmask; /* trim the upper bits */ + break; + case AML_FIELDFLAGS_UPDATE_WRITEASZEROS: + retval = 0; + break; + default: + printf("illegal update rule: %d\n", flags); + return (orgval); + } + + retval |= (value << (offset & bitmask)); + return (retval); +} + +/* + * BufferField I/O + */ + +#define AML_BUFFER_INPUT 0 +#define AML_BUFFER_OUTPUT 1 + +static int aml_bufferfield_io(int io, u_int32_t *valuep, + u_int8_t *origin, u_int32_t bitoffset, + u_int32_t bitlen); + +static int +aml_bufferfield_io(int io, u_int32_t *valuep, u_int8_t *origin, + u_int32_t bitoffset, u_int32_t bitlen) +{ + u_int8_t val, tmp, masklow, maskhigh; + u_int8_t offsetlow, offsethigh; + u_int8_t *addr; + int i; + u_int32_t value, readval; + u_int32_t byteoffset, bytelen; + + masklow = maskhigh = 0xff; + val = readval = 0; + value = *valuep; + + byteoffset = bitoffset / 8; + bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0); + addr = origin + byteoffset; + + /* simple I/O ? */ + if (bitlen <= 8 || bitlen == 16 || bitlen == 32) { + bcopy(addr, &readval, bytelen); + AML_DEBUGPRINT("\n\t[bufferfield:0x%x@%p:%d,%d]", + readval, addr, bitoffset % 8, bitlen); + switch (io) { + case AML_BUFFER_INPUT: + value = aml_adjust_readvalue(AML_FIELDFLAGS_ACCESS_BYTEACC, + bitoffset % 8, bitlen, readval); + *valuep = value; + AML_DEBUGPRINT("\n[read(bufferfield, %p)&mask:0x%x]\n", + addr, value); + break; + case AML_BUFFER_OUTPUT: + value = aml_adjust_updatevalue(AML_FIELDFLAGS_ACCESS_BYTEACC, + bitoffset % 8, bitlen, readval, value); + bcopy(&value, addr, bytelen); + AML_DEBUGPRINT("->[bufferfield:0x%x@%p:%d,%d]", + value, addr, bitoffset % 8, bitlen); + break; + } + goto out; + } + + offsetlow = bitoffset % 8; + if (bytelen > 1) { + offsethigh = (bitlen - (8 - offsetlow)) % 8; + } else { + offsethigh = 0; + } + + if (offsetlow) { + masklow = (~((1 << bitlen) - 1) << offsetlow) | ~(0xff << offsetlow); + AML_DEBUGPRINT("\t[offsetlow = 0x%x, masklow = 0x%x, ~masklow = 0x%x]\n", + offsetlow, masklow, ~masklow & 0xff); + } + if (offsethigh) { + maskhigh = 0xff << offsethigh; + AML_DEBUGPRINT("\t[offsethigh = 0x%x, maskhigh = 0x%x, ~maskhigh = 0x%x]\n", + offsethigh, maskhigh, ~maskhigh & 0xff); + } + for (i = bytelen; i > 0; i--, addr++) { + val = *addr; + + AML_DEBUGPRINT("\t[bufferfield:0x%02x@%p]", val, addr); + + switch (io) { + case AML_BUFFER_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; + } + + AML_DEBUGPRINT("\n"); + /* goto to next byte... */ + if (i > 1) { + continue; + } + /* final adjustment before finishing region access */ + if (offsetlow) { + readval = readval >> offsetlow; + } + AML_DEBUGPRINT("[read(bufferfield, %p)&mask:0x%x]\n", + addr, readval); + *valuep = readval; + + break; + + case AML_BUFFER_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; + } + + AML_DEBUGPRINT("->[bufferfield:0x%02x@%p]\n", + tmp, addr); + *addr = tmp; + } + } +out: + return (0); +} + +u_int32_t +aml_bufferfield_read(u_int8_t *origin, u_int32_t bitoffset, + u_int32_t bitlen) +{ + int value; + + value = 0; + aml_bufferfield_io(AML_BUFFER_INPUT, &value, origin, + bitoffset, bitlen); + return (value); +} + +int +aml_bufferfield_write(u_int32_t value, u_int8_t *origin, + u_int32_t bitoffset, u_int32_t bitlen) +{ + int status; + + status = aml_bufferfield_io(AML_BUFFER_OUTPUT, &value, + origin, bitoffset, bitlen); + return (status); +} + +int +aml_region_handle_alloc(struct aml_environ *env, int regtype, u_int32_t flags, + u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen, + struct aml_region_handle *h) +{ + int state; + struct aml_name *pci_info; + + state = 0; + pci_info = NULL; + bzero(h, sizeof(struct aml_region_handle)); + + h->env = env; + h->regtype = regtype; + h->flags = flags; + h->baseaddr = baseaddr; + h->bitoffset = bitoffset; + h->bitlen = bitlen; + + switch (AML_FIELDFLAGS_ACCESSTYPE(flags)) { + case AML_FIELDFLAGS_ACCESS_ANYACC: + if (bitlen <= 8) { + h->unit = 1; + break; + } + if (bitlen <= 16) { + h->unit = 2; + break; + } + h->unit = 4; + break; + case AML_FIELDFLAGS_ACCESS_BYTEACC: + h->unit = 1; + break; + case AML_FIELDFLAGS_ACCESS_WORDACC: + h->unit = 2; + break; + case AML_FIELDFLAGS_ACCESS_DWORDACC: + h->unit = 4; + break; + default: + h->unit = 1; + break; + } + + h->addr = baseaddr + h->unit * ((bitoffset / 8) / h->unit); + h->bytelen = baseaddr + ((bitoffset + bitlen) / 8) - h->addr + + ((bitlen % 8) ? 1 : 0); + +#ifdef _KERNEL + switch (h->regtype) { + case AML_REGION_SYSMEM: + OsdMapMemory((void *)h->addr, h->bytelen, (void **)&h->vaddr); + break; + + case AML_REGION_PCICFG: + /* Obtain PCI bus number */ + pci_info = aml_search_name(env, "_BBN"); + if (pci_info == NULL || pci_info->property->type != aml_t_num) { + AML_DEBUGPRINT("Cannot locate _BBN. Using default 0\n"); + h->pci_bus = 0; + } else { + AML_DEBUGPRINT("found _BBN: %d\n", + pci_info->property->num.number); + h->pci_bus = pci_info->property->num.number & 0xff; + } + + /* Obtain device & function number */ + pci_info = aml_search_name(env, "_ADR"); + if (pci_info == NULL || pci_info->property->type != aml_t_num) { + printf("Cannot locate: _ADR\n"); + state = -1; + goto out; + } + h->pci_devfunc = pci_info->property->num.number; + + AML_DEBUGPRINT("[pci%d.%d]", h->pci_bus, h->pci_devfunc); + break; + + default: + break; + } + +out: +#endif /* _KERNEL */ + return (state); +} + +void +aml_region_handle_free(struct aml_region_handle *h) +{ +#ifdef _KERNEL + switch (h->regtype) { + case AML_REGION_SYSMEM: + OsdUnMapMemory((void *)h->vaddr, h->bytelen); + break; + + default: + break; + } +#endif /* _KERNEL */ +} + +static int +aml_region_io_simple(struct aml_environ *env, 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 i, state; + u_int32_t readval, value, offset, bytelen; + struct aml_region_handle handle; + + state = aml_region_handle_alloc(env, regtype, flags, + baseaddr, bitoffset, bitlen, &handle); + if (state == -1) { + goto out; + } + + readval = 0; + offset = bitoffset % (handle.unit * 8); + /* limitation of 32 bits alignment */ + bytelen = (handle.bytelen > 4) ? 4 : handle.bytelen; + + if (io == AML_REGION_INPUT || + AML_FIELDFLAGS_UPDATERULE(flags) == AML_FIELDFLAGS_UPDATE_PRESERVE) { + for (i = 0; i < bytelen; i += handle.unit) { + state = aml_region_read_simple(&handle, i, &value); + if (state == -1) { + goto out; + } + readval |= (value << (i * 8)); + } + AML_DEBUGPRINT("\t[%d:0x%x@0x%x:%d,%d]", + regtype, readval, handle.addr, offset, bitlen); + } + + switch (io) { + case AML_REGION_INPUT: + AML_DEBUGPRINT("\n"); + readval = aml_adjust_readvalue(flags, offset, bitlen, readval); + value = readval; + value = aml_region_prompt_read(&handle, value); + state = aml_region_prompt_update_value(readval, value, &handle); + if (state == -1) { + goto out; + } + + *valuep = value; + break; + case AML_REGION_OUTPUT: + value = *valuep; + value = aml_adjust_updatevalue(flags, offset, + bitlen, readval, value); + value = aml_region_prompt_write(&handle, value); + AML_DEBUGPRINT("\t->[%d:0x%x@0x%x:%d,%d]\n", regtype, value, + handle.addr, offset, bitlen); + for (i = 0; i < bytelen; i += handle.unit) { + state = aml_region_write_simple(&handle, i, value); + if (state == -1) { + goto out; + } + value = value >> (handle.unit * 8); + } + break; + } + + aml_region_handle_free(&handle); +out: + return (state); +} + +int +aml_region_io(struct aml_environ *env, int io, int regtype, + u_int32_t flags, u_int32_t *valuep, u_int32_t baseaddr, + u_int32_t bitoffset, u_int32_t bitlen) +{ + u_int32_t unit, offset; + u_int32_t offadj, bitadj; + u_int32_t value, readval; + int state, i; + + readval = 0; + state = 0; + unit = 4; /* limitation of 32 bits alignment */ + offset = bitoffset % (unit * 8); + offadj = 0; + bitadj = 0; + if (offset + bitlen > unit * 8) { + bitadj = bitlen - (unit * 8 - offset); + } + for (i = 0; i < offset + bitlen; i += unit * 8) { + value = (*valuep) >> offadj; + state = aml_region_io_simple(env, io, regtype, flags, + &value, baseaddr, bitoffset + offadj, bitlen - bitadj); + if (state == -1) { + goto out; + } + readval |= value << offadj; + bitadj = offadj = bitlen - bitadj; + } + *valuep = readval; + +out: + return (state); +} diff --git a/usr.sbin/acpidump/aml/aml_common.h b/usr.sbin/acpidump/aml/aml_common.h new file mode 100644 index 00000000000..5ea32924a4a --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_common.h @@ -0,0 +1,162 @@ +/* $OpenBSD: aml_common.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 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: aml_common.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_common.h,v 1.4 2000/10/02 08:58:47 iwasaki Exp $ + */ + +#ifndef _AML_COMMON_H_ +#define _AML_COMMON_H_ + +#include "acpidump.h" + +/* + * General Stuff + */ +#ifdef _KERNEL +#define AML_SYSABORT() do { \ + printf("aml: fatal errer at %s:%d\n", __FILE__, __LINE__); \ + panic("panic in AML interpreter!"); \ +} while(0) +#define AML_SYSASSERT(x) do { \ + if (!(x)) { \ + AML_SYSABORT(); \ + } \ +} while(0) +#define AML_SYSERRX(eval, fmt, args...) do { \ + printf(fmt, args); \ +} while(0) +#define AML_DEBUGGER(x, y) /* no debugger in kernel */ +#define AML_STALL(micro) OsdSleepUsec(micro) +#define AML_SLEEP(sec, milli) OsdSleep(sec, milli) +#else /* !_KERNEL */ +#define AML_SYSASSERT(x) assert(x) +#define AML_SYSABORT() abort() +#define AML_SYSERRX(eval, fmt, args...) errx(eval, fmt, args) +#define AML_DEBUGGER(x, y) aml_dbgr(x, y) +#define AML_STALL(micro) /* not required in userland */ +#define AML_SLEEP(sec, milli) /* not required in userland */ +#endif /* _KERNEL */ + +union aml_object; +struct aml_name; + +extern int aml_debug; + +#define AML_DEBUGPRINT(args...) do { \ + if (aml_debug) { \ + printf(args); \ + } \ +} while(0) + +void aml_showobject(union aml_object *); +void aml_showtree(struct aml_name *, int); +int aml_print_curname(struct aml_name *); +void aml_print_namestring(u_int8_t *); +void aml_print_indent(int); + +/* + * Reigion I/O Stuff for both kernel/userland. + */ + +/* + * Field Flags + */ +/* bit 0 -3: AccessType */ +#define AML_FIELDFLAGS_ACCESS_ANYACC 0x00 +#define AML_FIELDFLAGS_ACCESS_BYTEACC 0x01 +#define AML_FIELDFLAGS_ACCESS_WORDACC 0x02 +#define AML_FIELDFLAGS_ACCESS_DWORDACC 0x03 +#define AML_FIELDFLAGS_ACCESS_BLOCKACC 0x04 +#define AML_FIELDFLAGS_ACCESS_SMBSENDRECVACC 0x05 +#define AML_FIELDFLAGS_ACCESS_SMBQUICKACC 0x06 +#define AML_FIELDFLAGS_ACCESSTYPE(flags) (flags & 0x0f) +/* bit 4: LockRule */ +#define AML_FIELDFLAGS_LOCK_NOLOCK 0x00 +#define AML_FIELDFLAGS_LOCK_LOCK 0x10 +#define AML_FIELDFLAGS_LOCKRULE(flags) (flags & 0x10) +/* bit 5 - 6: UpdateRule */ +#define AML_FIELDFLAGS_UPDATE_PRESERVE 0x00 +#define AML_FIELDFLAGS_UPDATE_WRITEASONES 0x20 +#define AML_FIELDFLAGS_UPDATE_WRITEASZEROS 0x40 +#define AML_FIELDFLAGS_UPDATERULE(flags) (flags & 0x60) +/* bit 7: reserved (must be 0) */ + +#define AML_REGION_INPUT 0 +#define AML_REGION_OUTPUT 1 + +#define AML_REGION_SYSMEM 0 +#define AML_REGION_SYSIO 1 +#define AML_REGION_PCICFG 2 +#define AML_REGION_EMBCTL 3 +#define AML_REGION_SMBUS 4 + +struct aml_region_handle { + /* These are copies of values used on initialization */ + struct aml_environ *env; + int regtype; + u_int32_t flags; + u_int32_t baseaddr; + u_int32_t bitoffset; + u_int32_t bitlen; + + /* following is determined on initialization */ + vm_offset_t addr, bytelen; + u_int32_t unit; /* access unit in bytes */ + + /* region type dependant */ + vm_offset_t vaddr; /* SystemMemory */ + u_int32_t pci_bus, pci_devfunc; /* PCI_Config */ +}; + +u_int32_t aml_adjust_readvalue(u_int32_t, u_int32_t, u_int32_t, + u_int32_t); +u_int32_t aml_adjust_updatevalue(u_int32_t, u_int32_t, u_int32_t, + u_int32_t, u_int32_t); + +u_int32_t aml_bufferfield_read(u_int8_t *, u_int32_t, u_int32_t); +int aml_bufferfield_write(u_int32_t, u_int8_t *, + u_int32_t, u_int32_t); + +int aml_region_handle_alloc(struct aml_environ *, int, u_int32_t, + u_int32_t, u_int32_t, u_int32_t, + struct aml_region_handle *); +void aml_region_handle_free(struct aml_region_handle *); + +int aml_region_io(struct aml_environ *, int, int, + u_int32_t, u_int32_t *, u_int32_t, + u_int32_t, u_int32_t); +extern int aml_region_read_simple(struct aml_region_handle *, vm_offset_t, + u_int32_t *); +extern int aml_region_write_simple(struct aml_region_handle *, vm_offset_t, + u_int32_t); +extern u_int32_t aml_region_prompt_read(struct aml_region_handle *, + u_int32_t); +extern u_int32_t aml_region_prompt_write(struct aml_region_handle *, + u_int32_t); +extern int aml_region_prompt_update_value(u_int32_t, u_int32_t, + struct aml_region_handle *); +#endif /* !_AML_COMMON_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_env.h b/usr.sbin/acpidump/aml/aml_env.h new file mode 100644 index 00000000000..fe85f362458 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_env.h @@ -0,0 +1,47 @@ +/* $OpenBSD: aml_env.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Takanori Watanabe + * 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: aml_env.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_env.h,v 1.2 2000/11/09 06:24:45 iwasaki Exp $ + */ + +#ifndef _AML_ENV_H_ +#define _AML_ENV_H_ + +#include <aml/aml_name.h> +#include <aml/aml_obj.h> +#include <aml/aml_status.h> + +struct aml_environ { + u_int8_t *dp; + u_int8_t *end; + enum aml_status stat; + struct aml_name *curname; + struct aml_name tempname; + union aml_object tempobject; +}; + +#endif /* !_AML_ENV_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_evalobj.c b/usr.sbin/acpidump/aml/aml_evalobj.c new file mode 100644 index 00000000000..48109bd88c5 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_evalobj.c @@ -0,0 +1,436 @@ +/* $OpenBSD: aml_evalobj.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_evalobj.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_evalobj.c,v 1.4 2000/11/09 06:24:45 iwasaki Exp $ + */ + +#include <sys/types.h> + +#include <aml/aml_amlmem.h> +#include <aml/aml_common.h> +#include <aml/aml_env.h> +#include <aml/aml_evalobj.h> +#include <aml/aml_name.h> +#include <aml/aml_obj.h> +#include <aml/aml_parse.h> +#include <aml/aml_region.h> +#include <aml/aml_status.h> +#include <aml/aml_store.h> + +#ifndef _KERNEL +#include <sys/stat.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/systm.h> +#endif /* !_KERNEL */ + +static union aml_object *aml_eval_fieldobject(struct aml_environ *env, + struct aml_name *name); + +static union aml_object * +aml_eval_fieldobject(struct aml_environ *env, struct aml_name *name) +{ + int num; + struct aml_name *oname,*wname; + struct aml_field *field; + struct aml_opregion *or; + union aml_object tobj; + + num = 0; + /* CANNOT OCCUR! */ + if (name == NULL || name->property == NULL || + name->property->type != aml_t_field) { + printf("????\n"); + env->stat = aml_stat_panic; + return (NULL); + } + field = &name->property->field; + oname = env->curname; + if (field->bitlen > 32) { + env->tempobject.type = aml_t_regfield; + } else { + env->tempobject.type = aml_t_num; + } + env->curname = name; + if (field->f.ftype == f_t_field) { + wname = aml_search_name(env, field->f.fld.regname); + if (wname == NULL || wname->property == NULL || + wname->property->type != aml_t_opregion) { + AML_DEBUGPRINT("Inappropreate Type\n"); + env->stat = aml_stat_panic; + env->curname = oname; + return (NULL); + } + or = &wname->property->opregion; + if (env->tempobject.type == aml_t_regfield) { + env->tempobject.regfield.space = or->space; + env->tempobject.regfield.flags = field->flags; + env->tempobject.regfield.offset = or->offset; + env->tempobject.regfield.bitoffset = field->bitoffset; + env->tempobject.regfield.bitlen = field->bitlen; + } else { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = aml_region_read(env, + or->space, field->flags, or->offset, + field->bitoffset, field->bitlen); + AML_DEBUGPRINT("[read(%d, 0x%x)->0x%x]", + or->space, or->offset + field->bitoffset / 8, + env->tempobject.num.number); + } + } else if (field->f.ftype == f_t_index) { + wname = aml_search_name(env, field->f.ifld.indexname); + tobj.type = aml_t_num; + tobj.num.number = field->bitoffset / 8;/* AccessType Boundary */ + aml_store_to_name(env, &tobj, wname); + wname = aml_search_name(env, field->f.ifld.dataname); + num = aml_objtonum(env, aml_eval_name(env, wname)); + env->tempobject.type = aml_t_num; + env->tempobject.num.number = (num >> (field->bitoffset & 7)) & + ((1 << field->bitlen) - 1); + } + env->curname = oname; + return (&env->tempobject); +} + +union aml_object * +aml_eval_objref(struct aml_environ *env, union aml_object *obj) +{ + int offset; + union aml_object num1; + union aml_object *ref, *ret; + + ret = obj; + if (obj->objref.deref == 1) { + num1.type = aml_t_num; + offset = obj->objref.offset; + ref = obj->objref.ref; + if (ref == NULL) { + goto out; + } + switch (ref->type) { + case aml_t_package: + if (ref->package.elements > offset) { + ret = ref->package.objects[offset]; + } else { + num1.num.number = 0; + env->tempobject = num1; + ret = &env->tempobject; + } + break; + case aml_t_buffer: + if (ref->buffer.size > offset) { + num1.num.number = ref->buffer.data[offset] & 0xff; + } else { + num1.num.number = 0; + } + env->tempobject = num1; + ret = &env->tempobject; + break; + default: + break; + } + } + if (obj->objref.alias == 1) { + ret = aml_eval_name(env, obj->objref.nameref); + goto out; + } +out: + return (ret); +} + +/* + * Eval named object. + */ +union aml_object * +aml_eval_name(struct aml_environ *env, struct aml_name *aname) +{ + int argnum, i; + int num; + struct aml_name *tmp; + struct aml_environ *copy; + struct aml_local_stack *stack; + union aml_object *obj, *ret; + union aml_object *src; + + ret = NULL; + if (aname == NULL || aname->property == NULL) { + return (NULL); + } + if (env->stat == aml_stat_panic) { + return (NULL); + } + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + return (NULL); + } + ret = aname->property; + i = 0; +reevaluate: + if (i > 10) { + env->stat = aml_stat_panic; + printf("TOO MANY LOOP\n"); + ret = NULL; + goto out; + } + switch (aname->property->type) { + case aml_t_namestr: + tmp = aname; + aname = aml_search_name(env, aname->property->nstr.dp); + if (aname == NULL) { + aname = tmp; + } + i++; + goto reevaluate; + case aml_t_objref: + ret = aml_eval_objref(env, aname->property); + goto out; + case aml_t_num: + case aml_t_string: + case aml_t_buffer: + case aml_t_package: + case aml_t_debug: + ret = aname->property; + goto out; + case aml_t_field: + aml_free_objectcontent(&env->tempobject); + ret = aml_eval_fieldobject(env, aname); + goto out; + case aml_t_method: + aml_free_objectcontent(&env->tempobject); + argnum = aname->property->meth.argnum & 7; + *copy = *env; + copy->curname = aname; + copy->dp = aname->property->meth.from; + copy->end = aname->property->meth.to; + copy->stat = aml_stat_none; + stack = aml_local_stack_create(); + AML_DEBUGPRINT("("); + for (i = 0; i < argnum; i++) { + aml_local_stack_getArgX(stack, i)->property = + aml_copy_object(env, + aml_eval_name(env, + aml_parse_termobj(env, 0))); + if (i < argnum - 1) + AML_DEBUGPRINT(", "); + } + AML_DEBUGPRINT(")\n"); + aml_local_stack_push(stack); + if (env->stat == aml_stat_step) { + AML_DEBUGGER(env, copy); + } + tmp = aml_execute_method(copy); + obj = aml_eval_name(env, tmp); + if (copy->stat == aml_stat_panic) { + AML_DEBUGPRINT("PANIC OCCURED IN METHOD"); + env->stat = aml_stat_panic; + ret = NULL; + aml_local_stack_delete(aml_local_stack_pop()); + goto out; + } + if (aml_debug) { + aml_showobject(obj); + } + + if (tmp) + tmp->property = NULL; + aml_local_stack_delete(aml_local_stack_pop()); + if (obj) { + aml_create_local_object()->property = obj; + ret = obj; + } else { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = 0; + } + + goto out; + case aml_t_bufferfield: + aml_free_objectcontent(&env->tempobject); + if (aname->property->bfld.bitlen > 32) { + ret = aname->property; + } else { + src = aname->property; + num = aml_bufferfield_read(src->bfld.origin, + src->bfld.bitoffset, src->bfld.bitlen); + env->tempobject.type = aml_t_num; + env->tempobject.num.number = num; + ret = &env->tempobject; + } + goto out; + default: + AML_DEBUGPRINT("I eval the object that I should not eval, %s%d", + aname->name, aname->property->type); + AML_SYSABORT(); + ret = NULL; + goto out; + } +out: + memman_free(aml_memman, memid_aml_environ, copy); + return (ret); +} + +/* + * Eval named object but env variable is not required and return + * status of evaluation (success is zero). This function is assumed + * to be called by aml_apply_foreach_found_objects(). + * Note that no arguments are passed if object is a method. + */ + +int +aml_eval_name_simple(struct aml_name *name, va_list ap) +{ + struct aml_environ *env; + union aml_object *ret; + + if (name == NULL || name->property == NULL) { + return (1); + } + + env = memman_alloc(aml_memman, memid_aml_environ); + if (env == NULL) { + return (1); + } + bzero(env, sizeof(struct aml_environ)); + + aml_local_stack_push(aml_local_stack_create()); + + AML_DEBUGPRINT("Evaluating "); + aml_print_curname(name); + ret = aml_eval_name(env, name); + if (name->property->type != aml_t_method) { + AML_DEBUGPRINT("\n"); + if (aml_debug) { + aml_showobject(ret); + } + } + + aml_local_stack_delete(aml_local_stack_pop()); + + memman_free(aml_memman, memid_aml_environ, env); + return (0); +} + +int +aml_objtonum(struct aml_environ *env, union aml_object *obj) +{ + + if (obj != NULL && obj->type == aml_t_num) { + return (obj->num.number); + } else { + env->stat = aml_stat_panic; + return (-1); + } +} + +struct aml_name * +aml_execute_method(struct aml_environ *env) +{ + struct aml_name *name; + struct aml_name_group *newgrp; + + newgrp = aml_new_name_group(AML_NAME_GROUP_IN_METHOD); + + AML_DEBUGPRINT("["); + aml_print_curname(env->curname); + AML_DEBUGPRINT(" START]\n"); + + name = aml_parse_objectlist(env, 0); + AML_DEBUGPRINT("["); + aml_print_curname(env->curname); + AML_DEBUGPRINT(" END]\n"); + + aml_delete_name_group(newgrp); + return (name); +} + +union aml_object * +aml_invoke_method(struct aml_name *name, int argc, union aml_object *argv) +{ + int i; + struct aml_name *tmp; + struct aml_environ *env; + struct aml_local_stack *stack; + union aml_object *retval; + union aml_object *obj; + + retval = NULL; + env = memman_alloc(aml_memman, memid_aml_environ); + if (env == NULL) { + return (NULL); + } + bzero(env, sizeof(struct aml_environ)); + + if (name != NULL && name->property != NULL && + name->property->type == aml_t_method) { + env->curname = name; + env->dp = name->property->meth.from; + env->end = name->property->meth.to; + AML_DEBUGGER(env, env); + stack = aml_local_stack_create(); + for (i = 0; i < argc; i++) { + aml_local_stack_getArgX(stack, i)->property = + aml_alloc_object(argv[i].type, &argv[i]); + } + aml_local_stack_push(stack); + obj = aml_eval_name(env, tmp = aml_execute_method(env)); + if (aml_debug) { + aml_showtree(name, 0); + } + + if (tmp) + tmp->property = NULL; + aml_local_stack_delete(aml_local_stack_pop()); + if (obj) { + aml_create_local_object()->property = obj; + retval = obj; + } + } + memman_free(aml_memman, memid_aml_environ, env); + return (retval); +} + +union aml_object * +aml_invoke_method_by_name(char *method, int argc, union aml_object *argv) +{ + struct aml_name *name; + + name = aml_find_from_namespace(aml_get_rootname(), method); + if (name == NULL) { + return (NULL); + } + + return (aml_invoke_method(name, argc, argv)); +} diff --git a/usr.sbin/acpidump/aml/aml_evalobj.h b/usr.sbin/acpidump/aml/aml_evalobj.h new file mode 100644 index 00000000000..e951abbe2b5 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_evalobj.h @@ -0,0 +1,49 @@ +/* $OpenBSD: aml_evalobj.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Takanori Watanabe + * 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: aml_evalobj.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_evalobj.h,v 1.2 2000/09/20 22:53:39 iwasaki Exp $ + */ + +#ifndef _AML_EVALOBJ_H_ +#define _AML_EVALOBJ_H_ + +#include <stdarg.h> + +union aml_object *aml_eval_objref(struct aml_environ *, + union aml_object *); +union aml_object *aml_eval_name(struct aml_environ *, + struct aml_name *); +int aml_eval_name_simple(struct aml_name *, va_list); +int aml_objtonum(struct aml_environ *, + union aml_object *); +struct aml_name *aml_execute_method(struct aml_environ *); +union aml_object *aml_invoke_method(struct aml_name *, + int, union aml_object *); +union aml_object *aml_invoke_method_by_name(char *, + int, union aml_object *); + +#endif /* !_AML_EVALOBJ_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_memman.c b/usr.sbin/acpidump/aml/aml_memman.c new file mode 100644 index 00000000000..942251be2da --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_memman.c @@ -0,0 +1,477 @@ +/* $OpenBSD: aml_memman.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_memman.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_memman.c,v 1.2 2000/11/09 06:24:45 iwasaki Exp $ + */ + +/* + * Generic Memory Management + */ +#include <sys/types.h> +#include <aml/aml_memman.h> +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ +#endif +#ifndef _KERNEL +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#else /* _KERNEL */ +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/malloc.h> +MALLOC_DEFINE(M_MEMMAN, "memman", "Generic and Simple Memory Management"); +#endif /* !_KERNEL */ + +unsigned int memid_unkown = 255; + +static int manage_block(struct memman *memman, unsigned int id, + void *block, unsigned static_mem, + unsigned entries); +static int blockman_init(struct memman *memman, unsigned int id); +static void memman_flexsize_add_histogram(struct memman *memman, + size_t size, + int tolerance); +static int memman_comp_histogram_size(const void *a, + const void *b); +static void memman_sort_histogram_by_size(struct memman *memman); +static unsigned int memman_guess_memid(struct memman *memman, void *chunk); +static void memman_statistics_fixedsize(struct memman *memman); +static void memman_statistics_flexsize(struct memman *memman); + +static int +manage_block(struct memman *memman, unsigned int id, void *block, + unsigned static_mem, unsigned entries) +{ + unsigned int i; + size_t alloc_size; + void *tmp, *realblock; + struct memman_blockman *bmp; + struct memman_block *memblock; + struct memman_node *memnodes; + + bmp = &memman->blockman[id]; + alloc_size = MEMMAN_BLOCKNODE_SIZE(entries); + + if (static_mem) { + tmp = (void *)block; + realblock = (char *)block + alloc_size; + } else { + tmp = MEMMAN_SYSMALLOC(alloc_size); + if (!tmp) { + return (-1); + } + realblock = block; + + memman->allocated_mem += alloc_size; + memman->salloc_called++; + } + + memblock = (struct memman_block *)tmp; + memnodes = (struct memman_node *)((char *)tmp + sizeof(struct memman_block)); + + memblock->block = realblock; + memblock->static_mem = static_mem; + memblock->allocated = entries; + memblock->available = entries; + if (!static_mem) { + alloc_size += roundup(bmp->size * entries, ROUNDUP_UNIT); + } + memblock->allocated_mem = alloc_size; + LIST_INSERT_HEAD(&bmp->block_list, memblock, links); + + for (i = 0; i < entries; ++i) { + memnodes[i].node = ((char *)realblock + (i * (bmp->size))); + memnodes[i].memblock = memblock; + LIST_INSERT_HEAD(&bmp->free_node_list, &memnodes[i], links); + } + bmp->available = entries; + + return (0); +} + +static int +blockman_init(struct memman *memman, unsigned int id) +{ + int status; + struct memman_blockman *bmp; + + bmp = &memman->blockman[id]; + bmp->initialized = 1; + LIST_INIT(&bmp->block_list); + LIST_INIT(&bmp->free_node_list); + LIST_INIT(&bmp->occupied_node_list); + status = manage_block(memman, id, bmp->initial_block, + 1, MEMMAN_INITIAL_SIZE); + return (status); +} + +void * +memman_alloc(struct memman *memman, unsigned int id) +{ + size_t alloc_size; + void *chunk, *block; + struct memman_blockman *bmp; + struct memman_node *memnode; + + if (memman->max_memid <= id) { + printf("memman_alloc: invalid memory type id\n"); + return (NULL); + } + bmp = &memman->blockman[id]; + if (!bmp->initialized) { + if (blockman_init(memman, id)) { + goto malloc_fail; + } + } + memman->alloc_called++; + + if (bmp->available == 0) { + alloc_size = roundup(bmp->size * MEMMAN_INCR_SIZE, + ROUNDUP_UNIT); + block = MEMMAN_SYSMALLOC(alloc_size); + if (!block) { + goto malloc_fail; + } + memman->required_mem += bmp->size * MEMMAN_INCR_SIZE; + memman->allocated_mem += alloc_size; + memman->salloc_called++; + + if (manage_block(memman, id, block, 0, MEMMAN_INCR_SIZE)) { + goto malloc_fail; + } + } + memnode = LIST_FIRST(&bmp->free_node_list); + LIST_REMOVE(memnode, links); + chunk = memnode->node; + LIST_INSERT_HEAD(&bmp->occupied_node_list, memnode, links); + memnode->memblock->available--; + bmp->available--; + + return (chunk); + +malloc_fail: + printf("memman_alloc: could not allocate memory\n"); + return (NULL); +} + +static void +memman_flexsize_add_histogram(struct memman *memman, size_t size, + int tolerance) +{ + int i; + int gap; + + if (size == 0) { + return; + } + for (i = 0; i < memman->flex_mem_histogram_ptr; i++) { + gap = memman->flex_mem_histogram[i].mem_size - size; + if (gap >= (tolerance * -1) && gap <= tolerance) { + memman->flex_mem_histogram[i].count++; + if (memman->flex_mem_histogram[i].mem_size < size) { + memman->flex_mem_histogram[i].mem_size = size; + } + return; + } + } + + if (memman->flex_mem_histogram_ptr == MEMMAN_HISTOGRAM_SIZE) { + memman_flexsize_add_histogram(memman, size, tolerance + 1); + return; + } + i = memman->flex_mem_histogram_ptr; + memman->flex_mem_histogram[i].mem_size = size; + memman->flex_mem_histogram[i].count = 1; + memman->flex_mem_histogram_ptr++; +} + +static int +memman_comp_histogram_size(const void *a, const void *b) +{ + int delta; + + delta = ((const struct memman_histogram *)a)->mem_size - + ((const struct memman_histogram *)b)->mem_size; + return (delta); +} + +static void +memman_sort_histogram_by_size(struct memman *memman) +{ + qsort(memman->flex_mem_histogram, memman->flex_mem_histogram_ptr, + sizeof(struct memman_histogram), memman_comp_histogram_size); +} + +void * +memman_alloc_flexsize(struct memman *memman, size_t size) +{ + void *mem; + struct memman_flexmem_info *info; + + if (size == 0) { + return (NULL); + } + if ((mem = MEMMAN_SYSMALLOC(size)) != NULL) { /* XXX */ + + info = MEMMAN_SYSMALLOC(sizeof(struct memman_flexmem_info)); + if (info) { + if (!memman->flex_mem_initialized) { + LIST_INIT(&memman->flexmem_info_list); + bzero(memman->flex_mem_histogram, + sizeof(struct memman_histogram)); + memman->flex_mem_initialized = 1; + } + info->addr = mem; + info->mem_size = size; + LIST_INSERT_HEAD(&memman->flexmem_info_list, info, links); + } + memman->flex_alloc_called++; + memman->flex_salloc_called++; + memman->flex_required_mem += size; + memman->flex_allocated_mem += size; + if (memman->flex_mem_size_min == 0 || + memman->flex_mem_size_min > size) { + memman->flex_mem_size_min = size; + } + if (memman->flex_mem_size_max < size) { + memman->flex_mem_size_max = size; + } + if (memman->flex_peak_mem_usage < + (memman->flex_allocated_mem - memman->flex_reclaimed_mem)) { + memman->flex_peak_mem_usage = + (memman->flex_allocated_mem - memman->flex_reclaimed_mem); + } + memman_flexsize_add_histogram(memman, size, + memman->flex_mem_histogram_initial_tolerance); + } + return (mem); +} + +static unsigned int +memman_guess_memid(struct memman *memman, void *chunk) +{ + unsigned int id; + struct memman_blockman *bmp; + struct memman_node *memnode; + + for (id = 0; id < memman->max_memid; id++) { + bmp = &memman->blockman[id]; + if (!bmp->initialized) { + if (blockman_init(memman, id)) { + printf("memman_free: could not initialized\n"); + } + } + LIST_FOREACH(memnode, &bmp->occupied_node_list, links) { + if (memnode->node == chunk) { + return (id); /* got it! */ + } + } + } + return (memid_unkown); /* gave up */ +} + +void +memman_free(struct memman *memman, unsigned int memid, void *chunk) +{ + unsigned int id; + unsigned found; + void *block; + struct memman_blockman *bmp; + struct memman_block *memblock; + struct memman_node *memnode; + + id = memid; + if (memid == memid_unkown) { + id = memman_guess_memid(memman, chunk); + } + if (memman->max_memid <= id) { + printf("memman_free: invalid memory type id\n"); + MEMMAN_SYSABORT(); + return; + } + bmp = &memman->blockman[id]; + if (!bmp->initialized) { + if (blockman_init(memman, id)) { + printf("memman_free: could not initialized\n"); + } + } + found = 0; + LIST_FOREACH(memnode, &bmp->occupied_node_list, links) { + if (memnode->node == chunk) { + found = 1; + break; + } + } + if (!found) { + printf("memman_free: invalid address\n"); + return; + } + memman->free_called++; + + LIST_REMOVE(memnode, links); + memblock = memnode->memblock; + memblock->available++; + LIST_INSERT_HEAD(&bmp->free_node_list, memnode, links); + bmp->available++; + + if (!memblock->static_mem && + memblock->available == memblock->allocated) { + LIST_FOREACH(memnode, &bmp->free_node_list, links) { + if (memnode->memblock != memblock) { + continue; + } + LIST_REMOVE(memnode, links); + bmp->available--; + } + block = memblock->block; + MEMMAN_SYSFREE(block); + memman->sfree_called++; + + LIST_REMOVE(memblock, links); + memman->sfree_called++; + memman->reclaimed_mem += memblock->allocated_mem; + MEMMAN_SYSFREE(memblock); + } +} + +void +memman_free_flexsize(struct memman *memman, void *chunk) +{ + struct memman_flexmem_info *info; + + LIST_FOREACH(info, &memman->flexmem_info_list, links) { + if (info->addr == chunk) { + memman->flex_reclaimed_mem += info->mem_size; + LIST_REMOVE(info, links); + MEMMAN_SYSFREE(info); + break; + } + } + /* XXX */ + memman->flex_free_called++; + memman->flex_sfree_called++; + MEMMAN_SYSFREE(chunk); +} + +void +memman_freeall(struct memman *memman) +{ + int id; + void *chunk; + struct memman_blockman *bmp; + struct memman_node *memnode; + struct memman_block *memblock; + struct memman_flexmem_info *info; + + for (id = 0; id < memman->max_memid; id++) { + bmp = &memman->blockman[id]; + + while ((memnode = LIST_FIRST(&bmp->occupied_node_list))) { + chunk = memnode->node; + printf("memman_freeall: fixed size (id = %d)\n", id); + memman_free(memman, id, chunk); + } + while ((memblock = LIST_FIRST(&bmp->block_list))) { + LIST_REMOVE(memblock, links); + if (!memblock->static_mem) { + memman->sfree_called++; + memman->reclaimed_mem += memblock->allocated_mem; + MEMMAN_SYSFREE(memblock); + } + } + bmp->initialized = 0; + } + + LIST_FOREACH(info, &memman->flexmem_info_list, links) { + printf("memman_freeall: flex size (size = %d, addr = %p)\n", + info->mem_size, info->addr); + memman_free_flexsize(memman, info->addr); + } +} + +static void +memman_statistics_fixedsize(struct memman *memman) +{ + printf(" fixed size memory blocks\n"); + printf(" alloc(): %d times\n", memman->alloc_called); + printf(" system malloc(): %d times\n", memman->salloc_called); + printf(" free(): %d times\n", memman->free_called); + printf(" system free(): %d times\n", memman->sfree_called); + printf(" required memory: %d bytes\n", memman->required_mem); + printf(" allocated memory: %d bytes\n", memman->allocated_mem); + printf(" reclaimed memory: %d bytes\n", memman->reclaimed_mem); +} + +static void +memman_statistics_flexsize(struct memman *memman) +{ + int i; + + printf(" flexible size memory blocks\n"); + printf(" alloc(): %d times\n", memman->flex_alloc_called); + printf(" system malloc(): %d times\n", memman->flex_salloc_called); + printf(" free(): %d times\n", memman->flex_free_called); + printf(" system free(): %d times\n", memman->flex_sfree_called); + printf(" required memory: %d bytes\n", memman->flex_required_mem); + printf(" allocated memory: %d bytes\n", memman->flex_allocated_mem); + printf(" reclaimed memory: %d bytes\n", memman->flex_reclaimed_mem); + printf(" peak memory usage: %d bytes\n", memman->flex_peak_mem_usage); + printf(" min memory size: %d bytes\n", memman->flex_mem_size_min); + printf(" max memory size: %d bytes\n", memman->flex_mem_size_max); + printf(" avg memory size: %d bytes\n", + (memman->flex_alloc_called) ? + memman->flex_allocated_mem / memman->flex_alloc_called : 0); + + printf(" memory size histogram (%d entries):\n", + memman->flex_mem_histogram_ptr); + printf(" size count\n"); + memman_sort_histogram_by_size(memman); + for (i = 0; i < memman->flex_mem_histogram_ptr; i++) { + printf(" %d %d\n", + memman->flex_mem_histogram[i].mem_size, + memman->flex_mem_histogram[i].count); + } +} + +void +memman_statistics(struct memman *memman) +{ + printf("memman: reporting statistics\n"); + memman_statistics_fixedsize(memman); + memman_statistics_flexsize(memman); +} + +size_t +memman_memid2size(struct memman *memman, unsigned int id) +{ + if (memman->max_memid <= id) { + printf("memman_alloc: invalid memory type id\n"); + return (0); + } + return (memman->blockman[id].size); +} diff --git a/usr.sbin/acpidump/aml/aml_memman.h b/usr.sbin/acpidump/aml/aml_memman.h new file mode 100644 index 00000000000..fce68328e72 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_memman.h @@ -0,0 +1,172 @@ +/* $OpenBSD: aml_memman.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_memman.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_memman.h,v 1.1 2000/08/24 09:33:08 takawata Exp $ + */ + +#ifndef _MEMMAN_H_ +#define _MEMMAN_H_ + +/* + * Generic Memory Management + */ + +#include <sys/types.h> +#include <sys/queue.h> + +/* memory block */ +struct memman_block { + LIST_ENTRY(memman_block) links; + void *block; + unsigned static_mem; /* static memory or not */ + unsigned int allocated; /* number of allocated chunks */ + unsigned int available; /* number of available chunks */ + unsigned int allocated_mem; /* block + misc (in bytes) */ + +}__attribute__((packed)); + +LIST_HEAD(memman_block_list, memman_block); + +/* memory node in block */ +struct memman_node { + LIST_ENTRY(memman_node) links; + void *node; + struct memman_block *memblock; +}__attribute__((packed)); + +LIST_HEAD(memman_node_list, memman_node); + +/* memory type id */ +extern unsigned int memid_unkown; + +/* memory block manager */ +struct memman_blockman { + unsigned int size; /* size of chunk */ + unsigned int available; /* total # of available chunks */ + void *initial_block; /* initial memory storage */ + unsigned initialized; /* initialized or not */ + + struct memman_block_list block_list; + struct memman_node_list free_node_list; + struct memman_node_list occupied_node_list; +}; + +/* memory size histogram */ +#define MEMMAN_HISTOGRAM_SIZE 20 +struct memman_histogram { + int mem_size; + int count; +}; + +/* flex size memory allocation info */ +struct memman_flexmem_info { + LIST_ENTRY(memman_flexmem_info) links; + void *addr; + size_t mem_size; +}__attribute__((packed)); + +LIST_HEAD(memman_flexmem_info_list, memman_flexmem_info); + +/* memory manager */ +struct memman { + struct memman_blockman *blockman; + unsigned int max_memid; /* max number of valid memid */ + + /* fixed size memory blocks */ + unsigned int alloc_called; /* memman_alloc() calling */ + unsigned int free_called; /* memman_free() calling */ + unsigned int salloc_called; /* malloc() calling */ + unsigned int sfree_called; /* free() calling */ + size_t required_mem; /* total required memory (in bytes) */ + size_t allocated_mem; /* total malloc()ed memory */ + size_t reclaimed_mem; /* total free()ed memory */ + /* flex size memory blocks */ + unsigned int flex_alloc_called; /* memman_alloc_flexsize() calling */ + unsigned int flex_free_called; /* memman_free_flexsize() calling */ + unsigned int flex_salloc_called;/* malloc() calling */ + unsigned int flex_sfree_called; /* free() calling */ + size_t flex_required_mem; /* total required memory (in bytes) */ + size_t flex_allocated_mem;/* total malloc()ed memory */ + size_t flex_reclaimed_mem;/* total free()ed memory */ + size_t flex_mem_size_min; /* min size of allocated memory */ + size_t flex_mem_size_max; /* max size of allocated memory */ + size_t flex_peak_mem_usage;/* memory usage at a peak period */ + + /* stuff for more detailed statistical information */ + struct memman_histogram *flex_mem_histogram; + unsigned int flex_mem_histogram_ptr; + int flex_mem_histogram_initial_tolerance; + unsigned flex_mem_initialized; + struct memman_flexmem_info_list flexmem_info_list; +}; + +#define MEMMAN_BLOCKNODE_SIZE(entries) sizeof(struct memman_block) + \ + sizeof(struct memman_node) * entries + +#ifndef ROUNDUP_UNIT +#define ROUNDUP_UNIT 4 +#endif + +#if !defined(MEMMAN_INITIAL_SIZE) || MEMMAN_INITIAL_SIZE < 2048 +#define MEMMAN_INITIAL_SIZE 2048 +#endif + +#if !defined(MEMMAN_INCR_SIZE) || MEMMAN_INCR_SIZE < 512 +#define MEMMAN_INCR_SIZE 512 +#endif + +#define MEMMAN_INITIALSTORAGE_DESC(type, name) \ +static struct { \ + char blocknodes[MEMMAN_BLOCKNODE_SIZE(MEMMAN_INITIAL_SIZE)]; \ + type realblock[MEMMAN_INITIAL_SIZE]; \ +} name + +#define MEMMAN_MEMBLOCK_DESC(size, initial_storage) \ + { size, MEMMAN_INITIAL_SIZE, &initial_storage, 0 } + +#define MEMMAN_MEMMANAGER_DESC(blockman, max_memid, histogram, tolerance) \ + { blockman, max_memid, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, histogram, 0, tolerance, 0} + +void *memman_alloc(struct memman *, unsigned int); +void *memman_alloc_flexsize(struct memman *, size_t); +void memman_free(struct memman *, unsigned int, void *); +void memman_free_flexsize(struct memman *, void *); +void memman_freeall(struct memman *); +void memman_statistics(struct memman *); +size_t memman_memid2size(struct memman *, unsigned int); + +#ifdef _KERNEL +#define MEMMAN_SYSMALLOC(size) malloc(size, M_MEMMAN, M_WAITOK) +#define MEMMAN_SYSFREE(ptr) free(ptr, M_MEMMAN) +#define MEMMAN_SYSABORT() /* no abort in kernel */ +#else /* !_KERNEL */ +#define MEMMAN_SYSMALLOC(size) malloc(size) +#define MEMMAN_SYSFREE(ptr) free(ptr) +#define MEMMAN_SYSABORT() abort() +#endif /* _KERNEL */ +#endif /* !_MEMMAN_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_name.c b/usr.sbin/acpidump/aml/aml_name.c new file mode 100644 index 00000000000..b41698d7e2c --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_name.c @@ -0,0 +1,481 @@ +/* $OpenBSD: aml_name.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Takanori Watanabe + * Copyright (c) 1999, 2000 Yasuo Yokoyama + * 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: aml_name.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_name.c,v 1.3 2000/11/09 06:24:45 iwasaki Exp $ + */ +#include <sys/types.h> + +#include <aml/aml_amlmem.h> +#include <aml/aml_common.h> +#include <aml/aml_env.h> +#include <aml/aml_name.h> + +#ifndef _KERNEL +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/systm.h> +#endif /* !_KERNEL */ + +static struct aml_name *aml_find_name(struct aml_name *, char *); +static struct aml_name *aml_new_name(struct aml_name *, char *); +static void aml_delete_name(struct aml_name *); + +static struct aml_name rootname = {"\\", NULL, NULL, NULL, NULL, NULL}; + +static struct aml_name_group root_group = { + AML_NAME_GROUP_ROOT, + &rootname, + NULL +}; + +struct aml_name_group *name_group_list = &root_group; +struct aml_local_stack *stack_top = NULL; + +struct aml_name * +aml_get_rootname() +{ + + return (&rootname); +} + +static struct aml_name * +aml_find_name(struct aml_name *parent, char *name) +{ + struct aml_name *result; + + if (!parent) + parent = &rootname; + for (result = parent->child; result; result = result->brother) + if (!strncmp(result->name, name, 4)) + break; + return (result); +} + +/* + * Parse given namesppace expression and find a first matched object + * under given level of the tree by depth first search. + */ + +struct aml_name * +aml_find_from_namespace(struct aml_name *parent, char *name) +{ + char *ptr; + int len; + struct aml_name *result; + + ptr = name; + if (!parent) + parent = &rootname; + + if (ptr[0] == '\\') { + ptr++; + parent = &rootname; + } + for (len = 0; ptr[len] != '.' && ptr[len] != '\0'; len++) + ; + + for (result = parent->child; result; result = result->brother) { + if (!strncmp(result->name, ptr, len)) { + if (ptr[len] == '\0' || ptr[len + 1] == '\0') { + return (result); + } + ptr += len; + if (ptr[0] != '.') { + return (NULL); + } + ptr++; + return (aml_find_from_namespace(result, ptr)); + } + } + + return (NULL); +} + +static void +_aml_apply_foreach_found_objects(struct aml_name *parent, char *name, + int len, int shallow, int (*func)(struct aml_name *, va_list), va_list ap) +{ + struct aml_name *child, *ptr; + + child = ptr = NULL; + + /* function to apply must be specified */ + if (func == NULL) { + return; + } + + for (child = parent->child; child; child = child->brother) { + if (!strncmp(child->name, name, len)) { + /* if function call was failed, stop searching */ + if (func(child, ap) != 0) { + return; + } + } + } + + if (shallow == 1) { + return; + } + + for (ptr = parent->child; ptr; ptr = ptr->brother) { + /* do more searching */ + _aml_apply_foreach_found_objects(ptr, name, len, 0, func, ap); + } +} + +/* + * Find named objects as many as possible under given level of + * namespace, and apply given callback function for each + * named objects found. If the callback function returns non-zero + * value, then the search terminates immediately. + * Note that object name expression is used as forward substring match, + * not exact match. The name expression "_L" will match for objects + * which have name starting with "_L" such as "\_SB_.LID_._LID" and + * "\_GPE._L00" and so on. The name expression can include parent object + * name in it like "\_GPE._L". In this case, GPE X level wake handlers + * will be found under "\_GPE" in shallow level. + */ + +void +aml_apply_foreach_found_objects(struct aml_name *start, char *name, + int (*func)(struct aml_name *, va_list), ...) +{ + int i, len, has_dot, last_is_dot, shallow; + struct aml_name *child, *parent; + va_list ap; + + shallow = 0; + if (start == NULL) { + parent = &rootname; + } else { + parent = start; + } + if (name[0] == '\\') { + name++; + parent = &rootname; + shallow = 1; + } + + len = strlen(name); + last_is_dot = 0; + /* the last dot should be ignored */ + if (len > 0 && name[len - 1] == '.') { + len--; + last_is_dot = 1; + } + + has_dot = 0; + for (i = 0; i < len - 1; i++) { + if (name[i] == '.') { + has_dot = 1; + break; + } + } + + /* try to parse expression and find any matched object. */ + if (has_dot == 1) { + child = aml_find_from_namespace(parent, name); + if (child == NULL) { + return; + } + + /* + * we have at least one object matched, search all objects + * under upper level of the found object. + */ + parent = child->parent; + + /* find the last `.' */ + for (name = name + len - 1; *name != '.'; name--) + ; + name++; + len = strlen(name) - last_is_dot; + shallow = 1; + } + + if (len > 4) { + return; + } + + va_start(ap, func); + _aml_apply_foreach_found_objects(parent, name, len, shallow, func, ap); + va_end(ap); +} + +struct aml_name_group * +aml_new_name_group(int id) +{ + struct aml_name_group *result; + + result = memman_alloc(aml_memman, memid_aml_name_group); + result->id = id; + result->head = NULL; + result->next = name_group_list; + name_group_list = result; + return (result); +} + +void +aml_delete_name_group(struct aml_name_group *target) +{ + struct aml_name_group *previous; + + previous = name_group_list; + if (previous == target) + name_group_list = target->next; + else { + while (previous && previous->next != target) + previous = previous->next; + if (previous) + previous->next = target->next; + } + target->next = NULL; + if (target->head) + aml_delete_name(target->head); + memman_free(aml_memman, memid_aml_name_group, target); +} + +static struct aml_name * +aml_new_name(struct aml_name *parent, char *name) +{ + struct aml_name *newname; + + if ((newname = aml_find_name(parent, name)) != NULL) + return (newname); + + newname = memman_alloc(aml_memman, memid_aml_name); + strncpy(newname->name, name, 4); + newname->parent = parent; + newname->child = NULL; + newname->property = NULL; + if (parent->child) + newname->brother = parent->child; + else + newname->brother = NULL; + parent->child = newname; + + newname->chain = name_group_list->head; + name_group_list->head = newname; + + return (newname); +} + +/* + * NOTE: + * aml_delete_name() doesn't maintain aml_name_group::{head,tail}. + */ +static void +aml_delete_name(struct aml_name *target) +{ + struct aml_name *next; + struct aml_name *ptr; + + for (; target; target = next) { + next = target->chain; + if (target->child) { + target->chain = NULL; + continue; + } + if (target->brother) { + if (target->parent) { + if (target->parent->child == target) { + target->parent->child = target->brother; + } else { + ptr = target->parent->child; + while (ptr && ptr->brother != target) + ptr = ptr->brother; + if (ptr) + ptr->brother = target->brother; + } + target->brother = NULL; + } + } else if (target->parent) { + target->parent->child = NULL; + } + aml_free_object(&target->property); + memman_free(aml_memman, memid_aml_name, target); + } +} + +#define AML_SEARCH_NAME 0 +#define AML_CREATE_NAME 1 +static struct aml_name *aml_nameman(struct aml_environ *, u_int8_t *, int); + +struct aml_name * +aml_search_name(struct aml_environ *env, u_int8_t *dp) +{ + + return (aml_nameman(env, dp, AML_SEARCH_NAME)); +} + +struct aml_name * +aml_create_name(struct aml_environ *env, u_int8_t *dp) +{ + + return (aml_nameman(env, dp, AML_CREATE_NAME)); +} + +static struct aml_name * +aml_nameman(struct aml_environ *env, u_int8_t *dp, int flag) +{ + int segcount; + int i; + struct aml_name *newname, *curname; + struct aml_name *(*searchfunc) (struct aml_name *, char *); + +#define CREATECHECK() do { \ + if (newname == NULL) { \ + AML_DEBUGPRINT("ERROR CANNOT FIND NAME\n"); \ + env->stat = aml_stat_panic; \ + return (NULL); \ + } \ +} while(0) + + searchfunc = (flag == AML_CREATE_NAME) ? aml_new_name : aml_find_name; + newname = env->curname; + if (dp[0] == '\\') { + newname = &rootname; + dp++; + } else if (dp[0] == '^') { + while (dp[0] == '^') { + newname = newname->parent; + CREATECHECK(); + dp++; + } + } + if (dp[0] == 0x00) { /* NullName */ + dp++; + } else if (dp[0] == 0x2e) { /* DualNamePrefix */ + newname = (*searchfunc) (newname, dp + 1); + CREATECHECK(); + newname = (*searchfunc) (newname, dp + 5); + CREATECHECK(); + } else if (dp[0] == 0x2f) { /* MultiNamePrefix */ + segcount = dp[1]; + for (i = 0, dp += 2; i < segcount; i++, dp += 4) { + newname = (*searchfunc) (newname, dp); + CREATECHECK(); + } + } else if (flag == AML_CREATE_NAME) { /* NameSeg */ + newname = aml_new_name(newname, dp); + CREATECHECK(); + } else { + curname = newname; + for (;;) { + newname = aml_find_name(curname, dp); + if (newname != NULL) + break; + if (curname == &rootname) + break; + curname = curname->parent; + } + } + return (newname); +} + +#undef CREATECHECK + +struct aml_local_stack * +aml_local_stack_create() +{ + struct aml_local_stack *result; + + result = memman_alloc(aml_memman, memid_aml_local_stack); + memset(result, 0, sizeof(struct aml_local_stack)); + return (result); +} + +void +aml_local_stack_push(struct aml_local_stack *stack) +{ + + stack->next = stack_top; + stack_top = stack; +} + +struct aml_local_stack * +aml_local_stack_pop() +{ + struct aml_local_stack *result; + + result = stack_top; + stack_top = result->next; + result->next = NULL; + return (result); +} + +void +aml_local_stack_delete(struct aml_local_stack *stack) +{ + int i; + + for (i = 0; i < 8; i++) + aml_free_object(&stack->localvalue[i].property); + for (i = 0; i < 7; i++) + aml_free_object(&stack->argumentvalue[i].property); + aml_delete_name(stack->temporary); + memman_free(aml_memman, memid_aml_local_stack, stack); +} + +struct aml_name * +aml_local_stack_getLocalX(int index) +{ + + if (stack_top == NULL) + return (NULL); + return (&stack_top->localvalue[index]); +} + +struct aml_name * +aml_local_stack_getArgX(struct aml_local_stack *stack, int index) +{ + + if (!stack) + stack = stack_top; + if (stack == NULL) + return (NULL); + return (&stack->argumentvalue[index]); +} + +struct aml_name * +aml_create_local_object() +{ + struct aml_name *result; + + result = memman_alloc(aml_memman, memid_aml_name); + result->child = result->brother = result->parent = NULL; + result->property = NULL; + result->chain = stack_top->temporary; + stack_top->temporary = result; + return (result); +} diff --git a/usr.sbin/acpidump/aml/aml_name.h b/usr.sbin/acpidump/aml/aml_name.h new file mode 100644 index 00000000000..87b89ba1c0e --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_name.h @@ -0,0 +1,89 @@ +/* $OpenBSD: aml_name.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Takanori Watanabe + * Copyright (c) 1999, 2000 Yasuo Yokoyama + * 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: aml_name.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_name.h,v 1.2 2000/11/09 06:24:45 iwasaki Exp $ + */ + +#ifndef _AML_NAME_H_ +#define _AML_NAME_H_ + + +#include <aml/aml_obj.h> +#include <stdarg.h> + +struct aml_name { + char name[4]; + union aml_object *property; + struct aml_name *parent; + struct aml_name *brother; + struct aml_name *child; + struct aml_name *chain; +}; + +#define AML_NAME_GROUP_ROOT 0 +#define AML_NAME_GROUP_OS_DEFINED 1 +#define AML_NAME_GROUP_IN_METHOD 2 + +struct aml_name_group { + int id; /* DSDT address or DBHANDLE */ + struct aml_name *head; + struct aml_name_group *next; +}; + +struct aml_local_stack { + struct aml_name localvalue[8]; + struct aml_name argumentvalue[7]; + struct aml_name *temporary; + struct aml_local_stack *next; +}; + +/* forward declarement */ +struct aml_envrion; + +struct aml_name *aml_get_rootname(void); +struct aml_name_group *aml_new_name_group(int); +void aml_delete_name_group(struct aml_name_group *); + +struct aml_name *aml_find_from_namespace(struct aml_name *, char *); +void aml_apply_foreach_found_objects(struct aml_name *, + char *, int (*)(struct aml_name *, va_list), ...); +struct aml_name *aml_search_name(struct aml_environ *, u_int8_t *); +struct aml_name *aml_create_name(struct aml_environ *, u_int8_t *); + +struct aml_local_stack *aml_local_stack_create(void); +void aml_local_stack_push(struct aml_local_stack *); +struct aml_local_stack *aml_local_stack_pop(void); +void aml_local_stack_delete(struct aml_local_stack *); +struct aml_name *aml_local_stack_getLocalX(int); +struct aml_name *aml_local_stack_getArgX(struct aml_local_stack *, int); +struct aml_name *aml_create_local_object(void); + +extern struct aml_name_group *name_group_list; + +#endif /* !_AML_NAME_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_obj.c b/usr.sbin/acpidump/aml/aml_obj.c new file mode 100644 index 00000000000..e1de8967d48 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_obj.c @@ -0,0 +1,265 @@ +/* $OpenBSD: aml_obj.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_obj.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_obj.c,v 1.3 2000/11/09 06:24:45 iwasaki Exp $ + */ + +#include <sys/types.h> + +#include <aml/aml_amlmem.h> +#include <aml/aml_env.h> +#include <aml/aml_name.h> +#include <aml/aml_obj.h> +#include <aml/aml_status.h> +#include <aml/aml_store.h> + +#ifndef _KERNEL +#include <sys/stat.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#else /* _KERNEL */ +#include <sys/systm.h> +#endif /* !_KERNEL */ + +union aml_object * +aml_copy_object(struct aml_environ *env, union aml_object *orig) +{ + int i; + union aml_object *ret; + + if (orig == NULL) + return (NULL); + switch (orig->type) { + case aml_t_regfield: + ret = aml_alloc_object(aml_t_buffer, 0); + ret->buffer.size = (orig->regfield.bitlen / 8) + + ((orig->regfield.bitlen % 8) ? 1 : 0); + if (ret->buffer.size == 0) { + goto out; + } + ret->buffer.data = memman_alloc_flexsize(aml_memman, ret->buffer.size); + aml_store_to_object(env, orig, ret); + break; + + default: + ret = aml_alloc_object(0, orig); + break; + } + + if (1 || orig != &env->tempobject) { /* XXX */ + if (orig->type == aml_t_buffer) { + if (orig->buffer.size == 0) { + goto out; + } + ret->buffer.data = memman_alloc_flexsize(aml_memman, + orig->buffer.size); + bcopy(orig->buffer.data, ret->buffer.data, orig->buffer.size); + } else if (orig->type == aml_t_package) { + if (ret->package.elements == 0) { + goto out; + } + ret->package.objects = memman_alloc_flexsize(aml_memman, + ret->package.elements * sizeof(union aml_object *)); + for (i = 0; i < ret->package.elements; i++) { + ret->package.objects[i] = aml_copy_object(env, orig->package.objects[i]); + } + } else if (orig->type == aml_t_string && orig->str.needfree != 0) { + ret->str.string = memman_alloc_flexsize(aml_memman, + strlen(orig->str.string) + 1); + strcpy(orig->str.string, ret->str.string); + } else if (orig->type == aml_t_num) { + ret->num.constant = 0; + } + } else { + printf("%s:%d\n", __FILE__, __LINE__); + env->tempobject.type = aml_t_null; + } +out: + return ret; +} + +/* + * This function have two function: copy or allocate. if orig != NULL, + * orig is duplicated. + */ + +union aml_object * +aml_alloc_object(enum aml_objtype type, union aml_object *orig) +{ + unsigned int memid; + union aml_object *ret; + + if (orig != NULL) { + type = orig->type; + } + switch (type) { + case aml_t_namestr: + memid = memid_aml_namestr; + break; + case aml_t_buffer: + memid = memid_aml_buffer; + break; + case aml_t_string: + memid = memid_aml_string; + break; + case aml_t_bufferfield: + memid = memid_aml_bufferfield; + break; + case aml_t_package: + memid = memid_aml_package; + break; + case aml_t_num: + memid = memid_aml_num; + break; + case aml_t_powerres: + memid = memid_aml_powerres; + break; + case aml_t_opregion: + memid = memid_aml_opregion; + break; + case aml_t_method: + memid = memid_aml_method; + break; + case aml_t_processor: + memid = memid_aml_processor; + break; + case aml_t_field: + memid = memid_aml_field; + break; + case aml_t_mutex: + memid = memid_aml_mutex; + break; + case aml_t_device: + memid = memid_aml_objtype; + break; + case aml_t_objref: + memid = memid_aml_objref; + break; + default: + memid = memid_aml_objtype; + break; + } + ret = memman_alloc(aml_memman, memid); + ret->type = type; + + if (orig != NULL) { + bcopy(orig, ret, memman_memid2size(aml_memman, memid)); + } + return (ret); +} + +void +aml_free_objectcontent(union aml_object *obj) +{ + int i; + + if (obj->type == aml_t_buffer && obj->buffer.data != NULL) { + memman_free_flexsize(aml_memman, obj->buffer.data); + obj->buffer.data = NULL; + } + if (obj->type == aml_t_string && obj->str.string != NULL) { + if (obj->str.needfree != 0) { + memman_free_flexsize(aml_memman, obj->str.string); + obj->str.string = NULL; + } + } + if (obj->type == aml_t_package && obj->package.objects != NULL) { + for (i = 0; i < obj->package.elements; i++) { + aml_free_object(&obj->package.objects[i]); + } + memman_free_flexsize(aml_memman, obj->package.objects); + obj->package.objects = NULL; + } +} + +void +aml_free_object(union aml_object **obj) +{ + union aml_object *body; + + body = *obj; + if (body == NULL) { + return; + } + aml_free_objectcontent(*obj); + memman_free(aml_memman, memid_unkown, *obj); + *obj = NULL; +} + +void +aml_realloc_object(union aml_object *obj, int size) +{ + int i; + enum aml_objtype type; + union aml_object tmp; + + type = obj->type; + switch (type) { + case aml_t_buffer: + if (obj->buffer.size >= size) { + return; + } + tmp.buffer.size = size; + tmp.buffer.data = memman_alloc_flexsize(aml_memman, size); + bzero(tmp.buffer.data, size); + bcopy(obj->buffer.data, tmp.buffer.data, obj->buffer.size); + aml_free_objectcontent(obj); + *obj = tmp; + break; + case aml_t_string: + if (strlen(obj->str.string) >= size) { + return; + } + tmp.str.string = memman_alloc_flexsize(aml_memman, size + 1); + strcpy(tmp.str.string, obj->str.string); + aml_free_objectcontent(obj); + *obj = tmp; + break; + case aml_t_package: + if (obj->package.elements >= size) { + return; + } + tmp.package.objects = memman_alloc_flexsize(aml_memman, + size * sizeof(union aml_object *)); + bzero(tmp.package.objects, size * sizeof(union aml_object *)); + for (i = 0; i < obj->package.elements; i++) { + tmp.package.objects[i] = obj->package.objects[i]; + } + memman_free_flexsize(aml_memman, obj->package.objects); + obj->package.objects = tmp.package.objects; + break; + default: + break; + } +} diff --git a/usr.sbin/acpidump/aml/aml_obj.h b/usr.sbin/acpidump/aml/aml_obj.h new file mode 100644 index 00000000000..c38404184ed --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_obj.h @@ -0,0 +1,232 @@ +/* $OpenBSD: aml_obj.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_obj.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_obj.h,v 1.1 2000/08/24 09:33:08 takawata Exp $ + */ + +#ifndef _AML_OBJ_H_ +#define _AML_OBJ_H_ + +#include <sys/queue.h> + +struct aml_environ; +enum aml_objtype { + aml_t_namestr = -3, + aml_t_regfield, + aml_t_objref, + aml_t_null = 0, + aml_t_num, + aml_t_string, + aml_t_buffer, + aml_t_package, + aml_t_device, + aml_t_field, + aml_t_event, + aml_t_method, + aml_t_mutex, + aml_t_opregion, + aml_t_powerres, + aml_t_processor, + aml_t_therm, + aml_t_bufferfield, + aml_t_ddbhandle, + aml_t_debug +}; + +struct aml_namestr { + enum aml_objtype type; /* =aml_t_namestr */ + u_int8_t *dp; +}; + +struct aml_opregion { + enum aml_objtype type; + int space; + int offset; + int length; +}; + +struct aml_num { + enum aml_objtype type; /* =aml_t_num */ + int number; + int constant; +}; + +struct aml_package { + enum aml_objtype type; + int elements; + union aml_object **objects; +}; + +struct aml_string { + enum aml_objtype type; /* =aml_t_string */ + int needfree; + u_int8_t *string; +}; + +struct aml_buffer { + enum aml_objtype type; /* =aml_t_buffer */ + int size; + u_int8_t *data; /* This should be free when + * this object is free. + */ +}; + +enum fieldtype { + f_t_field, + f_t_index, + f_t_bank +}; + +struct nfieldd { + enum fieldtype ftype; /* f_t_field */ + u_int8_t *regname; /* Namestring */ +}; + +struct ifieldd { + enum fieldtype ftype; /* f_t_index */ + u_int8_t *indexname; + u_int8_t *dataname; +}; + +struct bfieldd { + enum fieldtype ftype; /* f_t_bank */ + u_int8_t *regname; + u_int8_t *bankname; + u_int32_t bankvalue; +}; + +struct aml_field { + enum aml_objtype type; + u_int32_t flags; + int bitoffset; /* Not Byte offset but bitoffset */ + int bitlen; + union { + enum fieldtype ftype; + struct nfieldd fld; + struct ifieldd ifld; + struct bfieldd bfld; + } f; +}; + +struct aml_bufferfield { + enum aml_objtype type; /* aml_t_bufferfield */ + int bitoffset; + int bitlen; + u_int8_t *origin; /* This should not be free + * when this object is free + * (Within Buffer object) + */ +}; + +struct aml_method { + enum aml_objtype type; + int argnum; /* Not argnum but argnum|frag */ + u_int8_t *from; + u_int8_t *to; +}; + +struct aml_powerres { + enum aml_objtype type; + int level; + int order; +}; + +struct aml_processor { + enum aml_objtype type; + int id; + int addr; + int len; +}; + +struct aml_mutex_queue { +#if 0 + STAILQ_ENTRY(aml_mutex_queue) entry; +#endif +}; + +struct aml_mutex { + enum aml_objtype type; + int level; + volatile void *cookie; /* In kernel, struct proc? */ +#if 0 + STAILQ_HEAD(, aml_mutex_queue) queue; +#endif +}; + +struct aml_objref { + enum aml_objtype type; + struct aml_name *nameref; + union aml_object *ref; + int offset; /* of aml_buffer.data or aml_package.objects. */ + /* if negative value, not ready to dereference for element access. */ + unsigned deref; /* indicates whether dereffenced or not */ + unsigned alias; /* true if this is an alias object reference */ +}; + +struct aml_regfield { + enum aml_objtype type; + int space; + u_int32_t flags; + int offset; + int bitoffset; + int bitlen; +}; + +struct aml_event { + enum aml_objtype type; /* aml_t_event */ + int inuse; +}; + +union aml_object { + enum aml_objtype type; + struct aml_num num; + struct aml_processor proc; + struct aml_powerres pres; + struct aml_opregion opregion; + struct aml_method meth; + struct aml_field field; + struct aml_mutex mutex; + struct aml_namestr nstr; + struct aml_buffer buffer; + struct aml_bufferfield bfld; + struct aml_package package; + struct aml_string str; + struct aml_objref objref; + struct aml_event event; + struct aml_regfield regfield; +}; + +union aml_object *aml_copy_object(struct aml_environ *, + union aml_object *); +union aml_object *aml_alloc_object(enum aml_objtype, + union aml_object *); +void aml_free_objectcontent(union aml_object *); +void aml_free_object(union aml_object **); +void aml_realloc_object(union aml_object *, int); + +#endif /* !_AML_OBJ_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_parse.c b/usr.sbin/acpidump/aml/aml_parse.c new file mode 100644 index 00000000000..0da801de5cd --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_parse.c @@ -0,0 +1,2023 @@ +/* $OpenBSD: aml_parse.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Doug Rabson + * 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: aml_parse.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_parse.c,v 1.7 2001/10/23 14:54:15 takawata Exp $ + */ + +#include <sys/param.h> + +#include <aml/aml_amlmem.h> +#include <aml/aml_common.h> +#include <aml/aml_env.h> +#include <aml/aml_evalobj.h> +#include <aml/aml_name.h> +#include <aml/aml_obj.h> +#include <aml/aml_parse.h> +#include <aml/aml_status.h> +#include <aml/aml_store.h> + +#ifndef _KERNEL +#include <sys/stat.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/systm.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#ifndef ACPI_NO_OSDFUNC_INLINE +#include <machine/acpica_osd.h> +#endif +#endif /* !_KERNEL */ + +static int findsetleftbit(int num); +static int findsetrightbit(int num); +static int frombcd(int num); +static int tobcd(int num); + +static u_int32_t aml_parse_pkglength(struct aml_environ *env); +static u_int8_t aml_parse_bytedata(struct aml_environ *env); +static u_int16_t aml_parse_worddata(struct aml_environ *env); +static u_int32_t aml_parse_dworddata(struct aml_environ *env); +static u_int8_t *aml_parse_namestring(struct aml_environ *env); +static void aml_parse_defscope(struct aml_environ *env, + int indent); +static union aml_object *aml_parse_defbuffer(struct aml_environ *env, + int indent); +static struct aml_name *aml_parse_concat_number(struct aml_environ *env, + int num1, int indent); +static struct aml_name *aml_parse_concat_buffer(struct aml_environ *env, + union aml_object *obj, + int indent); +static struct aml_name *aml_parse_concat_string(struct aml_environ *env, + union aml_object *obj, + int indent); +static struct aml_name *aml_parse_concatop(struct aml_environ *env, + int indent); +static union aml_object *aml_parse_defpackage(struct aml_environ *env, + int indent); +static void aml_parse_defmethod(struct aml_environ *env, + int indent); +static void aml_parse_defopregion(struct aml_environ *env, + int indent); +static int aml_parse_field(struct aml_environ *env, + struct aml_field *template); +static void aml_parse_fieldlist(struct aml_environ *env, + struct aml_field *template, + int indent); +static void aml_parse_deffield(struct aml_environ *env, + int indent); +static void aml_parse_defindexfield(struct aml_environ *env, + int indent); +static void aml_parse_defbankfield(struct aml_environ *env, + int indent); +static void aml_parse_defdevice(struct aml_environ *env, + int indent); +static void aml_parse_defprocessor(struct aml_environ *env, + int indent); +static void aml_parse_defpowerres(struct aml_environ *env, + int indent); +static void aml_parse_defthermalzone(struct aml_environ *env, + int indent); +static struct aml_name *aml_parse_defelse(struct aml_environ *env, + int indent, int num); +static struct aml_name *aml_parse_defif(struct aml_environ *env, + int indent); +static struct aml_name *aml_parse_defwhile(struct aml_environ *env, + int indent); +static void aml_parse_defmutex(struct aml_environ *env, + int indent); +static void aml_createfield_generic(struct aml_environ *env, + union aml_object *srcbuf, + int index, int len, + char *newname); +static void aml_parse_defcreatefield(struct aml_environ *env, + int indent); + +static int +findsetleftbit(int num) +{ + int i, filter; + + filter = 0; + for (i = 0; i < 32; i++) { + filter = filter >> 1; + filter |= 1 << 31; + if (filter & num) { + break; + } + } + i = (i == 32) ? 0 : i + 1; + return (i); +} + +static int +findsetrightbit(int num) +{ + int i, filter; + + filter = 0; + for (i = 0; i < 32; i++) { + filter = filter << 1; + filter |= 1; + if (filter & num) { + break; + } + } + i = (i == 32) ? 0 : i + 1; + return (i); +} + +static int +frombcd(int num) +{ + int res, factor; + + res = 0; + factor = 1; + while (num != 0) { + res += ((num & 0xf) * factor); + num = num / 16; + factor *= 10; + } + return (res); +} + +static int +tobcd(int num) +{ + int res, factor; + + res = 0; + factor = 1; + while (num != 0) { + res += ((num % 10) * factor); + num = num / 10; + factor *= 16; + } + return (res); +} + +static u_int32_t +aml_parse_pkglength(struct aml_environ *env) +{ + u_int8_t *dp; + u_int32_t pkglength; + + dp = env->dp; + pkglength = *dp++; + switch (pkglength >> 6) { + case 0: + break; + case 1: + pkglength = (pkglength & 0xf) + (dp[0] << 4); + dp += 1; + break; + case 2: + pkglength = (pkglength & 0xf) + (dp[0] << 4) + (dp[1] << 12); + dp += 2; + break; + case 3: + pkglength = (pkglength & 0xf) + + (dp[0] << 4) + (dp[1] << 12) + (dp[2] << 20); + dp += 3; + break; + } + + env->dp = dp; + return (pkglength); +} + +static u_int8_t +aml_parse_bytedata(struct aml_environ *env) +{ + u_int8_t data; + + data = env->dp[0]; + env->dp++; + return (data); +} + +static u_int16_t +aml_parse_worddata(struct aml_environ *env) +{ + u_int16_t data; + + data = env->dp[0] + (env->dp[1] << 8); + env->dp += 2; + return (data); +} + +static u_int32_t +aml_parse_dworddata(struct aml_environ *env) +{ + u_int32_t data; + + data = env->dp[0] + (env->dp[1] << 8) + + (env->dp[2] << 16) + (env->dp[3] << 24); + env->dp += 4; + return (data); +} + +static u_int8_t * +aml_parse_namestring(struct aml_environ *env) +{ + u_int8_t *name; + int segcount; + + name = env->dp; + if (env->dp[0] == '\\') + env->dp++; + else if (env->dp[0] == '^') + while (env->dp[0] == '^') + env->dp++; + if (env->dp[0] == 0x00) /* NullName */ + env->dp++; + else if (env->dp[0] == 0x2e) /* DualNamePrefix */ + env->dp += 1 + 4 + 4; /* NameSeg, NameSeg */ + else if (env->dp[0] == 0x2f) { /* MultiNamePrefix */ + segcount = env->dp[1]; + env->dp += 1 + 1 + segcount * 4; /* segcount * NameSeg */ + } else + env->dp += 4; /* NameSeg */ + + return (name); +} + +struct aml_name * +aml_parse_objectlist(struct aml_environ *env, int indent) +{ + union aml_object *obj; + + obj = NULL; + while (env->dp < env->end) { + aml_print_indent(indent); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT("\n"); + if (env->stat == aml_stat_step) { + AML_DEBUGGER(env, env); + continue; + } + if (env->stat != aml_stat_none) { + env->tempname.property = obj; + return (&env->tempname); + } + } + return (NULL); +} + +#define AML_CREATE_NAME(amlname, env, namestr, ret) do { \ + amlname = aml_create_name(env, namestr); \ + if (env->stat == aml_stat_panic) \ + return ret; \ +} while(0) + +#define AML_COPY_OBJECT(dest, env, src, ret) do { \ + dest = aml_copy_object(env, src); \ + if (dest == NULL) { \ + env->stat = aml_stat_panic; \ + return ret; \ + } \ +} while(0) + +#define AML_ALLOC_OBJECT(dest, env, type, ret) do { \ + dest = aml_alloc_object(type, NULL); \ + if (dest == NULL) { \ + env->stat= aml_stat_panic; \ + return ret; \ + } \ +} while(0) + +static void +aml_parse_defscope(struct aml_environ *env, int indent) +{ + u_int8_t *start, *end, *oend; + u_int8_t *name; + u_int32_t pkglength; + struct aml_name *oname; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + + AML_DEBUGPRINT("Scope("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_DEBUGPRINT(") {\n"); + oname = env->curname; + AML_CREATE_NAME(env->curname, env, name,); + oend = env->end; + env->end = end = start + pkglength; + aml_parse_objectlist(env, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + AML_SYSASSERT(env->dp == env->end); + env->dp = end; + env->end = oend; + env->curname = oname; + env->stat = aml_stat_none; +} + +static union aml_object * +aml_parse_defbuffer(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *end; + u_int8_t *buffer; + u_int32_t pkglength; + int size1, size2, size; + union aml_object *obj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + end = start + pkglength; + + AML_DEBUGPRINT("Buffer("); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + size1 = aml_objtonum(env, obj); + size2 = end - env->dp; + size = (size1 < size2) ? size1 : size2; + if (size1 > 0) { + buffer = memman_alloc_flexsize(aml_memman, size1); + if (buffer == NULL) { + AML_DEBUGPRINT("NO MEMORY\n"); + env->stat = aml_stat_panic; + return (NULL); + } + bzero(buffer, size1); + bcopy(env->dp, buffer, size); + } else { + buffer = NULL; + } + + obj = &env->tempobject; + obj->type = aml_t_buffer; + obj->buffer.size = size1; + obj->buffer.data = buffer; + AML_DEBUGPRINT(") "); + env->dp = end; + + return (obj); +} + +static struct aml_name * +aml_parse_concat_number(struct aml_environ *env, int num1, int indent) +{ + int num2; + struct aml_name *destname; + union aml_object *obj; + + num2 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + destname = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + obj = &env->tempobject; + obj->type = aml_t_buffer; + obj->buffer.size = 2; + obj->buffer.data = memman_alloc_flexsize(aml_memman, 2); + if (obj->buffer.data == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + obj->buffer.data[0] = num1 & 0xff; + obj->buffer.data[1] = num2 & 0xff; + aml_store_to_name(env, obj, destname); + return (&env->tempname); +} + +static struct aml_name * +aml_parse_concat_buffer(struct aml_environ *env, union aml_object *obj, + int indent) +{ + union aml_object *tmpobj, *tmpobj2, *resobj; + struct aml_name *destname; + + tmpobj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + if (tmpobj->type != aml_t_buffer) { + env->stat = aml_stat_panic; + return (NULL); + } + AML_COPY_OBJECT(tmpobj2, env, tmpobj, NULL); + destname = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + resobj = &env->tempobject; + env->tempname.property = resobj; + resobj->buffer.type = aml_t_buffer; + resobj->buffer.size = tmpobj2->buffer.size + obj->buffer.size; + if (resobj->buffer.size > 0) { + resobj->buffer.data = memman_alloc_flexsize(aml_memman, + resobj->buffer.size); + if (resobj->buffer.data == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + bcopy(obj->buffer.data, resobj->buffer.data, obj->buffer.size); + bcopy(tmpobj2->buffer.data, + resobj->buffer.data + obj->buffer.size, + tmpobj2->buffer.size); + } else { + resobj->buffer.data = NULL; + } + aml_free_object(&tmpobj2); + aml_store_to_name(env, resobj, destname); + return (&env->tempname); +} + +static struct aml_name * +aml_parse_concat_string(struct aml_environ *env, union aml_object *obj, + int indent) +{ + int len; + union aml_object *tmpobj, *tmpobj2, *resobj; + struct aml_name *destname; + + tmpobj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + if (tmpobj->type != aml_t_string) { + env->stat = aml_stat_panic; + return (NULL); + } + AML_COPY_OBJECT(tmpobj2, env, tmpobj, NULL); + destname = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + resobj = &env->tempobject; + env->tempname.property = resobj; + resobj->type = aml_t_buffer; + resobj->str.needfree = 1; + len = strlen(obj->str.string) + strlen(tmpobj2->str.string) + 1; + if (len > 0) { + resobj->str.string = memman_alloc_flexsize(aml_memman, len); + if (resobj->str.string == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + strncpy(resobj->str.string, obj->str.string, len); + strcat(resobj->str.string, tmpobj->str.string); + } else { + resobj->str.string = NULL; + } + aml_free_object(&tmpobj2); + aml_store_to_name(env, resobj, destname); + return (&env->tempname); +} + +static struct aml_name * +aml_parse_concatop(struct aml_environ *env, int indent) +{ + union aml_object *obj, *tmpobj; + struct aml_name *aname; + + AML_DEBUGPRINT("Concat("); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + switch (obj->type) { + case aml_t_num: + aname = aml_parse_concat_number(env, aml_objtonum(env, obj), indent); + break; + + case aml_t_buffer: + /* obj may be temporal object */ + AML_COPY_OBJECT(tmpobj, env, obj, NULL); + aname = aml_parse_concat_buffer(env, obj, indent); + aml_free_object(&tmpobj); + break; + + case aml_t_string: + /* obj may be temporal object */ + AML_COPY_OBJECT(tmpobj, env, obj, NULL); + aname = aml_parse_concat_string(env, obj, indent); + aml_free_object(&tmpobj); + break; + + default: + env->stat = aml_stat_panic; + aname = NULL; + break; + } + + AML_DEBUGPRINT("\n"); + return (aname); +} + +static union aml_object * +aml_parse_defpackage(struct aml_environ *env, int indent) +{ + u_int8_t numelements; + u_int8_t *start; + u_int32_t pkglength; + int i; + struct aml_environ *copy; + struct aml_name *tmpname; + union aml_object *obj, **objects; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + numelements = aml_parse_bytedata(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } + if (numelements > 0) { + objects = memman_alloc_flexsize(aml_memman, + numelements * sizeof(union aml_object *)); + if (objects == NULL) { + env->stat = aml_stat_panic; + return (NULL); + } else { + bzero(objects, numelements * sizeof(union aml_object *)); + } + } else { + objects = NULL; + } + + *copy = *env; + env->dp = copy->end = start + pkglength; + AML_DEBUGPRINT("Package() {\n"); + i = 0; + while ((copy->dp < copy->end) && (i < numelements)) { + aml_print_indent(indent + 1); + tmpname = aml_parse_termobj(copy, indent + 1); + + if (tmpname != NULL) { + objects[i] = aml_copy_object(copy, tmpname->property); + } + AML_DEBUGPRINT(",\n"); + i++; + } + aml_free_objectcontent(©->tempobject); + + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + obj = &env->tempobject; + obj->type = aml_t_package; + obj->package.elements = numelements; + obj->package.objects = objects; + + memman_free(aml_memman, memid_aml_environ, copy); + return (obj); +} + +static void +aml_parse_defmethod(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start; + u_int32_t pkglength; + char *name; + struct aml_environ *copy; + struct aml_method *meth; + struct aml_name *aname; + union aml_object *aobj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("Method("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + AML_ALLOC_OBJECT(aobj, env, aml_t_method,); + meth = &aobj->meth; + aname->property = aobj; + flags = *env->dp++; + + if (flags) { + AML_DEBUGPRINT(", %d", flags); + } + AML_DEBUGPRINT(") {\n"); + *copy = *env; + meth->argnum = flags; + meth->from = env->dp; + meth->to = env->dp = copy->end = start + pkglength; + aml_print_indent(indent); + AML_DEBUGPRINT("}"); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defopregion(struct aml_environ *env, int indent) +{ + u_int8_t *name; + struct aml_name *aname; + struct aml_opregion *opregion; + union aml_object *obj; + const char *regions[] = { + "SystemMemory", + "SystemIO", + "PCI_Config", + "EmbeddedControl", + "SMBus", + }; + + AML_DEBUGPRINT("OperationRegion("); + /* Name */ + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return; + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_opregion,); + opregion = &aname->property->opregion; + opregion->space = *env->dp; + AML_DEBUGPRINT(", %s, ", regions[*env->dp]); /* Space */ + env->dp++; + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); /* Offset */ + opregion->offset = aml_objtonum(env, obj); + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); /* Length */ + opregion->length = aml_objtonum(env, obj); + AML_DEBUGPRINT(")"); +} + +static const char *accessnames[] = { + "AnyAcc", + "ByteAcc", + "WordAcc", + "DWordAcc", + "BlockAcc", + "SMBSendRecvAcc", + "SMBQuickAcc" +}; + +static int +aml_parse_field(struct aml_environ *env, struct aml_field *template) +{ + u_int8_t *name; + u_int8_t access, attribute; + u_int32_t width; + struct aml_name *aname; + struct aml_field *prop; + + switch (*env->dp) { + case '\\': + case '^': + case 'A'...'Z': + case '_': + case '.': + case '/': + name = aml_parse_namestring(env); + width = aml_parse_pkglength(env); + template->bitlen = width; + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + /* Allignment */ + if (width == 16) { + template->bitoffset += 15; + template->bitoffset &= (~15); + } + if (width == 32) { + template->bitoffset += 31; + template->bitoffset &= (~31); + } else if ((width & 7) == 0) { + template->bitoffset += 7; + template->bitoffset &= (~7); + } else if ((width > 32) && (width & 7) != 0) { + AML_DEBUGPRINT("??? Can I treat it?\n"); + } + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return (NULL); + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_field, NULL); + prop = &aname->property->field; + *prop = *template; + template->bitoffset += width; + AML_DEBUGPRINT(",\t%d", width); + break; + case 0x00: + env->dp++; + width = aml_parse_pkglength(env); + template->bitoffset += width; + AML_DEBUGPRINT("Offset(0x%x)", template->bitoffset); + break; + case 0x01: + access = env->dp[1]; + attribute = env->dp[2]; + env->dp += 3; + AML_DEBUGPRINT("AccessAs(%s, %d)", accessnames[access], attribute); + template->bitoffset = attribute; + template->flags = (template->flags | 0xf0) | access; + break; + } + return (template->bitoffset); +} + +static void +aml_parse_fieldlist(struct aml_environ *env, struct aml_field *template, + int indent) +{ + u_int32_t offset; + + offset = 0; + while (env->dp < env->end) { + aml_print_indent(indent); + offset = aml_parse_field(env, template); + if (env->dp < env->end) { + AML_DEBUGPRINT(",\n"); + } else { + AML_DEBUGPRINT("\n"); + } + } +} + +static void +aml_parse_deffield(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start, *name; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_field fieldtemplate; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("Field("); + aml_print_namestring(name = aml_parse_namestring(env)); + fieldtemplate.type = aml_t_field; + flags = aml_parse_bytedata(env); + fieldtemplate.flags = fieldtemplate.flags = flags; + + *copy = *env; + env->dp = copy->end = start + pkglength; + fieldtemplate.bitoffset = 0; + fieldtemplate.bitlen = 0; + fieldtemplate.f.ftype = f_t_field; + fieldtemplate.f.fld.regname = name; + AML_DEBUGPRINT(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + aml_parse_fieldlist(copy, &fieldtemplate, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defindexfield(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start, *iname, *dname; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_field template; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("IndexField("); + aml_print_namestring(iname = aml_parse_namestring(env)); /* Name1 */ + AML_DEBUGPRINT(", "); + aml_print_namestring(dname = aml_parse_namestring(env)); /* Name2 */ + template.type = aml_t_field; + template.flags = flags = aml_parse_bytedata(env); + template.bitoffset = 0; + template.bitlen = 0; + template.f.ftype = f_t_index; + template.f.ifld.indexname = iname; + template.f.ifld.dataname = dname; + AML_DEBUGPRINT(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + *copy = *env; + env->dp = copy->end = start + pkglength; + aml_parse_fieldlist(copy, &template, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defbankfield(struct aml_environ *env, int indent) +{ + u_int8_t flags; + u_int8_t *start, *rname, *bname; + u_int32_t pkglength, bankvalue; + struct aml_environ *copy; + struct aml_field template; + union aml_object *obj; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("BankField("); + aml_print_namestring(rname = aml_parse_namestring(env)); /* Name1 */ + AML_DEBUGPRINT(", "); + aml_print_namestring(bname = aml_parse_namestring(env)); /* Name2 */ + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); /* BankValue */ + bankvalue = aml_objtonum(env, obj); + template.type = aml_t_field; + template.flags = flags = aml_parse_bytedata(env); + template.bitoffset = 0; + template.bitlen = 0; + template.f.ftype = f_t_bank; + template.f.bfld.regname = rname; + template.f.bfld.bankname = bname; + template.f.bfld.bankvalue = bankvalue; + *copy = *env; + env->dp = copy->end = start + pkglength; + AML_DEBUGPRINT(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + aml_parse_fieldlist(copy, &template, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + + aml_free_objectcontent(©->tempobject); + AML_SYSASSERT(copy->dp == copy->end); + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defdevice(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("Device("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_DEBUGPRINT(") {\n"); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + AML_ALLOC_OBJECT(copy->curname->property, env, aml_t_device,); + env->dp = copy->end = start + pkglength; + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defprocessor(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_processor *proc; + union aml_object *obj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_ALLOC_OBJECT(obj, env, aml_t_processor,); + proc = &obj->proc; + AML_DEBUGPRINT("Processor("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + proc->id = aml_parse_bytedata(env); + proc->addr = aml_parse_dworddata(env); + proc->len = aml_parse_bytedata(env); + AML_DEBUGPRINT(", %d, 0x%x, 0x%x) {\n", proc->id, proc->addr, proc->len); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + copy->curname->property = obj; + env->dp = copy->end = start + pkglength; + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defpowerres(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + struct aml_powerres *pres; + union aml_object *obj; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("PowerResource("); + AML_ALLOC_OBJECT(obj, env, aml_t_powerres,); + name = aml_parse_namestring(env); + aml_print_namestring(name); + pres = &obj->pres; + pres->level = aml_parse_bytedata(env); + pres->order = aml_parse_worddata(env); + AML_DEBUGPRINT(", %d, %d) {\n", pres->level, pres->order); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + copy->curname->property = obj; + env->dp = copy->end = start + pkglength; + + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static void +aml_parse_defthermalzone(struct aml_environ *env, int indent) +{ + u_int8_t *start; + u_int8_t *name; + u_int32_t pkglength; + struct aml_environ *copy; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + copy = memman_alloc(aml_memman, memid_aml_environ); + if (copy == NULL) { + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT("ThermalZone("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_DEBUGPRINT(") {\n"); + *copy = *env; + AML_CREATE_NAME(copy->curname, env, name,); + if (copy->curname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + goto out; + } + AML_ALLOC_OBJECT(copy->curname->property, env, aml_t_therm,); + env->dp = copy->end = start + pkglength; + aml_parse_objectlist(copy, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + aml_free_objectcontent(©->tempobject); + AML_SYSASSERT(copy->dp == copy->end); +out: + memman_free(aml_memman, memid_aml_environ, copy); +} + +static struct aml_name * +aml_parse_defelse(struct aml_environ *env, int indent, int num) +{ + u_int8_t *start, *end, *oend; + u_int32_t pkglength; + struct aml_name *aname; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + oend = env->end; + env->end = end = start + pkglength; + aname = NULL; + + AML_DEBUGPRINT("Else {\n"); + if (num == 0) { + aname = aml_parse_objectlist(env, indent + 1); + aml_print_indent(indent); + } + AML_DEBUGPRINT("}"); + + env->dp = end; + env->end = oend; + return (aname); +} + +static struct aml_name * +aml_parse_defif(struct aml_environ *env, int indent) +{ + u_int8_t *start, *end, *oend; + u_int32_t pkglength; + int num; + struct aml_name *aname, *aname1; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + aname = NULL; + + AML_DEBUGPRINT("If("); + num = aml_objtonum(env, aml_eval_name + (env, aml_parse_termobj(env, indent))); + oend = env->end; + end = start + pkglength; + AML_DEBUGPRINT(")"); + if (num) { + AML_DEBUGPRINT("{\n"); + env->end = end; + aname = aml_parse_objectlist(env, indent + 1); + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + } + env->dp = end; + env->end = oend; + if ((end < oend) && *(env->dp) == 0xa1) { + env->dp++; + aname1 = aml_parse_defelse(env, indent, num); + aname = (num == 0) ? aname1 : aname; + } + return (aname); +} + +static struct aml_name * +aml_parse_defwhile(struct aml_environ *env, int indent) +{ + u_int8_t *start, *end, *oend; + u_int32_t pkglength; + int num; + struct aml_name *aname; + + start = env->dp; + pkglength = aml_parse_pkglength(env); + oend = env->end; + end = start + pkglength; + aname = NULL; + for (;;) { + env->dp = start; + aml_parse_pkglength(env); + AML_DEBUGPRINT("While("); + num = aml_objtonum(env, aml_eval_name + (env, aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(")"); + if (num == 0) { + break; + } + AML_DEBUGPRINT(" {\n"); + env->end = end; + aname = aml_parse_objectlist(env, indent + 1); + if (env->stat == aml_stat_step) { + AML_DEBUGGER(env, env); + continue; + } + if (env->stat != aml_stat_none) + break; + aml_print_indent(indent); + AML_DEBUGPRINT("}"); + } + AML_DEBUGPRINT("\n"); + env->dp = end; + env->end = oend; + if (env->stat == aml_stat_break) { + env->stat = aml_stat_none; + aname = NULL; + } + return (aname); +} + +static void +aml_parse_defmutex(struct aml_environ *env, int indent) +{ + char *name; + struct aml_name *aname; + struct aml_mutex *mut; + + /* MutexOp */ + AML_DEBUGPRINT("Mutex("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return; + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_mutex,); + mut = &aname->property->mutex; + mut->level = *env->dp++; +#if 0 + STAILQ_INIT(&mut->queue); +#endif + AML_DEBUGPRINT(", %d)", mut->level); +} + +static void +aml_createfield_generic(struct aml_environ *env, + union aml_object *srcbuf, int index, + int len, char *newname) +{ + struct aml_bufferfield *field; + struct aml_name *aname; + + if (srcbuf == NULL || srcbuf->type != aml_t_buffer) { + AML_DEBUGPRINT("Not Buffer assigned,"); + env->stat = aml_stat_panic; + return; + } + AML_CREATE_NAME(aname, env, newname,); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return; + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_bufferfield,); + field = &aname->property->bfld; + field->bitoffset = index; + field->bitlen = len; + field->origin = srcbuf->buffer.data; +} + +static void +aml_parse_defcreatefield(struct aml_environ *env, int indent) +{ + int index, len; + char *newname; + union aml_object *obj, *srcbuf; + + /* CreateFieldOp */ + AML_DEBUGPRINT("CreateField("); + srcbuf = aml_eval_name(env, aml_parse_termobj(env, indent)); + if (srcbuf == &env->tempobject) { + AML_DEBUGPRINT("NONAMED BUFFER\n"); + env->stat = aml_stat_panic; + return; + } + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + index = aml_objtonum(env, obj); + AML_DEBUGPRINT(", "); + obj = aml_eval_name(env, aml_parse_termobj(env, indent)); + len = aml_objtonum(env, obj); + AML_DEBUGPRINT(", "); + newname = aml_parse_namestring(env); + aml_print_namestring(newname); + aml_createfield_generic(env, srcbuf, index, len, newname); + AML_DEBUGPRINT(") "); +} + +/* + * Returns Named object or parser buffer. The object need not be free because + * it returns preallocated buffer in env or Contain of named object. If You + * need to preserve object, create a copy and then store. And The object + * returned from this function is not valid after another call is + * shared, tempolary buffer may be shared. + */ +struct aml_name * +aml_parse_termobj(struct aml_environ *env, int indent) +{ + u_int8_t opcode; + u_int8_t *name; + int value; + int num1, num2; + int len; + int match1, match2, i, pkgval, start; + int widthindex, index; + char *newname; + struct aml_name *aname; + struct aml_name *destname1, *destname2; + struct aml_name *tmpname, *srcname; + struct aml_name *src; + union aml_object *ret; + union aml_object *tmpobj; + union aml_object anum; + union aml_object *objref; + union aml_object *srcobj; + union aml_object *obj; + union aml_object *srcbuf; + static int widthtbl[4] = {32, 16, 8, 1}; + const char *opname[4] = {"CreateDWordField", "CreateWordField", + "CreateByteField", "CreateBitField"}; + + aname = &env->tempname; + ret = &env->tempobject; + anum.type = aml_t_num; + aname->property = ret; + aml_free_objectcontent(ret); + if (env->stat == aml_stat_panic) { + /* + * If previosuly parser panic , parsing next instruction is + * prohibited. + */ + return (NULL); + } + aname = NULL; + opcode = *env->dp++; + switch (opcode) { + case '\\': + case '^': + case 'A' ... 'Z': + case '_': + case '.': + case '/': + env->dp--; + ret->type = aml_t_namestr; + ret->nstr.dp = aml_parse_namestring(env); + aml_print_namestring(ret->nstr.dp); + aname = &env->tempname; + break; + case 0x0a: /* BytePrefix */ + ret->type = aml_t_num; + value = aml_parse_bytedata(env); + ret->num.number = value; + AML_DEBUGPRINT("0x%x", value); + aname = &env->tempname; + break; + case 0x0b: /* WordPrefix */ + ret->type = aml_t_num; + value = aml_parse_worddata(env); + ret->num.number = value; + AML_DEBUGPRINT("0x%x", value); + aname = &env->tempname; + break; + case 0x0c: /* DWordPrefix */ + ret->type = aml_t_num; + value = aml_parse_dworddata(env); + ret->num.number = value; + AML_DEBUGPRINT("0x%x", value); + aname = &env->tempname; + break; + case 0x0d: /* StringPrefix */ + ret->type = aml_t_string; + ret->str.string = env->dp; + len = strlen(env->dp); + ret->str.needfree = 0; + AML_DEBUGPRINT("\"%s\"", (const char *)ret->str.string); + env->dp += (len + 1); + aname = &env->tempname; + break; + case 0x00: /* ZeroOp */ + ret->type = aml_t_num; + ret->num.number = 0; + ret->num.constant = 1; + AML_DEBUGPRINT("Zero"); + aname = &env->tempname; + break; + case 0x01: /* OneOp */ + ret->type = aml_t_num; + ret->num.number = 1; + ret->num.constant = 1; + AML_DEBUGPRINT("One"); + aname = &env->tempname; + break; + case 0xff: /* OnesOp */ + ret->type = aml_t_num; + ret->num.number = 0xffffffff; + ret->num.constant = 1; + AML_DEBUGPRINT("Ones"); + aname = &env->tempname; + break; + case 0x06: /* AliasOp */ + AML_DEBUGPRINT("Alias("); + tmpname = aml_parse_termobj(env, indent); + if (env->stat == aml_stat_panic) { + return (NULL); + } + if (tmpname->property == NULL || + tmpname->property->type != aml_t_namestr) { + env->stat = aml_stat_panic; + return (NULL); + } + /* + * XXX if srcname is deleted after this object, what + * shall I do? + */ + srcname = aml_search_name(env, tmpname->property->nstr.dp); + AML_DEBUGPRINT(", "); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + aml_print_curname(aname); + return (NULL); + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_objref, NULL); + objref = aname->property; + objref->objref.nameref = srcname; + objref->objref.ref = srcname->property; + objref->objref.offset = -1; + objref->objref.alias = 1; /* Yes, this is an alias */ + AML_DEBUGPRINT(")"); + /* shut the interpreter up during the namespace initializing */ + return (NULL); + case 0x08: /* NameOp */ + AML_DEBUGPRINT("Name("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + if (env->stat == aml_stat_panic) { + AML_DEBUGPRINT("Already Defined \n"); + aml_print_curname(aname); + return (NULL); + } + AML_DEBUGPRINT(", "); + AML_COPY_OBJECT(aname->property, env, + aml_eval_name(env, + aml_parse_termobj(env, indent)), + NULL); + AML_DEBUGPRINT(")"); + break; + case 0x10: /* ScopeOp */ + aml_parse_defscope(env, indent); + break; + case 0x11: /* BufferOp */ + aname = &env->tempname; + aname->property = aml_parse_defbuffer(env, indent); + break; + case 0x12: /* PackageOp */ + aname = &env->tempname; + aname->property = aml_parse_defpackage(env, indent); + break; + case 0x14: /* MethodOp */ + aml_parse_defmethod(env, indent); + break; + case 0x5b: /* ExtOpPrefix */ + opcode = *env->dp++; + switch (opcode) { + case 0x01: + aml_parse_defmutex(env, indent); + break; + case 0x02: /* EventOp */ + AML_DEBUGPRINT("Event("); + name = aml_parse_namestring(env); + aml_print_namestring(name); + AML_CREATE_NAME(aname, env, name, NULL); + if (aname->property != NULL) { + env->stat = aml_stat_panic; + AML_DEBUGPRINT("Already Defined \n"); + return (NULL); + } + AML_ALLOC_OBJECT(aname->property, env, aml_t_event, NULL); + AML_DEBUGPRINT(")"); + return (NULL); + break; + case 0x12: /* CondRefOfOp */ + AML_DEBUGPRINT("CondRefOf("); + src = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + if (src == &env->tempname || src == NULL) { + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + anum.num.number = 0xffffffff; + env->tempobject.num = anum.num; + aname = &env->tempname; + break; + } + AML_ALLOC_OBJECT(objref, env, aml_t_objref, NULL); + if (src->property == NULL || + src->property->type != aml_t_namestr) { + objref->objref.nameref = src; + } else { + objref->objref.nameref = aml_create_local_object(); + } + objref->objref.ref = src->property; + objref->objref.offset = -1; /* different from IndexOp */ + + destname1 = aml_parse_termobj(env, indent); + aml_store_to_name(env, objref, destname1); + anum.num.number = 0; + env->tempobject.num = anum.num; + aname = &env->tempname; + AML_DEBUGPRINT(")"); + break; + case 0x13: + aml_parse_defcreatefield(env, indent); + break; + case 0x20: /* LoadOp *//* XXX Not Impremented */ + AML_DEBUGPRINT("Load("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x21: /* StallOp */ + AML_DEBUGPRINT("Stall("); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(")"); + AML_STALL(num1); + break; + case 0x22: /* SleepOp */ + AML_DEBUGPRINT("Sleep("); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_SLEEP(0, num1); + AML_DEBUGPRINT(")"); + break; + case 0x23: /* AcquireOp *//* XXX Not yet */ + AML_DEBUGPRINT("Acquire("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", 0x%x)", aml_parse_worddata(env)); + break; + case 0x24: /* SignalOp *//* XXX Not yet */ + AML_DEBUGPRINT("Signal("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x25: /* WaitOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Wait("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x26: /* ResetOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Reset("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x27: /* ReleaseOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Release("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; +#define NUMOP2(opname, operation) do { \ + AML_DEBUGPRINT(opname); \ + AML_DEBUGPRINT("("); \ + num1 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + anum.num.number = operation (num1); \ + destname1 = aml_parse_termobj(env, indent); \ + AML_DEBUGPRINT(")"); \ + aml_store_to_name(env, &anum, destname1); \ + env->tempobject.num = anum.num; \ + env->tempname.property = &env->tempobject; \ + aname = &env->tempname; \ +} while(0) + + case 0x28: /* FromBCDOp */ + NUMOP2("FromBCD", frombcd); + break; + case 0x29: /* ToBCDOp */ + NUMOP2("ToBCD", tobcd); + break; + case 0x2a: /* UnloadOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Unload("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x30: + env->tempobject.type = aml_t_num; + env->tempobject.num.number = 0; + env->tempobject.num.constant = 1; + AML_DEBUGPRINT("Revision"); + break; + case 0x31: + env->tempobject.type = aml_t_debug; + aname = &env->tempname; + AML_DEBUGPRINT("Debug"); + break; + case 0x32: /* FatalOp */ + AML_DEBUGPRINT("Fatal("); + AML_DEBUGPRINT("0x%x, ", aml_parse_bytedata(env)); + AML_DEBUGPRINT("0x%x, ", aml_parse_dworddata(env)); + aml_parse_termobj(env, indent); + env->stat = aml_stat_panic; + AML_DEBUGPRINT(")"); + break; + case 0x80: /* OpRegionOp */ + aml_parse_defopregion(env, indent); + break; + case 0x81: /* FieldOp */ + aml_parse_deffield(env, indent); + break; + case 0x82: /* DeviceOp */ + aml_parse_defdevice(env, indent); + break; + case 0x83: /* ProcessorOp */ + aml_parse_defprocessor(env, indent); + break; + case 0x84: /* PowerResOp */ + aml_parse_defpowerres(env, indent); + break; + case 0x85: /* ThermalZoneOp */ + aml_parse_defthermalzone(env, indent); + break; + case 0x86: /* IndexFieldOp */ + aml_parse_defindexfield(env, indent); + break; + case 0x87: /* BankFieldOp */ + aml_parse_defbankfield(env, indent); + break; + default: + AML_SYSERRX(1, "strange opcode 0x5b, 0x%x\n", opcode); + AML_SYSABORT(); + } + break; + case 0x68 ... 0x6e: /* ArgN */ + AML_DEBUGPRINT("Arg%d", opcode - 0x68); + return (aml_local_stack_getArgX(NULL, opcode - 0x68)); + break; + case 0x60 ... 0x67: + AML_DEBUGPRINT("Local%d", opcode - 0x60); + return (aml_local_stack_getLocalX(opcode - 0x60)); + break; + case 0x70: /* StoreOp */ + AML_DEBUGPRINT("Store("); + aname = aml_create_local_object(); + AML_COPY_OBJECT(tmpobj, env, + aml_eval_name(env, aml_parse_termobj(env, indent)), NULL); + aname->property = tmpobj; + AML_DEBUGPRINT(", "); + destname1 = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + /* XXX + * temporary object may change during aml_store_to_name() + * operation, so we make a copy of it on stack. + */ + if (destname1 == &env->tempname && + destname1->property == &env->tempobject) { + destname1 = aml_create_local_object(); + AML_COPY_OBJECT(destname1->property, env, + &env->tempobject, NULL); + } + aml_store_to_name(env, tmpobj, destname1); + if (env->stat == aml_stat_panic) { + AML_DEBUGPRINT("StoreOp failed"); + return (NULL); + } + aname = aml_create_local_object(); + AML_COPY_OBJECT(tmpobj, env, destname1->property, NULL); + aname->property = tmpobj; + if (tmpobj == NULL) { + printf("???"); + break; + } + break; + case 0x71: /* RefOfOp */ + AML_DEBUGPRINT("RefOf("); + src = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + + aname = aml_create_local_object(); + AML_ALLOC_OBJECT(aname->property, env, aml_t_objref, NULL); + objref = aname->property; + if (src->property == NULL || + src->property->type != aml_t_namestr) { + objref->objref.nameref = src; + } else { + objref->objref.nameref = aml_create_local_object(); + } + objref->objref.ref = src->property; + objref->objref.offset = -1; /* different from IndexOp */ + break; + +#define NUMOP3_2(opname, oparation, ope2) do { \ + AML_DEBUGPRINT(opname); \ + AML_DEBUGPRINT("("); \ + num1 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + num2 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + anum.num.number = ope2(num1 oparation num2); \ + destname1 = aml_parse_termobj(env, indent); \ + AML_DEBUGPRINT(")"); \ + aml_store_to_name(env, &anum, destname1); \ + env->tempobject.num = anum.num; \ + env->tempname.property = &env->tempobject; \ + aname = &env->tempname; \ +} while(0) + +#define NUMOP3(opname, operation) NUMOP3_2(opname, operation, ) +#define NUMOPN3(opname, operation) NUMOP3_2(opname, operation, ~) + + case 0x72: /* AddOp */ + NUMOP3("Add", +); + break; + case 0x73: /* ConcatOp */ + aname = aml_parse_concatop(env, indent); + break; + case 0x74: /* SubtractOp */ + NUMOP3("Subtract", -); + break; + case 0x75: /* IncrementOp */ + AML_DEBUGPRINT("Increment("); + aname = aml_parse_termobj(env, indent); + num1 = aml_objtonum(env, aml_eval_name(env, aname)); + num1++; + anum.num.number = num1; + AML_DEBUGPRINT(")"); + aml_store_to_name(env, &anum, aname); + aname = &env->tempname; + env->tempobject.num = anum.num; + break; + case 0x76: /* DecrementOp */ + AML_DEBUGPRINT("Decrement("); + aname = aml_parse_termobj(env, indent); + num1 = aml_objtonum(env, aml_eval_name(env, aname)); + num1--; + anum.num.number = num1; + AML_DEBUGPRINT(")"); + aml_store_to_name(env, &anum, aname); + aname = &env->tempname; + env->tempobject.num = anum.num; + break; + case 0x77: /* MultiplyOp */ + NUMOP3("Multiply", *); + break; + case 0x78: /* DivideOp */ + AML_DEBUGPRINT("Divide("); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + num2 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + anum.num.number = num1 % num2; + destname1 = aml_parse_termobj(env, indent); + aml_store_to_name(env, &anum, destname1); + AML_DEBUGPRINT(", "); + anum.num.number = num1 / num2; + destname2 = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + aml_store_to_name(env, &anum, destname2); + env->tempobject.num = anum.num; + aname = &env->tempname; + break; + case 0x79: /* ShiftLeftOp */ + NUMOP3("ShiftLeft", <<); + break; + case 0x7a: /* ShiftRightOp */ + NUMOP3("ShiftRight", >>); + break; + case 0x7b: /* AndOp */ + NUMOP3("And", &); + break; + case 0x7c: /* NAndOp */ + NUMOPN3("NAnd", &); + break; + case 0x7d: /* OrOp */ + NUMOP3("Or", |); + break; + case 0x7e: /* NOrOp */ + NUMOPN3("NOr", |); + break; + case 0x7f: /* XOrOp */ + NUMOP3("XOr", ^); + break; + case 0x80: /* NotOp */ + NUMOP2("Not", ~); + break; + case 0x81: /* FindSetLeftBitOp */ + NUMOP2("FindSetLeftBit", findsetleftbit); + break; + case 0x82: /* FindSetRightBitOp */ + NUMOP2("FindSetRightBit", findsetrightbit); + break; + case 0x83: /* DerefOp */ + AML_DEBUGPRINT("DerefOf("); + objref = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(")"); + + if (objref->objref.ref == NULL) { + env->tempname.property = objref->objref.ref; + aname = &env->tempname; + break; + } + switch (objref->objref.ref->type) { + case aml_t_package: + case aml_t_buffer: + if (objref->objref.offset < 0) { + env->tempname.property = objref->objref.ref; + } else { + objref->objref.deref = 1; + env->tempname.property = objref; + } + break; + default: + env->tempname.property = objref->objref.ref; + break; + } + + aname = &env->tempname; + break; + case 0x86: /* NotifyOp *//* XXX Not yet impremented */ + AML_DEBUGPRINT("Notify("); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(", "); + aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + break; + case 0x87: /* SizeOfOp */ + AML_DEBUGPRINT("SizeOf("); + aname = aml_parse_termobj(env, indent); + tmpobj = aml_eval_name(env, aname); + + AML_DEBUGPRINT(")"); + num1 = 0; + switch (tmpobj->type) { + case aml_t_buffer: + num1 = tmpobj->buffer.size; + break; + case aml_t_string: + num1 = strlen(tmpobj->str.string); + break; + case aml_t_package: + num1 = tmpobj->package.elements; + break; + default: + AML_DEBUGPRINT("Args of SizeOf should be " + "buffer/string/package only\n"); + break; + } + + anum.num.number = num1; + env->tempobject.num = anum.num; + aname = &env->tempname; + break; + case 0x88: /* IndexOp */ + AML_DEBUGPRINT("Index("); + srcobj = aml_eval_name(env, aml_parse_termobj(env, indent)); + AML_DEBUGPRINT(", "); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + destname1 = aml_parse_termobj(env, indent); + AML_DEBUGPRINT(")"); + aname = aml_create_local_object(); + switch (srcobj->type) { + case aml_t_package: + case aml_t_buffer: + AML_ALLOC_OBJECT(objref, env, aml_t_objref, NULL); + aname->property = objref; + objref->objref.ref = srcobj; + objref->objref.offset = num1; + objref->objref.deref = 0; + break; + default: + AML_DEBUGPRINT("Arg0 of Index should be either " + "buffer or package\n"); + return (aname); + } + + aml_store_to_name(env, objref, destname1); + break; + case 0x89: /* MatchOp *//* XXX Not yet Impremented */ + AML_DEBUGPRINT("Match("); + AML_COPY_OBJECT(obj, env, aml_eval_name(env, + aml_parse_termobj(env, indent)), NULL); + if (obj->type != aml_t_package) { + env->stat = aml_stat_panic; + return (NULL); + } + anum.num.number = 0xffffffff; + match1 = *env->dp; + AML_DEBUGPRINT(", %d", *env->dp); + env->dp++; + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + match2 = *env->dp; + AML_DEBUGPRINT(", %d", *env->dp); + env->dp++; + num2 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + AML_DEBUGPRINT(", "); + start = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + +#define MATCHOP(opnum, arg1, arg2) ((opnum == 0) ? (1) : \ + (opnum == 1) ? ((arg1) == (arg2)) : \ + (opnum == 2) ? ((arg1) <= (arg2)) : \ + (opnum == 3) ? ((arg1) < (arg2)) : \ + (opnum == 4) ? ((arg1) >= (arg2)) : \ + (opnum == 5) ? ((arg1) > (arg2)) : 0 ) + + for (i = start; i < obj->package.elements; i++) { + pkgval = aml_objtonum(env, obj->package.objects[i]); + if (MATCHOP(match1, pkgval, num1) && + MATCHOP(match2, pkgval, num2)) { + anum.num.number = i; + break; + } + } + AML_DEBUGPRINT(")"); + aml_free_object(&obj); + aname = &env->tempname; + env->tempname.property = &env->tempobject; + env->tempobject.num = anum.num; + break; +#undef MATCHOP + case 0x8a ... 0x8d: /* CreateDWordFieldOp */ + widthindex = *(env->dp - 1) - 0x8a; + AML_DEBUGPRINT("%s(", opname[widthindex]); + srcbuf = aml_eval_name(env, aml_parse_termobj(env, indent)); + if (srcbuf == &env->tempobject) { + AML_DEBUGPRINT("NOT NAMEDBUF\n"); + env->stat = aml_stat_panic; + return (NULL); + } + AML_DEBUGPRINT(", "); + index = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + if (widthindex != 3) { + index *= 8; + } + AML_DEBUGPRINT(", "); + newname = aml_parse_namestring(env); + aml_print_namestring(newname); + aml_createfield_generic(env, srcbuf, index, + widthtbl[widthindex], newname); + AML_DEBUGPRINT(")"); + break; + case 0x8e: /* ObjectTypeOp */ + AML_DEBUGPRINT("ObjectType("); + aname = aml_parse_termobj(env, indent); + if (aname == NULL) { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = aml_t_null; + } else { + env->tempobject.type = aml_t_num; + env->tempobject.num.number = aname->property->type; + } + aname = &env->tempname; + AML_DEBUGPRINT(")"); + break; + +#define CMPOP(opname,operation) do { \ + AML_DEBUGPRINT(opname); \ + AML_DEBUGPRINT("("); \ + num1 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + AML_DEBUGPRINT(", "); \ + num2 = aml_objtonum(env, aml_eval_name(env, \ + aml_parse_termobj(env, indent))); \ + aname = &env->tempname; \ + env->tempobject.type = aml_t_num; \ + env->tempobject.num.number = (num1 operation num2) ? 0xffffffff : 0; \ + aname->property = &env->tempobject; \ + AML_DEBUGPRINT(")"); \ +} while(0) + + case 0x90: + CMPOP("LAnd", &&); + break; + case 0x91: + CMPOP("LOr", ||); + break; + case 0x92: + AML_DEBUGPRINT("LNot("); + num1 = aml_objtonum(env, aml_eval_name(env, + aml_parse_termobj(env, indent))); + aname = &env->tempname; + env->tempobject.type = aml_t_num; + env->tempobject.num.number = (!num1) ? 0xffffffff : 0; + aname->property = &env->tempobject; + AML_DEBUGPRINT(")"); + break; + case 0x93: + CMPOP("LEqual", ==); + break; + case 0x94: + CMPOP("LGreater", >); + break; + case 0x95: + CMPOP("LLess", <); + break; + case 0xa0: /* IfOp */ + aname = aml_parse_defif(env, indent); + break; +#if 0 + + case 0xa1: /* ElseOp should not be treated in Main parser + * But If Op */ + aml_parse_defelse(env, indent); + break; +#endif + case 0xa2: /* WhileOp */ + aname = aml_parse_defwhile(env, indent); + break; + case 0xa3: /* NoopOp */ + AML_DEBUGPRINT("Noop"); + break; + case 0xa5: /* BreakOp */ + AML_DEBUGPRINT("Break"); + env->stat = aml_stat_break; + break; + case 0xa4: /* ReturnOp */ + AML_DEBUGPRINT("Return("); + AML_COPY_OBJECT(env->tempname.property, env, aml_eval_name(env, + aml_parse_termobj(env, indent)), NULL); + aname = &env->tempname; + env->stat = aml_stat_return; + AML_DEBUGPRINT(")"); + break; + case 0xcc: /* BreakPointOp */ + /* XXX Not Yet Impremented (Not need?) */ + AML_DEBUGPRINT("BreakPoint"); + break; + default: + AML_SYSERRX(1, "strange opcode 0x%x\n", opcode); + AML_SYSABORT(); + } + + return (aname); +} diff --git a/usr.sbin/acpidump/aml/aml_parse.h b/usr.sbin/acpidump/aml/aml_parse.h new file mode 100644 index 00000000000..b9b55b3eb5c --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_parse.h @@ -0,0 +1,37 @@ +/* $OpenBSD: aml_parse.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Doug Rabson + * 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: aml_parse.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_parse.h,v 1.1 2000/08/24 09:33:08 takawata Exp $ + */ + +#ifndef _AML_PARSE_H_ +#define _AML_PARSE_H_ + +struct aml_name *aml_parse_objectlist(struct aml_environ *, int); +struct aml_name *aml_parse_termobj(struct aml_environ *, int); + +#endif /* !_AML_PARSE_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_region.h b/usr.sbin/acpidump/aml/aml_region.h new file mode 100644 index 00000000000..97c78cfabc4 --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_region.h @@ -0,0 +1,93 @@ +/* $OpenBSD: aml_region.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 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: aml_region.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_region.h,v 1.2 2000/09/20 01:01:27 iwasaki Exp $ + */ + +#ifndef _AML_REGION_H_ +#define _AML_REGION_H_ + +/* + * Note that common part of region I/O is implemented in aml_common.c. + */ + +/* + * Debug macros for region I/O + */ + +#define AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen) \ + AML_DEBUGPRINT("\n[aml_region_read(%d, %d, 0x%x, 0x%x, 0x%x)]\n",\ + regtype, flags, addr, bitoffset, bitlen) + +#define AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, \ + addr, bitoffset, bitlen) \ + AML_DEBUGPRINT("\n[aml_region_read_into_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",\ + regtype, flags, addr, bitoffset, bitlen) + +#define AML_REGION_WRITE_DEBUG(regtype, flags, value, \ + addr, bitoffset, bitlen) \ + AML_DEBUGPRINT("\n[aml_region_write(%d, %d, 0x%x, 0x%x, 0x%x, 0x%x)]\n",\ + regtype, flags, value, addr, bitoffset, bitlen) + +#define AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags, \ + addr, bitoffset, bitlen) \ + AML_DEBUGPRINT("\n[aml_region_write_from_buffer(%d, %d, 0x%x, 0x%x, 0x%x)]\n",\ + regtype, flags, addr, bitoffset, bitlen) + +#define AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen, \ + dflags, daddr, dbitoffset, dbitlen) \ + 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) + +/* + * Region I/O subroutine + */ + +struct aml_environ; + +u_int32_t aml_region_read(struct aml_environ *, int, u_int32_t, + u_int32_t, u_int32_t, u_int32_t); +int aml_region_write(struct aml_environ *, int, u_int32_t, + u_int32_t, u_int32_t, u_int32_t, u_int32_t); +int aml_region_read_into_buffer(struct aml_environ *, int, + u_int32_t, u_int32_t, u_int32_t, + u_int32_t, u_int8_t *); +int aml_region_write_from_buffer(struct aml_environ *, int, + u_int32_t, u_int8_t *, u_int32_t, + u_int32_t, u_int32_t); +int aml_region_bcopy(struct aml_environ *, int, + u_int32_t, u_int32_t, u_int32_t, u_int32_t, + u_int32_t, u_int32_t, u_int32_t, u_int32_t); + +#ifndef _KERNEL +void aml_simulation_regdump(const char *); +extern int aml_debug_prompt_regoutput; +extern int aml_debug_prompt_reginput; +#endif /* !_KERNEL */ + +#endif /* !_AML_REGION_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_status.h b/usr.sbin/acpidump/aml/aml_status.h new file mode 100644 index 00000000000..d6d09be618a --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_status.h @@ -0,0 +1,42 @@ +/* $OpenBSD: aml_status.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Takanori Watanabe + * 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: aml_status.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_status.h,v 1.1 2000/08/24 09:33:08 takawata Exp $ + */ + +#ifndef _AML_STATUS_H_ +#define _AML_STATUS_H_ + +enum aml_status { + aml_stat_none = 0, + aml_stat_return, + aml_stat_break, + aml_stat_panic, + aml_stat_step +}; + +#endif /* !_AML_STATUS_H_ */ diff --git a/usr.sbin/acpidump/aml/aml_store.c b/usr.sbin/acpidump/aml/aml_store.c new file mode 100644 index 00000000000..0fcae246eff --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_store.c @@ -0,0 +1,350 @@ +/* $OpenBSD: aml_store.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_store.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_store.c,v 1.3 2000/11/09 06:24:45 iwasaki Exp $ + */ + +#include <sys/types.h> + +#include <aml/aml_amlmem.h> +#include <aml/aml_common.h> +#include <aml/aml_env.h> +#include <aml/aml_evalobj.h> +#include <aml/aml_name.h> +#include <aml/aml_obj.h> +#include <aml/aml_region.h> +#include <aml/aml_status.h> +#include <aml/aml_store.h> + +#ifndef _KERNEL +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "debug.h" +#else /* _KERNEL */ +#include <sys/systm.h> +#endif /* !_KERNEL */ + +static void +aml_store_to_fieldname(struct aml_environ *env, union aml_object *obj, + struct aml_name *name) +{ + char *buffer; + struct aml_name *wname, *oname, *iname; + struct aml_field *field; + struct aml_opregion *or; + union aml_object tobj, iobj, *tmpobj; + + field = &name->property->field; + oname = env->curname; + iname = NULL; + env->curname = name->parent; + if (field->f.ftype == f_t_field) { + wname = aml_search_name(env, field->f.fld.regname); + if (wname == NULL || + wname->property == NULL || + wname->property->type != aml_t_opregion) { + AML_DEBUGPRINT("Inappropreate Type\n"); + env->stat = aml_stat_panic; + env->curname = oname; + return; + } + or = &wname->property->opregion; + switch (obj->type) { + case aml_t_num: + aml_region_write(env, or->space, field->flags, + obj->num.number, or->offset, + field->bitoffset, field->bitlen); + AML_DEBUGPRINT("[write(%d, 0x%x, 0x%x)]", + or->space, obj->num.number, + or->offset + field->bitoffset / 8); + break; + case aml_t_buffer: + case aml_t_bufferfield: + if (obj->type == aml_t_buffer) { + buffer = obj->buffer.data; + } else { + buffer = obj->bfld.origin; + buffer += obj->bfld.bitoffset / 8; + } + aml_region_write_from_buffer(env, or->space, + field->flags, buffer, or->offset, field->bitoffset, + field->bitlen); + break; + case aml_t_regfield: + if (or->space != obj->regfield.space) { + AML_DEBUGPRINT("aml_store_to_fieldname: " + "Different type of space\n"); + break; + } + aml_region_bcopy(env, obj->regfield.space, + obj->regfield.flags, obj->regfield.offset, + obj->regfield.bitoffset, obj->regfield.bitlen, + field->flags, or->offset, field->bitoffset, + field->bitlen); + break; + default: + AML_DEBUGPRINT("aml_store_to_fieldname: " + "Inappropreate Type of src object\n"); + break; + } + } else if (field->f.ftype == f_t_index) { + iname = aml_search_name(env, field->f.ifld.indexname); + wname = aml_search_name(env, field->f.ifld.dataname); + iobj.type = aml_t_num; + iobj.num.number = field->bitoffset / 8; /* AccessType Boundary */ + + /* read whole values of IndexField */ + aml_store_to_name(env, &iobj, iname); + tmpobj = aml_eval_name(env, wname); + + /* make the values to be written */ + tobj.num = obj->num; + tobj.num.number = aml_adjust_updatevalue(field->flags, + field->bitoffset & 7, field->bitlen, + tmpobj->num.number, obj->num.number); + + /* write the values to IndexField */ + aml_store_to_name(env, &iobj, iname); + aml_store_to_name(env, &tobj, wname); + } + env->curname = oname; +} + +static void +aml_store_to_buffer(struct aml_environ *env, union aml_object *obj, + union aml_object *buf, int offset) +{ + int size; + int bitlen; + + switch (obj->type) { + case aml_t_num: + if (offset > buf->buffer.size) { + aml_realloc_object(buf, offset); + } + buf->buffer.data[offset] = obj->num.number & 0xff; + AML_DEBUGPRINT("[Store number 0x%x to buffer]", + obj->num.number & 0xff); + break; + case aml_t_string: + size = strlen(obj->str.string); + if (buf->buffer.size - offset < size) { + aml_realloc_object(buf, offset + size + 1); + } + strcpy(&buf->buffer.data[offset], obj->str.string); + AML_DEBUGPRINT("[Store string to buffer]"); + break; + case aml_t_buffer: + bzero(buf->buffer.data, buf->buffer.size); + if (obj->buffer.size > buf->buffer.size) { + size = buf->buffer.size; + } else { + size = obj->buffer.size; + } + bcopy(obj->buffer.data, buf->buffer.data, size); + break; + case aml_t_regfield: + bitlen = (buf->buffer.size - offset) * 8; + if (bitlen > obj->regfield.bitlen) { + bitlen = obj->regfield.bitlen; + } + aml_region_read_into_buffer(env, obj->regfield.space, + obj->regfield.flags, obj->regfield.offset, + obj->regfield.bitoffset, bitlen, + buf->buffer.data + offset); + break; + default: + goto not_yet; + } + return; +not_yet: + AML_DEBUGPRINT("[XXX not supported yet]"); +} + + +void +aml_store_to_object(struct aml_environ *env, union aml_object *src, + union aml_object * dest) +{ + char *buffer, *srcbuf; + int offset, bitlen; + + switch (dest->type) { + case aml_t_num: + if (src->type == aml_t_num) { + dest->num = src->num; + AML_DEBUGPRINT("[Store number 0x%x]", src->num.number); + } else { + env->stat = aml_stat_panic; + } + break; + case aml_t_string: + case aml_t_package: + break; + case aml_t_buffer: + aml_store_to_buffer(env, src, dest, 0); + break; + case aml_t_bufferfield: + buffer = dest->bfld.origin; + offset = dest->bfld.bitoffset; + bitlen = dest->bfld.bitlen; + + switch (src->type) { + case aml_t_num: + if (aml_bufferfield_write(src->num.number, buffer, offset, bitlen)) { + AML_DEBUGPRINT("aml_bufferfield_write() failed\n"); + } + break; + case aml_t_buffer: + case aml_t_bufferfield: + if (src->type == aml_t_buffer) { + srcbuf = src->buffer.data; + } else { + srcbuf = src->bfld.origin; + srcbuf += src->bfld.bitoffset / 8; + } + bcopy(srcbuf, buffer, bitlen / 8); + break; + case aml_t_regfield: + aml_region_read_into_buffer(env, src->regfield.space, + src->regfield.flags, src->regfield.offset, + src->regfield.bitoffset, src->regfield.bitlen, + buffer); + break; + default: + AML_DEBUGPRINT("not implemented yet"); + break; + } + break; + case aml_t_debug: + aml_showobject(src); + break; + default: + AML_DEBUGPRINT("[Unimplemented %d]", dest->type); + break; + } +} + +static void +aml_store_to_objref(struct aml_environ *env, union aml_object *obj, + union aml_object *r) +{ + int offset; + union aml_object *ref; + + if (r->objref.ref == NULL) { + r->objref.ref = aml_alloc_object(obj->type, NULL); /* XXX */ + r->objref.nameref->property = r->objref.ref; + } + ref = r->objref.ref; + + switch (ref->type) { + case aml_t_buffer: + offset = r->objref.offset; + aml_store_to_buffer(env, obj, ref, r->objref.offset); + break; + case aml_t_package: + offset = r->objref.offset; + if (r->objref.ref->package.elements < offset) { + aml_realloc_object(ref, offset); + } + if (ref->package.objects[offset] == NULL) { + ref->package.objects[offset] = aml_copy_object(env, obj); + } else { + aml_store_to_object(env, obj, ref->package.objects[offset]); + } + break; + default: + aml_store_to_object(env, obj, ref); + break; + } +} + +/* + * Store to Named object + */ +void +aml_store_to_name(struct aml_environ *env, union aml_object *obj, + struct aml_name *name) +{ + struct aml_name *wname; + + if (env->stat == aml_stat_panic) { + return; + } + if (name == NULL || obj == NULL) { + AML_DEBUGPRINT("[Try to store no existant name ]"); + return; + } + if (name->property == NULL) { + name->property = aml_copy_object(env, obj); + AML_DEBUGPRINT("[Copy number 0x%x]", obj->num.number); + return; + } + if (name->property->type == aml_t_namestr) { + wname = aml_search_name(env, name->property->nstr.dp); + name = wname; + } + if (name == NULL) { + env->stat = aml_stat_panic; + return; + } + if (name->property == NULL || name->property->type == aml_t_null) { + name->property = aml_copy_object(env, obj); + AML_DEBUGPRINT("[Copy number 0x%x]", obj->num.number); + return; + } + /* Writes to constant object are not allowed */ + if (name->property != NULL && name->property->type == aml_t_num && + name->property->num.constant == 1) { + return; + } + /* try to dereference */ + if (obj->type == aml_t_objref && obj->objref.deref == 0) { + AML_DEBUGPRINT("Source object isn't dereferenced yet, " + "try to dereference anyway\n"); + obj->objref.deref = 1; + obj = aml_eval_objref(env, obj); + } + switch (name->property->type) { + case aml_t_field: + aml_store_to_fieldname(env, obj, name); + break; + case aml_t_objref: + aml_store_to_objref(env, obj, name->property); + break; + case aml_t_num: + if (name == &env->tempname) + break; + default: + aml_store_to_object(env, obj, name->property); + break; + } +} diff --git a/usr.sbin/acpidump/aml/aml_store.h b/usr.sbin/acpidump/aml/aml_store.h new file mode 100644 index 00000000000..7dbaf70b84e --- /dev/null +++ b/usr.sbin/acpidump/aml/aml_store.h @@ -0,0 +1,40 @@ +/* $OpenBSD: aml_store.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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: aml_store.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_store.h,v 1.1 2000/08/24 09:33:08 takawata Exp $ + */ + +#ifndef _AML_STORE_H_ +#define _AML_STORE_H_ + +void aml_store_to_name(struct aml_environ *, union aml_object *, + struct aml_name *); +void aml_store_to_object(struct aml_environ *, union aml_object *, + union aml_object *); + +#endif /* _AML_STORE_H_ */ diff --git a/usr.sbin/acpidump/aml_dump.c b/usr.sbin/acpidump/aml_dump.c new file mode 100644 index 00000000000..11acc4858e1 --- /dev/null +++ b/usr.sbin/acpidump/aml_dump.c @@ -0,0 +1,61 @@ +/* $OpenBSD: aml_dump.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 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: aml_dump.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/acpidump/aml_dump.c,v 1.3 2000/11/08 02:37:00 iwasaki Exp $ + */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#include "acpidump.h" + +char *aml_dumpfile = NULL; + +void +aml_dump(struct ACPIsdt *dsdp) +{ + int fd; + mode_t mode; + + if (aml_dumpfile == NULL) { + return; + } + + mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + fd = open(aml_dumpfile, O_WRONLY | O_CREAT | O_TRUNC, mode); + if (fd == -1) { + return; + } + write(fd, dsdp, SIZEOF_SDT_HDR); + write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); + close(fd); +} + diff --git a/usr.sbin/acpidump/asl_dump.c b/usr.sbin/acpidump/asl_dump.c new file mode 100644 index 00000000000..25cea02bb05 --- /dev/null +++ b/usr.sbin/acpidump/asl_dump.c @@ -0,0 +1,1281 @@ +/* $OpenBSD: asl_dump.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * Copyright (c) 1999 Doug Rabson + * Copyright (c) 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: asl_dump.c,v 1.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/acpidump/asl_dump.c,v 1.5 2001/10/23 14:53:58 takawata Exp $ + */ + +#include <sys/param.h> + +#include <assert.h> +#include <err.h> +#include <stdio.h> + +#include "acpidump.h" + +#include "aml/aml_env.h" + +struct aml_environ asl_env; + +static u_int32_t +asl_dump_pkglength(u_int8_t **dpp) +{ + u_int8_t *dp; + u_int32_t pkglength; + + dp = *dpp; + pkglength = *dp++; + switch (pkglength >> 6) { + case 0: + break; + case 1: + pkglength = (pkglength & 0xf) + (dp[0] << 4); + dp += 1; + break; + case 2: + pkglength = (pkglength & 0xf) + (dp[0] << 4) + (dp[1] << 12); + dp += 2; + break; + case 3: + pkglength = (pkglength & 0xf) + + (dp[0] << 4) + (dp[1] << 12) + (dp[2] << 20); + dp += 3; + break; + } + + *dpp = dp; + return (pkglength); +} + +static void +print_nameseg(u_int8_t *dp) +{ + + if (dp[3] != '_') + printf("%c%c%c%c", dp[0], dp[1], dp[2], dp[3]); + else if (dp[2] != '_') + printf("%c%c%c_", dp[0], dp[1], dp[2]); + else if (dp[1] != '_') + printf("%c%c__", dp[0], dp[1]); + else if (dp[0] != '_') + printf("%c___", dp[0]); +} + +static u_int8_t +asl_dump_bytedata(u_int8_t **dpp) +{ + u_int8_t *dp; + u_int8_t data; + + dp = *dpp; + data = dp[0]; + *dpp = dp + 1; + return (data); +} + +static u_int16_t +asl_dump_worddata(u_int8_t **dpp) +{ + u_int8_t *dp; + u_int16_t data; + + dp = *dpp; + data = dp[0] + (dp[1] << 8); + *dpp = dp + 2; + return (data); +} + +static u_int32_t +asl_dump_dworddata(u_int8_t **dpp) +{ + u_int8_t *dp; + u_int32_t data; + + dp = *dpp; + data = dp[0] + (dp[1] << 8) + (dp[2] << 16) + (dp[3] << 24); + *dpp = dp + 4; + return (data); +} + +static u_int8_t * +asl_dump_namestring(u_int8_t **dpp) +{ + u_int8_t *dp; + u_int8_t *name; + + dp = *dpp; + name = dp; + if (dp[0] == '\\') + dp++; + else if (dp[0] == '^') + while (dp[0] == '^') + dp++; + if (dp[0] == 0x00) /* NullName */ + dp++; + else if (dp[0] == 0x2e) /* DualNamePrefix */ + dp += 1 + 4 + 4;/* NameSeg, NameSeg */ + else if (dp[0] == 0x2f) { /* MultiNamePrefix */ + int segcount = dp[1]; + dp += 1 + 1 + segcount * 4; /* segcount * NameSeg */ + } else + dp += 4; /* NameSeg */ + + *dpp = dp; + return (name); +} + +static void +print_namestring(u_int8_t *dp) +{ + + if (dp[0] == '\\') { + putchar(dp[0]); + dp++; + } else if (dp[0] == '^') { + while (dp[0] == '^') { + putchar(dp[0]); + dp++; + } + } + if (dp[0] == 0x00) { /* NullName */ + /* printf("<null>"); */ + dp++; + } else if (dp[0] == 0x2e) { /* DualNamePrefix */ + print_nameseg(dp + 1); + putchar('.'); + print_nameseg(dp + 5); + } else if (dp[0] == 0x2f) { /* MultiNamePrefix */ + int segcount = dp[1]; + int i; + for (i = 0, dp += 2; i < segcount; i++, dp += 4) { + if (i > 0) + putchar('.'); + print_nameseg(dp); + } + } else /* NameSeg */ + print_nameseg(dp); +} + +static void +print_indent(int indent) +{ + int i; + + for (i = 0; i < indent; i++) + printf(" "); +} + +#define ASL_ENTER_SCOPE(dp_orig, old_name) do { \ + u_int8_t *dp_copy; \ + u_int8_t *name; \ + old_name = asl_env.curname; \ + dp_copy = dp_orig; \ + name = asl_dump_namestring(&dp_copy); \ + asl_env.curname = aml_search_name(&asl_env, name); \ +} while(0) + +#define ASL_LEAVE_SCOPE(old_name) do { \ + asl_env.curname = old_name; \ +} while(0) + +#define ASL_CREATE_LOCALNAMEOBJ(dp) do { \ + if(scope_within_method){ \ + aml_create_name(&asl_env, dp); \ + } \ +}while(0); + +static void +asl_dump_defscope(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int32_t pkglength; + struct aml_name *oname; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + + printf("Scope("); + ASL_ENTER_SCOPE(dp, oname); + asl_dump_termobj(&dp, indent); + printf(") {\n"); + end = start + pkglength; + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + ASL_LEAVE_SCOPE(oname); + *dpp = dp; +} + +static void +asl_dump_defbuffer(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int32_t pkglength; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + printf("Buffer("); + asl_dump_termobj(&dp, indent); + printf(") {"); + while (dp < end) { + printf("0x%x", *dp++); + if (dp < end) + printf(", "); + } + printf(" }"); + + *dpp = dp; +} + +static void +asl_dump_defpackage(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int8_t numelements; + u_int32_t pkglength; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + numelements = asl_dump_bytedata(&dp); + end = start + pkglength; + printf("Package(0x%x) {\n", numelements); + while (dp < end) { + print_indent(indent + 1); + asl_dump_termobj(&dp, indent + 1); + printf(",\n"); + } + + print_indent(indent); + printf("}"); + + dp = end; + + *dpp = dp; +} + +int scope_within_method = 0; + +static void +asl_dump_defmethod(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int8_t flags; + u_int32_t pkglength; + struct aml_name *oname; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + + printf("Method("); + ASL_ENTER_SCOPE(dp, oname); + asl_dump_termobj(&dp, indent); + flags = *dp++; + if (flags) { + printf(", %d", flags & 7); + if (flags & 8) { + printf(", Serialized"); + } + } + printf(") {\n"); + end = start + pkglength; + scope_within_method = 1; + asl_dump_objectlist(&dp, end, indent + 1); + scope_within_method = 0; + print_indent(indent); + printf("}"); + + assert(dp == end); + ASL_LEAVE_SCOPE(oname); + *dpp = dp; +} + + +static void +asl_dump_defopregion(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + const char *regions[] = { + "SystemMemory", + "SystemIO", + "PCI_Config", + "EmbeddedControl", + "SMBus", + }; + + dp = *dpp; + printf("OperationRegion("); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); /* Name */ + printf(", %s, ", regions[*dp++]); /* Space */ + asl_dump_termobj(&dp, indent); /* Offset */ + printf(", "); + asl_dump_termobj(&dp, indent); /* Length */ + printf(")"); + + *dpp = dp; +} + +static const char *accessnames[] = { + "AnyAcc", + "ByteAcc", + "WordAcc", + "DWordAcc", + "BlockAcc", + "SMBSendRecvAcc", + "SMBQuickAcc" +}; + +static int +asl_dump_field(u_int8_t **dpp, u_int32_t offset) +{ + u_int8_t *dp; + u_int8_t *name; + u_int8_t access, attribute; + u_int32_t width; + + dp = *dpp; + switch (*dp) { + case '\\': + case '^': + case 'A' ... 'Z': + case '_': + case '.': + case '/': + ASL_CREATE_LOCALNAMEOBJ(dp); + name = asl_dump_namestring(&dp); + width = asl_dump_pkglength(&dp); + offset += width; + print_namestring(name); + printf(",\t%d", width); + break; + case 0x00: + dp++; + width = asl_dump_pkglength(&dp); + offset += width; + if ((offset % 8) == 0) { + printf("Offset(0x%x)", offset / 8); + } else { + printf(",\t%d", width); + } + break; + case 0x01: + access = dp[1]; + attribute = dp[2]; + dp += 3; + printf("AccessAs(%s, %d)", accessnames[access], attribute); + break; + } + + *dpp = dp; + return (offset); +} + +static void +asl_dump_fieldlist(u_int8_t **dpp, u_int8_t *end, int indent) +{ + u_int8_t *dp; + u_int32_t offset; + + dp = *dpp; + offset = 0; + while (dp < end) { + print_indent(indent); + offset = asl_dump_field(&dp, offset); + if (dp < end) + printf(",\n"); + else + printf("\n"); + } + + *dpp = dp; +} + +static void +asl_dump_deffield(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int8_t flags; + u_int32_t pkglength; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("Field("); + asl_dump_termobj(&dp, indent); /* Name */ + flags = asl_dump_bytedata(&dp); + printf(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + asl_dump_fieldlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + *dpp = dp; +} + +static void +asl_dump_defindexfield(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int8_t flags; + u_int32_t pkglength; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("IndexField("); + asl_dump_termobj(&dp, indent); /* Name1 */ + printf(", "); + asl_dump_termobj(&dp, indent); /* Name2 */ + flags = asl_dump_bytedata(&dp); + printf(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + asl_dump_fieldlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + *dpp = dp; +} + +static void +asl_dump_defbankfield(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int8_t flags; + u_int32_t pkglength; + static const char *lockrules[] = {"NoLock", "Lock"}; + static const char *updaterules[] = {"Preserve", "WriteAsOnes", + "WriteAsZeros", "*Error*"}; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + printf("BankField("); + asl_dump_termobj(&dp, indent); /* Name1 */ + printf(", "); + asl_dump_termobj(&dp, indent); /* Name2 */ + printf(", "); + asl_dump_termobj(&dp, indent); /* BankValue */ + flags = asl_dump_bytedata(&dp); + printf(", %s, %s, %s) {\n", + accessnames[flags & 0xf], + lockrules[(flags >> 4) & 1], + updaterules[(flags >> 5) & 3]); + asl_dump_fieldlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + *dpp = dp; +} + +static void +asl_dump_defdevice(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int32_t pkglength; + struct aml_name *oname; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("Device("); + ASL_ENTER_SCOPE(dp, oname); + asl_dump_termobj(&dp, indent); + printf(") {\n"); + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + ASL_LEAVE_SCOPE(oname); + *dpp = dp; +} + +static void +asl_dump_defprocessor(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int8_t procid; + u_int8_t pblklen; + u_int32_t pkglength; + u_int32_t pblkaddr; + struct aml_name *oname; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("Processor("); + ASL_ENTER_SCOPE(dp, oname); + asl_dump_termobj(&dp, indent); + procid = asl_dump_bytedata(&dp); + pblkaddr = asl_dump_dworddata(&dp); + pblklen = asl_dump_bytedata(&dp); + printf(", %d, 0x%x, 0x%x) {\n", procid, pblkaddr, pblklen); + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + ASL_LEAVE_SCOPE(oname); + *dpp = dp; +} + +static void +asl_dump_defpowerres(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int8_t systemlevel; + u_int16_t resourceorder; + u_int32_t pkglength; + struct aml_name *oname; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("PowerResource("); + ASL_ENTER_SCOPE(dp, oname); + asl_dump_termobj(&dp, indent); + systemlevel = asl_dump_bytedata(&dp); + resourceorder = asl_dump_worddata(&dp); + printf(", %d, %d) {\n", systemlevel, resourceorder); + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + ASL_LEAVE_SCOPE(oname); + *dpp = dp; +} + +static void +asl_dump_defthermalzone(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int32_t pkglength; + struct aml_name *oname; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("ThermalZone("); + ASL_ENTER_SCOPE(dp, oname); + asl_dump_termobj(&dp, indent); + printf(") {\n"); + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + ASL_LEAVE_SCOPE(oname); + *dpp = dp; +} + +static void +asl_dump_defif(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int32_t pkglength; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("If("); + asl_dump_termobj(&dp, indent); + printf(") {\n"); + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + *dpp = dp; +} + +static void +asl_dump_defelse(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int32_t pkglength; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("Else {\n"); + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + *dpp = dp; +} + +static void +asl_dump_defwhile(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *start; + u_int8_t *end; + u_int32_t pkglength; + + dp = *dpp; + start = dp; + pkglength = asl_dump_pkglength(&dp); + end = start + pkglength; + + printf("While("); + asl_dump_termobj(&dp, indent); + printf(") {\n"); + asl_dump_objectlist(&dp, end, indent + 1); + print_indent(indent); + printf("}"); + + assert(dp == end); + + *dpp = dp; +} + +/* + * Public interfaces + */ +void +asl_dump_termobj(u_int8_t **dpp, int indent) +{ + u_int8_t *dp; + u_int8_t *name; + u_int8_t opcode; + struct aml_name *method; + const char *matchstr[] = { + "MTR", "MEQ", "MLE", "MLT", "MGE", "MGT", + }; + +#define OPTARG() do { \ + printf(", "); \ + if (*dp == 0x00) { \ + dp++; \ + } else { \ + asl_dump_termobj(&dp, indent); \ + } \ +} while (0) + + dp = *dpp; + opcode = *dp++; + switch (opcode) { + case '\\': + case '^': + case 'A' ... 'Z': + case '_': + case '.': + case '/': + dp--; + print_namestring((name = asl_dump_namestring(&dp))); + if (scope_within_method == 1) { + method = aml_search_name(&asl_env, name); + if (method != NULL && method->property != NULL && + method->property->type == aml_t_method) { + int i, argnum; + + argnum = method->property->meth.argnum & 7; + printf("("); + for (i = 0; i < argnum; i++) { + asl_dump_termobj(&dp, indent); + if (i < (argnum-1)) { + printf(", "); + } + } + printf(")"); + } + } + break; + case 0x0a: /* BytePrefix */ + printf("0x%x", asl_dump_bytedata(&dp)); + break; + case 0x0b: /* WordPrefix */ + printf("0x%04x", asl_dump_worddata(&dp)); + break; + case 0x0c: /* DWordPrefix */ + printf("0x%08x", asl_dump_dworddata(&dp)); + break; + case 0x0d: /* StringPrefix */ + printf("\"%s\"", (const char *) dp); + while (*dp) + dp++; + dp++; /* NUL terminate */ + break; + case 0x00: /* ZeroOp */ + printf("Zero"); + break; + case 0x01: /* OneOp */ + printf("One"); + break; + case 0xff: /* OnesOp */ + printf("Ones"); + break; + case 0x06: /* AliasOp */ + printf("Alias("); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x08: /* NameOp */ + printf("Name("); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x10: /* ScopeOp */ + asl_dump_defscope(&dp, indent); + break; + case 0x11: /* BufferOp */ + asl_dump_defbuffer(&dp, indent); + break; + case 0x12: /* PackageOp */ + asl_dump_defpackage(&dp, indent); + break; + case 0x14: /* MethodOp */ + asl_dump_defmethod(&dp, indent); + break; + case 0x5b: /* ExtOpPrefix */ + opcode = *dp++; + switch (opcode) { + case 0x01: /* MutexOp */ + printf("Mutex("); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(", %d)", *dp++); + break; + case 0x02: /* EventOp */ + printf("Event("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x12: /* CondRefOfOp */ + printf("CondRefOf("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x13: /* CreateFieldOp */ + printf("CreateField("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(", "); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x20: /* LoadOp */ + printf("Load("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x21: /* StallOp */ + printf("Stall("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x22: /* SleepOp */ + printf("Sleep("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x23: /* AcquireOp */ + printf("Acquire("); + asl_dump_termobj(&dp, indent); + printf(", 0x%x)", asl_dump_worddata(&dp)); + break; + case 0x24: /* SignalOp */ + printf("Signal("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x25: /* WaitOp */ + printf("Wait("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x26: /* ResetOp */ + printf("Reset("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x27: /* ReleaseOp */ + printf("Release("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x28: /* FromBCDOp */ + printf("FromBCD("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x29: /* ToBCDOp */ + printf("ToBCD("); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x2a: /* UnloadOp */ + printf("Unload("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x30: + printf("Revision"); + break; + case 0x31: + printf("Debug"); + break; + case 0x32: /* FatalOp */ + printf("Fatal("); + printf("0x%x, ", asl_dump_bytedata(&dp)); + printf("0x%x, ", asl_dump_dworddata(&dp)); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x80: /* OpRegionOp */ + asl_dump_defopregion(&dp, indent); + break; + case 0x81: /* FieldOp */ + asl_dump_deffield(&dp, indent); + break; + case 0x82: /* DeviceOp */ + asl_dump_defdevice(&dp, indent); + break; + case 0x83: /* ProcessorOp */ + asl_dump_defprocessor(&dp, indent); + break; + case 0x84: /* PowerResOp */ + asl_dump_defpowerres(&dp, indent); + break; + case 0x85: /* ThermalZoneOp */ + asl_dump_defthermalzone(&dp, indent); + break; + case 0x86: /* IndexFieldOp */ + asl_dump_defindexfield(&dp, indent); + break; + case 0x87: /* BankFieldOp */ + asl_dump_defbankfield(&dp, indent); + break; + default: + errx(1, "strange opcode 0x5b, 0x%x\n", opcode); + } + break; + case 0x68 ... 0x6e: /* ArgN */ + printf("Arg%d", opcode - 0x68); + break; + case 0x60 ... 0x67: + printf("Local%d", opcode - 0x60); + break; + case 0x70: /* StoreOp */ + printf("Store("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x71: /* RefOfOp */ + printf("RefOf("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x72: /* AddOp */ + printf("Add("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x73: /* ConcatenateOp */ + printf("Concatenate("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x74: /* SubtractOp */ + printf("Subtract("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x75: /* IncrementOp */ + printf("Increment("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x76: /* DecrementOp */ + printf("Decrement("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x77: /* MultiplyOp */ + printf("Multiply("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x78: /* DivideOp */ + printf("Divide("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + OPTARG(); + printf(")"); + break; + case 0x79: /* ShiftLeftOp */ + printf("ShiftLeft("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x7a: /* ShiftRightOp */ + printf("ShiftRight("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x7b: /* AndOp */ + printf("And("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x7c: /* NAndOp */ + printf("NAnd("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x7d: /* OrOp */ + printf("Or("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x7e: /* NOrOp */ + printf("NOr("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x7f: /* XOrOp */ + printf("XOr("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x80: /* NotOp */ + printf("Not("); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x81: /* FindSetLeftBitOp */ + printf("FindSetLeftBit("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x82: /* FindSetRightBitOp */ + printf("FindSetRightBit("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x83: /* DerefOp */ + printf("DerefOf("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x86: /* NotifyOp */ + printf("Notify("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x87: /* SizeOfOp */ + printf("SizeOf("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x88: /* IndexOp */ + printf("Index("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + OPTARG(); + printf(")"); + break; + case 0x89: /* MatchOp */ + printf("Match("); + asl_dump_termobj(&dp, indent); + printf(", %s, ", matchstr[*dp++]); + asl_dump_termobj(&dp, indent); + printf(", %s, ", matchstr[*dp++]); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x8a: /* CreateDWordFieldOp */ + printf("CreateDWordField("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(", "); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x8b: /* CreateWordFieldOp */ + printf("CreateWordField("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(", "); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x8c: /* CreateByteFieldOp */ + printf("CreateByteField("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(", "); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x8d: /* CreateBitFieldOp */ + printf("CreateBitField("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(", "); + ASL_CREATE_LOCALNAMEOBJ(dp); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x8e: /* ObjectTypeOp */ + printf("ObjectType("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x90: + printf("LAnd("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x91: + printf("LOr("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x92: + printf("LNot("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x93: + printf("LEqual("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x94: + printf("LGreater("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0x95: + printf("LLess("); + asl_dump_termobj(&dp, indent); + printf(", "); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0xa0: /* IfOp */ + asl_dump_defif(&dp, indent); + break; + case 0xa1: /* ElseOp */ + asl_dump_defelse(&dp, indent); + break; + case 0xa2: /* WhileOp */ + asl_dump_defwhile(&dp, indent); + break; + case 0xa3: /* NoopOp */ + printf("Noop"); + break; + case 0xa5: /* BreakOp */ + printf("Break"); + break; + case 0xa4: /* ReturnOp */ + printf("Return("); + asl_dump_termobj(&dp, indent); + printf(")"); + break; + case 0xcc: /* BreakPointOp */ + printf("BreakPoint"); + break; + default: + errx(1, "strange opcode 0x%x\n", opcode); + } + + *dpp = dp; +} + +void +asl_dump_objectlist(u_int8_t **dpp, u_int8_t *end, int indent) +{ + u_int8_t *dp; + + dp = *dpp; + while (dp < end) { + print_indent(indent); + asl_dump_termobj(&dp, indent); + printf("\n"); + } + + *dpp = dp; +} diff --git a/usr.sbin/acpidump/debug.h b/usr.sbin/acpidump/debug.h new file mode 100644 index 00000000000..db645ca1405 --- /dev/null +++ b/usr.sbin/acpidump/debug.h @@ -0,0 +1,37 @@ +/* $OpenBSD: debug.h,v 1.1 2005/06/02 20:09:39 tholo Exp $ */ +/*- + * 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.1 2005/06/02 20:09:39 tholo Exp $ + * $FreeBSD: src/usr.sbin/acpi/amldb/debug.h,v 1.1.1.1 2000/08/31 14:45:00 iwasaki Exp $ + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +void aml_dbgr(struct aml_environ *, struct aml_environ *); + +#endif /* !_DEBUG_H_ */ |