diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2006-11-03 19:33:57 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2006-11-03 19:33:57 +0000 |
commit | 0754ad9672a8765f576bdba8db1c9f1b9be901fa (patch) | |
tree | a3668849c162d19c0ca6d1e4c09303a0206df43d /usr.sbin | |
parent | 05ae39297525fdf87aa8234c6f43d2e5a016f565 (diff) |
Add Jordan's acpiscan acpi table dump tool. The current tool, acpidump,
does not dump all relevant tables and will eventually be deprecated by this.
It needs some more cleanup but we need to start getting acpi dumps from
the field using this instead of acpidump.
Code written by jordan, cleanup by me.
ok jordan@
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 + |