diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/acpiscan/Makefile | 17 | ||||
-rw-r--r-- | usr.sbin/acpiscan/acpiscan.8 | 65 | ||||
-rw-r--r-- | usr.sbin/acpiscan/acpiscan.c | 619 | ||||
-rw-r--r-- | usr.sbin/acpiscan/oslib.c | 441 | ||||
-rw-r--r-- | usr.sbin/acpiscan/oslib.h | 205 |
6 files changed, 1349 insertions, 2 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index f3db1998404..95e625e2e43 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.129 2006/10/29 18:06:07 norby Exp $ +# $OpenBSD: Makefile,v 1.130 2006/11/03 19:33:56 marco Exp $ .include <bsd.own.mk> -SUBDIR= ac accton acpid acpidump adduser amd apm apmd arp authpf \ +SUBDIR= ac accton acpid acpidump acpiscan adduser amd apm apmd arp authpf \ bgpctl bgpd bind chroot config cron dev_mkdb dhcpd dhcrelay \ dvmrpctl dvmrpd \ edquota eeprom fdformat ftp-proxy gpioctl hostapd hotplugd httpd \ diff --git a/usr.sbin/acpiscan/Makefile b/usr.sbin/acpiscan/Makefile new file mode 100644 index 00000000000..2569b8f5a4e --- /dev/null +++ b/usr.sbin/acpiscan/Makefile @@ -0,0 +1,17 @@ +# $OpenBSD: Makefile,v 1.1 2006/11/03 19:33:56 marco Exp $ + +.if (${MACHINE} == "i386") || (${MACHINE} == "amd64") +PROG= acpiscan +SRCS= acpiscan.c oslib.c +.else +NOPROG= yes +.endif + +MAN= acpiscan.8 + +CFLAGS+=-I${.CURDIR} +LDADD=-l${MACHINE} + +BINDIR?=/usr/sbin + +.include <bsd.prog.mk> diff --git a/usr.sbin/acpiscan/acpiscan.8 b/usr.sbin/acpiscan/acpiscan.8 new file mode 100644 index 00000000000..9daba1eff6d --- /dev/null +++ b/usr.sbin/acpiscan/acpiscan.8 @@ -0,0 +1,65 @@ +.\" $OpenBSD: acpiscan.8,v 1.1 2006/11/03 19:33:56 marco Exp $ +.\" +.\" Copyright (c) 2006 Marco Peereboom +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.Dd November 3, 2006 +.Dt ACPISCAN 8 +.Os +.Sh NAME +.Nm acpiscan +.Nd ACPI table dump utility +.Sh SYNOPSIS +.Nm acpiscan +.Bk -words +.Op Fl D filename +.Op Fl f filename +.Ek +.Sh DESCRIPTION +Dump relevant ACPI tables. For example: APIC, RSDT, DSDT etc +.Pp +The options are as follows: +.Bl -tag -width Ds +.It -D filename +Dump the tables to human readable format from the supplied filename. +The input file has to be a raw dump from the BIOS region. +.It Fl f filename +Dump BIOS memory region that contains ACPI tables and AML into multiple +files where the name starts with the supplied filename. This dump can be +dumped in human readable format with the -D command. +.El +.Pp +Omitting these options will cause the program to dump the ACPI tables drectly +from the BIOS memory region as human readable format. +.Sh SEE ALSO +.Xr acpi 4 +.Sh HISTORY +The +.Nm +command first appeared in +.Ox 4.1 . +.Sh AUTHORS +This +.Nm +utility was written by +.An Jordan Hargrave Aq jordan@openbsd.org . diff --git a/usr.sbin/acpiscan/acpiscan.c b/usr.sbin/acpiscan/acpiscan.c new file mode 100644 index 00000000000..e0249038c13 --- /dev/null +++ b/usr.sbin/acpiscan/acpiscan.c @@ -0,0 +1,619 @@ +/* $OpenBSD: acpiscan.c,v 1.1 2006/11/03 19:33:56 marco Exp $ */ +/* + * Copyright (c) 2006 Jordan Hargrave <jordan@openbsd.org> + * + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include "oslib.h" + +static const char *savename; + +#define ACPI_LAPIC 0x00 +#define ACPI_IOAPIC 0x01 +#define ACPI_INTSRC 0x02 +#define ACPI_NMISRC 0x03 +#define ACPI_LAPICNMI 0x04 + +#define MPC_CPU 0x00 +#define MPC_BUS 0x01 +#define MPC_APIC 0x02 +#define MPC_INT 0x03 +#define MPC_LINT 0x04 + +/* MPBIOS Structures */ +typedef struct _mps_root +{ + char mph_signature[4]; /* _MP_ */ + uint32_t mph_physaddr; + uint8_t mph_length; + uint8_t mph_spec; + uint8_t mph_cksum; + uint8_t mph_feature[5]; +} PACKED mps_root; + +typedef struct _mps_header +{ + char mpc_signature[4]; + uint16_t mpc_length; + uint8_t mpc_spec; + uint8_t mpc_cksum; + char mpc_oem[8]; + char mpc_product[12]; + uint32_t mpc_oemptr; + uint16_t mpc_oemsize; + uint16_t mpc_oemcount; + uint32_t mpc_lapic; + uint32_t reserved; +} PACKED mps_header; + +typedef struct _mps_cpu +{ + uint8_t type; + uint8_t apicid; + uint8_t apicver; + uint8_t cpuflag; + uint32_t cpufeature; + uint32_t featureflag; + uint32_t reserved[2]; +} PACKED mps_cpu; + +typedef struct _mps_bus +{ + uint8_t type; + uint8_t busid; + char bustype[6]; +} PACKED mps_bus; + +typedef struct _mps_ioapic +{ + uint8_t type; + uint8_t apicid; + uint8_t apicver; + uint8_t flags; + uint32_t apicaddr; +} PACKED mps_ioapic; + +typedef struct _mps_intsrc +{ + uint8_t type; + uint8_t irqtype; + uint16_t irqflag; + uint8_t srcbus; + uint8_t srcbusirq; + uint8_t dstapic; + uint8_t dstirq; +} PACKED mps_intsrc; + +typedef struct _mps_lintsrc +{ + uint8_t type; + uint8_t irqtype; + uint16_t irqflag; + uint8_t srcbus; + uint8_t srcbusirq; + uint8_t dstapic; + uint8_t dstapiclint; +} PACKED mps_lintsrc; + +typedef union _mps_entry +{ + uint8_t type; + mps_cpu m_cpu; + mps_bus m_bus; + mps_ioapic m_ioapic; + mps_intsrc m_int; + mps_lintsrc m_lint; +} PACKED mps_entry; + +/* ACPI Structures */ +typedef struct _acpi_table_rsdp +{ + char signature[8]; + uint8_t checksum; + char oem_id[6]; + uint8_t revision; + uint32_t rsdt_address; + uint32_t length; + uint64_t xsdt_address; + uint8_t xchecksum; + uint8_t reserved[3]; +} PACKED acpi_table_rsdp; + +typedef struct _acpi_table_header +{ + uint8_t sig[4]; + uint32_t length; + uint8_t rev; + uint8_t checksum; + uint8_t oem[6]; + uint8_t oem_table[8]; + uint32_t oem_rev; + char asl_compiler_id[4]; + uint32_t asl_compiler_rev; +} PACKED acpi_table_header; + +typedef struct _acpi_table_madt +{ + uint32_t local_apic_addr; + uint32_t compat; +} PACKED acpi_table_madt; + +typedef struct _acpi_table_entry_header +{ + uint8_t type; + uint8_t length; +} PACKED acpi_table_entry_header; + +typedef struct _acpi_facp +{ + uint32_t facs; + uint32_t dsdt; + uint8_t model; + uint8_t resvd; + uint16_t sciint; + uint32_t smicmd; + uint8_t enable; + uint8_t disable; + uint8_t s4bios; + uint8_t resvd2; + uint32_t pm1a_evt; + uint32_t pm1b_evt; + uint32_t pm1a_cnt; + uint32_t pm1b_cnt; + uint32_t pm2_cnt; + uint32_t pm_tmr; + uint32_t gpe0; + uint32_t gpe1; + uint8_t pm1_evt_len; + uint8_t pm1_cnt_len; + uint8_t pm2_cnt_len; + uint8_t pm_tm_len; + uint8_t gpe0_len; + uint8_t gpe1_len; + uint8_t gpe1_base; + uint8_t resvd3; + uint16_t lvl2; + uint16_t lvl3; + uint16_t size; + uint16_t stride; + uint8_t offset; + uint8_t width; + uint8_t day; + uint8_t mon; + uint8_t century; + uint16_t arch; + uint8_t resvd4; + uint32_t flags; + uint8_t reset_reg[12]; + uint8_t reset_val; + uint8_t resvd5[3]; + uint64_t x_facs; + uint64_t x_dsdt; +} PACKED acpi_facp; + +typedef struct _acpi_table_lapic +{ + uint8_t acpi_id; + uint8_t apic_id; + uint32_t enabled; +} PACKED acpi_table_lapic; + +typedef struct _acpi_table_ioapic +{ + uint8_t id; + uint8_t resvd; + uint32_t address; + uint32_t irq_base; +} PACKED acpi_table_ioapic; + +typedef struct _acpi_table_int_src_ovr +{ + uint8_t bus; + uint8_t bus_irq; + uint8_t global_irq; + uint16_t flags; +} PACKED acpi_table_int_src_ovr; + +typedef struct _acpi_table_lapic_nmi +{ + uint8_t acpi_id; + uint16_t flags; + uint8_t lint; +} PACKED acpi_table_lapic_nmi; + +typedef struct _acpi_table_entry +{ + acpi_table_entry_header hdr; + union { + acpi_table_lapic m_lapic; + acpi_table_ioapic m_ioapic; + acpi_table_int_src_ovr m_intsrc; + //acpi_table_nmi_src m_nmisrc; + acpi_table_lapic_nmi m_lapicnmi; + } PACKED x; +} PACKED acpi_table_entry; + +#ifdef MSDOS +#pragma pack() +#endif + +/* Show Table Entry */ +void show_acpitab(uint64_t addr); + +/* Return a string of n bytes */ +const char FAR +*zstr(const char FAR *src, int n) +{ + static char tmp[32]; + + if (n >= sizeof(tmp)) { + n = sizeof(tmp)-1; + } + strncpy(tmp, src, n); + tmp[n] = 0; + return tmp; +} + +void +dump_facp(int rev, long len, void *buf) +{ + acpi_facp *afp = (acpi_facp *)buf; + uint8_t buf2[128]; + + if (rev == 3) { + printf(" XFACS : %llx\n", afp->x_facs); + printf(" XDSDT : %llx\n", afp->x_dsdt); + } + else { + printf(" FACS : %lx\n", afp->facs); + printf(" DSDT : %lx\n", afp->dsdt); + } + printf(" Model : %x\n", afp->model); + printf(" SCI Int : %x\n", afp->sciint); + printf(" SMI Cmd : %x\n", afp->smicmd); + printf(" S4 BIOS : %x\n", afp->s4bios); + printf(" enable : %x\n", afp->enable); + printf(" disable : %x\n", afp->disable); + printf(" PM1A : %.8x/%.8x\n", afp->pm1a_evt, afp->pm1a_cnt); + printf(" PM1B : %.8x/%.8x\n", afp->pm1b_evt, afp->pm1b_cnt); + printf(" PM2 : %x\n", afp->pm2_cnt); + + if (physmemcpy(buf2, afp->facs, 128) == 0) { + printf("------ (facs) ------\n"); + dump(buf2, 128); + } + + /* Show DSDT */ + if (rev == 3) { + show_acpitab(afp->x_dsdt); + } + else { + show_acpitab(afp->dsdt); + } +} + +void dump_madt(int rev, long len, void *buf) +{ + acpi_table_madt *pmad = (acpi_table_madt *)buf; + acpi_table_entry *phdr = (acpi_table_entry *)&pmad[1]; + + printf("------------( madt ) ------------\n"); + printf(" Local APIC: %lx\n", (long)pmad->local_apic_addr); + printf(" Compat : %lx\n", (long)pmad->compat); + len -= sizeof(acpi_table_madt); + + while(len > 0) { + if (phdr->hdr.length == 0) { + printf("Invalid entry\n"); + break; + } + len -= phdr->hdr.length; + printf(" type : %x length: %x", phdr->hdr.type, phdr->hdr.length); + switch(phdr->hdr.type) { + case ACPI_LAPIC: + printf(" (lapic)\tacpi_id:%.2x id:%.2x en:%.2x\n", + phdr->x.m_lapic.acpi_id, phdr->x.m_lapic.apic_id, phdr->x.m_lapic.enabled); + break; + case ACPI_IOAPIC: + printf(" (ioapic)\tioapic :%.2x addr:%.8x irq:%.4x\n", + phdr->x.m_ioapic.id, phdr->x.m_ioapic.address, phdr->x.m_ioapic.irq_base); + break; + case ACPI_INTSRC: + printf(" (int_src_ovr)\tbus:%.2x busirq:%.2x globalirq:%.2x flags:%.4x\n", + phdr->x.m_intsrc.bus, phdr->x.m_intsrc.bus_irq, phdr->x.m_intsrc.global_irq, + phdr->x.m_intsrc.flags); + break; + case ACPI_NMISRC: + printf(" nmi_src\n"); + break; + case ACPI_LAPICNMI: + printf(" (lapic_nmi)\tacpi_id:%.2x flags:%.4x lint:%.2x\n", + phdr->x.m_lapicnmi.acpi_id, phdr->x.m_lapicnmi.flags, phdr->x.m_lapicnmi.lint); + break; + default: + printf(" unknown : %x\n", phdr->hdr.type); + break; + } + phdr = (acpi_table_entry *)((uint8_t *)phdr + phdr->hdr.length); + } +} + +void +dump_xsdt(int rev, uint32_t len, void *buf) +{ + uint64_t *pb = (uint64_t *)buf; + + len /= sizeof(*pb); + while(len--) { + show_acpitab(*(pb++)); + } +} + +void +dump_rsdt(int rev, uint32_t len, void *buf) +{ + uint32_t *pb = (uint32_t *)buf; + + len /= sizeof(*pb); + while(len--) { + show_acpitab(*(pb++)); + } +} + +void +dump_dsdt(int rev, uint32_t len, void *buf) +{ +} + +/*========================================================================* + * Parse ACPI Table contents + *========================================================================*/ +void +parse_acpitab(acpi_table_header *atab, uint32_t physaddr, uint32_t len) +{ + void *buf; + FILE *fp; + char name[64]; + static int tid; + + if ((buf = malloc(len)) == NULL) { + return; + } + physmemcpy(buf, physaddr, len); + dump(buf, len); + + /* Save Table data */ + if (savename != NULL) { + snprintf(name, sizeof(name), "%s.%s.%d", savename, zstr(atab->sig, 4), tid++); + if ((fp = fopen(name, "wb")) != NULL) { + fwrite(atab, sizeof(*atab), 1, fp); + fwrite(buf, len, 1, fp); + fclose(fp); + } + } + if (!strncmp(atab->sig, "SSDT", 4)) dump_dsdt(atab->rev, len, buf); + if (!strncmp(atab->sig, "DSDT", 4)) dump_dsdt(atab->rev, len, buf); + if (!strncmp(atab->sig, "XSDT", 4)) dump_xsdt(atab->rev, len, buf); + if (!strncmp(atab->sig, "RSDT", 4)) dump_rsdt(atab->rev, len, buf); + if (!strncmp(atab->sig, "APIC", 4)) dump_madt(atab->rev, len, buf); + if (!strncmp(atab->sig, "FACP", 4)) dump_facp(atab->rev, len, buf); + free(buf); +} + +/*========================================================================* + * Display ACPI Table header + *========================================================================*/ +void +show_acpitab(uint64_t addr) +{ + acpi_table_header atab; + + if (physmemcpy(&atab, addr, sizeof(atab)) != 0) { + return; + } + printf("--------------------------------------\n"); + printf("%s @ 0x%lx\n", zstr(atab.sig, 4), (long)addr); + printf(" length : %x\n", atab.length); + printf(" rev : %x\n", atab.rev); + printf(" cksum : %x\n", atab.checksum); + printf(" oem : %s\n", zstr(atab.oem, 6)); + printf(" oemtab : %s\n", zstr(atab.oem_table, 8)); + printf(" oem_rev: %x\n", atab.oem_rev); + printf(" asl id : %s\n", zstr(atab.asl_compiler_id, 4)); + printf(" asl rev: %x\n", atab.asl_compiler_rev); + + parse_acpitab(&atab, addr + sizeof(atab), atab.length - sizeof(atab)); +} + +/*=============================================================== + * Display ACPI Table root header + *===============================================================*/ +void +show_acpi(uint32_t addr) +{ + acpi_table_rsdp rsdp; + + if (physmemcpy(&rsdp, addr, sizeof(rsdp)) != 0) { + return; + } + printf("===================== (ACPI TABLE) ======================\n"); + printf("RSDP: 0x%lx\n", (long)addr); + printf(" signature: %s\n", zstr(rsdp.signature, 8)); + printf(" checksum : %x\n", rsdp.checksum); + printf(" oem id : %s\n", zstr(rsdp.oem_id, 6)); + printf(" revision : %x\n", rsdp.revision); + printf(" rsdt addr: %lx\n", rsdp.rsdt_address); + if (rsdp.revision == 2) { + /* ACPI 2.0 uses XSDT */ + printf(" length : %lx\n", rsdp.length); + printf(" xsdt addr: %llx\n", rsdp.xsdt_address); + show_acpitab(rsdp.xsdt_address); + } + else { + /* ACPI 1.x uses RSDT */ + show_acpitab(rsdp.rsdt_address); + } +} + +/*=============================================================== + * + * Display MPBIOS Table + * + *===============================================================*/ +const char * +mp_inttype(int id) +{ + switch(id) { + case 0: return "int"; + case 1: return "nmi"; + case 2: return "smi"; + case 3: return "ext"; + } + return "xxx"; +} + +void +show_mptable(uint32_t addr) +{ + mps_root root; + mps_header hdr; + mps_entry entry; + uint32_t ptbl; + uint8_t type; + int idx; + + printf("===================== (MP TABLE) ======================\n"); + physmemcpy(&root, addr, sizeof(root)); + printf("Conf addr: %lx\n", root.mph_physaddr); + printf("Length : %x\n", root.mph_length); + printf("Spec Rev : %x\n", root.mph_spec); + printf("Checksum : %x\n", root.mph_cksum); + printf("Feature : %2x.%2x.%2x.%2x.%2x\n", + root.mph_feature[0], root.mph_feature[1], root.mph_feature[2], + root.mph_feature[3], root.mph_feature[4]); + + ptbl = root.mph_physaddr + sizeof(hdr); + physmemcpy(&hdr, root.mph_physaddr, sizeof(hdr)); + + printf(" OEM ID : '%s'\n", zstr(hdr.mpc_oem, 8)); + printf(" Prod ID : '%s'\n", zstr(hdr.mpc_product, 12)); + printf(" Base len : %x\n", hdr.mpc_length); + printf(" Checksum : %x\n", hdr.mpc_cksum); + printf(" Ptr : %x\n", hdr.mpc_oemptr); + printf(" Size : %x\n", hdr.mpc_oemsize); + printf(" Count : %x\n", hdr.mpc_oemcount); + printf(" LAPIC : %x\n", hdr.mpc_lapic); + + printf("---------\n"); + for(idx=0; idx<hdr.mpc_oemcount; idx++) { + physmemcpy(&entry, ptbl, sizeof(entry)); + switch(entry.type) { + case MPC_CPU: + printf(" cpu : id:%.2x apicver:%.2x cpuflags:%.2x cpusig:%.08x fflags:%.08x\n", + entry.m_cpu.apicid, entry.m_cpu.apicver, entry.m_cpu.cpuflag, + entry.m_cpu.cpufeature, entry.m_cpu.featureflag); + ptbl += sizeof(mps_cpu); + break; + case MPC_BUS: + printf(" bus : id:%.2x type:%s\n", + entry.m_bus.busid, zstr(entry.m_bus.bustype, 6)); + ptbl += sizeof(mps_bus); + break; + case MPC_APIC: + printf(" apic: id:%.2x apicver:%.2x apicflag:%.2x addr:%.08x\n", + entry.m_ioapic.apicid, entry.m_ioapic.apicver, entry.m_ioapic.flags, + entry.m_ioapic.apicaddr); + ptbl += sizeof(mps_ioapic); + break; + case MPC_INT: + printf(" int : type:%.2x[%s] pol:%x trig:%x bus:%.2x irq:%.2x -> apic:%.2x irq:%.2x\n", + entry.m_int.irqtype, mp_inttype(entry.m_int.irqtype), entry.m_int.irqflag&3, + (entry.m_int.irqflag>>2)&3, entry.m_int.srcbus, entry.m_int.srcbusirq, + entry.m_int.dstapic, entry.m_int.dstirq); + ptbl += sizeof(mps_intsrc); + break; + case MPC_LINT: + printf(" lint: type:%.2x[%s] pol:%x trig:%x bus:%.2x irq:%.2x -> apic:%.2x lint:%.2x\n", + entry.m_lint.irqtype, mp_inttype(entry.m_lint.irqtype), entry.m_lint.irqflag&3, + (entry.m_lint.irqflag>>2)&3, entry.m_lint.srcbus, entry.m_lint.srcbusirq, + entry.m_lint.dstapic, entry.m_lint.dstapiclint); + ptbl += sizeof(mps_lintsrc); + break; + default: + printf(" unknown: %x\n", type); + return; + } + } +} + +/* Uses neat feature of physmemcpy */ +void +showtable(const char *name) +{ + FILE *fp; + long len; + void *buf; + + set_physmemfile(name, 0); + show_acpitab(0); +} + +void +usage(void) +{ + extern char *__progname; + + fprintf(stderr, "usage: %s [-p filename] [-f filename]\n", __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + uint32_t addr; + int ch; + + while ((ch = getopt(argc, argv, "f:p:")) != -1) { + switch (ch) { + case 'f': /* save */ + savename = optarg; + break; + case 'p': /* print */ + showtable(optarg); + return (0); + break; + default: + usage(); + /* NOTREACHED */ + } + } + + /* Dump MP Table */ + addr = scanmem(0xF0000L, 0xFFFFFL, 16, 4, "_MP_"); + if (addr != 0) + show_mptable(addr); + + /* Dump ACPI Table */ + addr = scanmem(0xF0000L, 0xFFFFFL, 16, 8, "RSD PTR "); + if (addr != 0) + show_acpi(addr); + + return (0); +} diff --git a/usr.sbin/acpiscan/oslib.c b/usr.sbin/acpiscan/oslib.c new file mode 100644 index 00000000000..2a624272575 --- /dev/null +++ b/usr.sbin/acpiscan/oslib.c @@ -0,0 +1,441 @@ +/* $OpenBSD: oslib.c,v 1.1 2006/11/03 19:33:56 marco Exp $ */ +/* + * Copyright (c) 2006 Jordan Hargrave <jordan@openbsd.org> + * + * 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 <oslib.h> + +#define need_pciio 1 +#define need_physmem 1 +#define need_portio 1 +//#define need_pthread 1 + +/*===================================================================== + * + * OpenBSD User Mode + * + *=====================================================================*/ +#ifdef __OpenBSD__ +void set_iopl(int x) +{ + i386_iopl(x); +} +#endif + +/*===================================================================== + * + * Solaris User Mode + * + *=====================================================================*/ +#if defined(__sun__) +void set_iopl(int x) +{ + sysi86(SI86V86,V86SC_IOPL,0x3000); +} +#endif + +/*===================================================================== + * + * UnixWare User Mode + * + *=====================================================================*/ +#if defined(SCO) +void set_iopl(int x) +{ + sysi86(SI86IOPL, x); +} +#endif + +/*===================================================================== + * + * Linux Kernel Mode + * + *=====================================================================*/ +#if defined(linux) && defined(__KERNEL__) + +#if (LINUX_KERNEL_VERSION >= 0x020400) +MODULE_LICENSE("GPL"); +#endif + +char kernel_version[] = UTS_RELEASE; + +#define printf printk + +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif + +void ZeroMem(void *a, int c) +{ + uint8_t *b = (uint8_t *)a; + while(c--) { + *(b++) = 0; + } +} + +void CopyMem(void *d, const void *s, int c) +{ + uint8_t *a = (uint8_t *)d; + uint8_t *b = (uint8_t *)s; + + while(c--) { + *(a++) = *(b++); + } +} + +#undef need_pthread +#undef need_physmem +int physmemcpy(void *dest, uint32_t src, size_t len) +{ + memcpy(dest, phys_to_virt(src), len); + return 0; +} + +int physmemcmp(const void *dest, uint32_t src, size_t len) +{ + uint8_t buf[len]; + + physmemcpy(buf, src, len); + return memcmp(dest, buf, len); +} +#endif + +/*===================================================================== + * + * Linux User Mode + * + *=====================================================================*/ +#if defined(linux) && !defined(__KERNEL__) +void set_iopl(int x) +{ + iopl(x); +} + +#define need_mmap 1 + +#undef need_pciio +int pci_read_n(int b, int d, int f, int reg, int len, void *buf) +{ + char dev[32]; + int fd; + + memset(buf, 0, len); + sprintf(dev,"/proc/bus/pci/%.02x/%.02x.%x", b,d,f); + if ((fd = open(dev,O_RDWR)) >= 0) { + pread(fd,buf,len,reg); + close(fd); + return 0; + } + return -1; +} +#endif + +/*===================================================================== + * + * DOS 16-bit Mode + * + *=====================================================================*/ +#ifdef MSDOS + +/* Converts linear address to 16:16 pointer */ +void FAR *lintoseg(uint32_t v); +#pragma aux lintoseg = "shl dx, 12" parm caller [dx ax] value [dx ax]; + +void set_iopl(int x) +{ +} + +#undef need_portio +uint8_t os_inb(uint16_t port) +{ + return inb(port); +} +uint16_t os_inw(uint16_t port) +{ + return inw(port); +} +uint32_t os_inl(uint16_t port) +{ + return inl(port); +} +void os_outb(uint16_t port, uint8_t val) +{ + outb(port, val); +} +void os_outw(uint16_t port, uint16_t val) +{ + outw(port, val); +} +void os_outl(uint16_t port, uint32_t val) +{ + outl(port, val); +} + +#ifdef WATCOM +#pragma aux os_inb = "in al, dx" value [al] parms [dx]; +#pragma aux os_inw = "in ax, dx" value [ax] parms [dx]; +#pragma aux os_inl = \ + "in eax, dx" \ +"mov dx, ax" \ +"shr eax, 16", \ +"xchg dx, ax" value [dx ax] parms [dx]; + +#pragma aux os_outb = "out dx, al" parms [dx] [al]; +#pragma aux os_outw = "out dx, ax" parms [dx] [ax]; +#pragma aux os_outl = \ + "mov ax, cx" \ +"shl eax, 16" \ +"mov ax, bx" \ +"out dx, eax" parm [dx] [cx bx] modifies [ax]; +#endif + +#undef need_physmem +int physmemcpy(void FAR *dest, uint32_t src, int len) +{ + _fmemcpy(dest, lintoseg(src), len); + return 0; +} + +int physmemcmp(const void FAR *dest, uint32_t src, int len) +{ + return _fmemcmp(dest, lintoseg(src), len); +} +#endif /* end dos */ + +/*===================================================================== + * + * Common Physmem code + * + *=====================================================================*/ +#ifdef need_physmem + +#define PAGE_OFFSET(x) (uint64_t)((x) & ~PAGE_MASK) + +static const char *memfile = "/dev/mem"; +static uint64_t memoff; + +int physmemcpy(void FAR *dest, uint32_t src, size_t len) +{ + int fd,rc; + uint64_t memlimit; + + memset(dest, 0, len); + if ((fd = open(memfile, O_RDONLY)) < 0) { + printf("Can't open: %s\n", memfile); + exit(0); + } +#if 0 + memlimit = lseek(fd, 0, SEEK_END); + if (src < (unsigned)memoff || src+len > memlimit + memoff) { + close(fd); + return -1; + } +#endif + src -= memoff; +#ifdef need_mmap + { + uint64_t offset; + void *ptr; + + offset = PAGE_OFFSET(src); + ptr = mmap(NULL, offset+len, PROT_READ, MAP_PRIVATE, fd, src-offset); + if (ptr == (void *)-1L) { + printf("Can't mmap @ 0x%.08lx! %d\n", src, errno); + } + else { + memcpy(dest, ptr+offset, len); + munmap(ptr, offset+len); + } + } +#else + rc=pread(fd, dest, len, (off_t)(src - memoff)); + if (rc < 0) { + printf("Can't pread64 @ 0x%.08x %d\n", src, errno); + } +#endif + close(fd); + return 0; +} + +int physmemcmp(const void FAR *dest, uint32_t src, size_t len) +{ + unsigned char bufr[len]; + + physmemcpy(bufr, src, len); + return memcmp(bufr, dest, len); +} +#endif + +/*===================================================================== + * + * Common PCI Access code + * + *=====================================================================*/ +#ifdef need_pciio +#define PCI_ADDR(b,d,f,r) (0x80000000+((b)<<16)+((d)<<10)+((f)<<8)+(r)) +int pci_read_n(int b, int d, int f, int reg, int len, void *buf) +{ + uint8_t *ptr = (uint8_t *)buf; + while(len--) { + os_outl(0xCF8, PCI_ADDR(b,d,f,reg++)); + *(ptr++) = os_inb(0xCF8); + } +} +#endif + +/*===================================================================== + * + * Common Port code + * + *=====================================================================*/ +#ifdef need_portio +uint8_t os_inb(uint16_t port) +{ + uint8_t v; + + __asm__ __volatile__ ("inb %w1,%b0" : "=a" (v) : "Nd" (port)); + return v; +} +uint16_t os_inw(uint16_t port) +{ + uint16_t v; + + __asm__ __volatile__ ("inw %w1,%w0" : "=a" (v) : "Nd" (port)); + return v; +} +uint32_t os_inl(uint16_t port) +{ + uint32_t v; + + __asm__ __volatile__ ("inl %w1,%0" : "=a" (v) : "Nd" (port)); + return v; +} +void os_outb(uint16_t port, uint8_t v) +{ + __asm__ __volatile__ ("outb %b0,%w1" : "=a" (v) : "Nd" (port)); +} +void os_outw(uint16_t port, uint16_t v) +{ + __asm__ __volatile__ ("outw %w0,%w1" : "=a" (v) : "Nd" (port)); +} +void os_outl(uint16_t port, uint32_t v) +{ + __asm__ __volatile__ ("outl %0,%w1" : "=a" (v) : "Nd" (port)); +} +#endif + + +/*================================================================== + * common pthread routines + *==================================================================*/ +#ifdef need_pthread +#include <pthread.h> + +typedef int (*threadproc_t)(void *); + +typedef struct +{ + pthread_t tid; + threadproc_t proc; + void *arg; +} osthread_t; + +static void *os_threadhelper(void *arg) +{ + osthread_t *thrd = (osthread_t *)arg; + + thrd->proc(thrd->arg); + return NULL; +} + +osthread_t *os_create_thread(threadproc_t threadproc, void *arg) +{ + osthread_t *thrd; + + if ((thrd = (osthread_t *)malloc(sizeof(osthread_t))) == NULL) { + return NULL; + } + thrd->proc = threadproc; + thrd->arg = arg; + pthread_create(&thrd->tid, NULL, os_threadhelper, thrd); + return thrd; +} + +int os_destroy_thread(osthread_t *thrd) +{ + void *rcval; + + pthread_join(thrd->tid, &rcval); + free(thrd); +} +#endif + +/*====================================================================* + * Common code + *====================================================================*/ +uint32_t scanmem(uint32_t src, uint32_t end, int step, int sz, + const void FAR *mem) +{ + while(src < end) { + if (physmemcmp(mem, src, sz) == 0) { + return src; + } + src += step; + } + return 0; +} + +void set_physmemfile(const char *name, uint64_t offset) +{ +#ifdef need_physmem + memfile = name; + memoff = offset; +#endif +} + +char dxc(char v, int t) +{ + if (v < ' ' || v > 'z' || t) { + return '.'; + } + return v; +} +uint8_t dxb(uint8_t v, int t) +{ + return (t) ? 0xFF : v; +} + +void dump(void FAR *dest, int len) +{ + uint8_t FAR *b = (uint8_t FAR *)dest; + int i,j; + + for(i=0;i<len;i+=16) { + printf("%.06x: ", i); + for(j=0;j<16;j++) { + if (i+j >= len) { + printf("-- "); + } + else { + printf("%.02x ", dxb(b[i+j],i+j>=len)); + } + } + printf(" "); + for(j=0;j<16;j++) { + printf("%c", dxc(b[i+j],i+j>=len)); + } + printf("\n"); + } +} diff --git a/usr.sbin/acpiscan/oslib.h b/usr.sbin/acpiscan/oslib.h new file mode 100644 index 00000000000..218fa1e9b1b --- /dev/null +++ b/usr.sbin/acpiscan/oslib.h @@ -0,0 +1,205 @@ +/* $OpenBSD: oslib.h,v 1.1 2006/11/03 19:33:56 marco Exp $ */ +/* + * Copyright (c) 2006 Jordan Hargrave <jordan@openbsd.org> + * + * 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. + */ + +#ifndef __oslib_h__ +#define __oslib_h__ + +/*=========== ( DOS 16-bit ) ============================= */ +#ifdef MSDOS +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <stddef.h> +#include <dos.h> +#include <time.h> + +#define FAR far +#define PACKED + +typedef unsigned __int64 uint64_t; +typedef unsigned long uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; + +#define ZeroMem(a,c) _fmemset((void FAR *)a,0,c) +#define CopyMem(a,b,c) _fmemcpy((void FAR *)(a),(void FAR *)b,c) +#endif + +/*==== ( OpenBSD user mode ) ============================= */ +#ifdef __OpenBSD__ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <fcntl.h> +#include <time.h> +#include <machine/pio.h> +#include <i386/sysarch.h> + +#define ZeroMem(buf,len) bzero(buf,len) +#define CopyMem(dest,src,len) bcopy(src,dest,len) + +#define cpu_to_be16 be16toh +#define cpu_to_be32 be32toh +#define cpu_to_be64 be64toh +#define be16_to_cpu htobe16 +#define be32_to_cpu htobe32 +#define be64_to_cpu htobe64 +#endif + +/*==== ( FreeBSD user mode ) ============================= */ +#ifdef __FreeBSD__ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <stdint.h> +#include <fcntl.h> +#include <time.h> + +#define ZeroMem(buf,len) bzero(buf,len) +#define CopyMem(dest,src,len) bcopy(src,dest,len) +#endif + +/*==== ( SCO UNIXWARE user mode ) ============================= */ +#ifdef SCO +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcntl.h> +#include <sys/sysi86.h> +#include <sys/inline.h> +#include <inttypes.h> + +#define ZeroMem(buf,len) bzero(buf,len) +#define CopyMem(dest,src,len) bcopy(src,dest,len) +#endif + +/*==== ( Solaris user mode ) ============================= */ +#ifdef __sun__ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <fcntl.h> +#include <sys/sysi86.h> +//#include <sys/inline.h> + +#define ZeroMem(buf,len) bzero(buf,len) +#define CopyMem(dest,src,len) bcopy(src,dest,len) + +#endif + +/*==== ( Linux kernel mode ) ============================= */ +#if defined(linux) && defined(__KERNEL__) +#include <linux/version.h> +#include <linux/module.h> +#include <linux/config.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <linux/miscdevice.h> + +#endif + +/*==== ( Linux user mode ) ============================= */ +#if defined(linux) && !defined(__KERNEL__) +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <stddef.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> +#include <sys/io.h> +#include <inttypes.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <asm/page.h> +#include <errno.h> +#include <endian.h> +#include <byteswap.h> + +#endif + +/*====================================================* + * Common code + *====================================================*/ +#ifndef FAR +# define FAR +#endif +#ifndef PACKED +# define PACKED __attribute__((packed)) +#endif + +extern void os_dump(const void FAR *, int); + +/* ----==== Memory I/O ====---- */ +extern void set_physmemfile(const char FAR *, uint64_t); +extern int physmemcpy(void FAR *dest, uint32_t src, size_t len); +extern int physmemcmp(const void FAR *dest, uint32_t src, size_t len); +extern uint32_t scanmem(uint32_t src, uint32_t end, int step, int sz, + const void FAR *mem); + +/* ----==== Port I/O ====---- */ +extern void set_iopl(int); +extern uint8_t os_inb(uint16_t); +extern uint16_t os_inw(uint16_t); +extern uint32_t os_inl(uint16_t); +extern void os_outb(uint16_t, uint8_t); +extern void os_outw(uint16_t, uint16_t); +extern void os_outl(uint16_t, uint32_t); + +/* ----==== PCI ====---- */ +extern int pci_read_n(int, int, int, int, int, void FAR *); + +#define cpu_to_le16(x) (x) +#define cpu_to_le32(x) (x) +#define cpu_to_le64(x) (x) + +#define le16_to_cpu(x) (x) +#define le32_to_cpu(x) (x) +#define le64_to_cpu(x) (x) + +/* AABBCCDD + * xchg dh, al = DDBBCCAA + * xchg dl, ah = DDCCBBAA + */ +#ifdef WATCOM +#pragma aux cpu_to_be16 = "xchg ah, al" parm [ax] value [ax]; +#pragma aux cpu_to_be32 = \ + "xchg dh, al" \ +"xchg dl, ah" \ +parm caller [dx ax] value [dx ax]; +#endif + +#endif + |