summaryrefslogtreecommitdiffstats
path: root/usr.sbin/acpidump/acpidump.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2018-06-24 10:39:59 +0000
committerkettenis <kettenis@openbsd.org>2018-06-24 10:39:59 +0000
commit6988a5d702ea0122c41a250f62242f3b9bbab6e8 (patch)
tree9e20602dc90f135c36447286149ca9305969034f /usr.sbin/acpidump/acpidump.c
parentIf ACPI tables are present, set a global variable to point at their (diff)
downloadwireguard-openbsd-6988a5d702ea0122c41a250f62242f3b9bbab6e8.tar.xz
wireguard-openbsd-6988a5d702ea0122c41a250f62242f3b9bbab6e8.zip
Add support for parsing XSDT tables. Add support for arm64.
ok deraadt@
Diffstat (limited to 'usr.sbin/acpidump/acpidump.c')
-rw-r--r--usr.sbin/acpidump/acpidump.c185
1 files changed, 145 insertions, 40 deletions
diff --git a/usr.sbin/acpidump/acpidump.c b/usr.sbin/acpidump/acpidump.c
index 4a499e2f47e..fdad67a7895 100644
--- a/usr.sbin/acpidump/acpidump.c
+++ b/usr.sbin/acpidump/acpidump.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpidump.c,v 1.17 2016/09/26 19:58:26 kettenis Exp $ */
+/* $OpenBSD: acpidump.c,v 1.18 2018/06/24 10:39:59 kettenis Exp $ */
/*
* Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
* All rights reserved.
@@ -30,7 +30,6 @@
#include <sys/mman.h>
#include <sys/queue.h>
#include <sys/stat.h>
-#include <machine/biosvar.h>
#include <assert.h>
#include <err.h>
@@ -58,8 +57,13 @@ struct ACPIrsdp {
u_char signature[8];
u_char sum;
u_char oem[6];
- u_char res;
+ u_char rev;
u_int32_t addr;
+#define SIZEOF_RSDP_REV_0 20
+ u_int32_t len;
+ u_int64_t xaddr;
+ u_char xsum;
+ u_char xres[3];
} __packed;
struct ACPIsdt {
@@ -174,6 +178,7 @@ int acpi_checksum(void *_p, size_t _length);
struct acpi_user_mapping *acpi_user_find_mapping(vm_offset_t _pa, size_t _size);
void *acpi_map_physical(vm_offset_t _pa, size_t _size);
void acpi_user_init(void);
+struct ACPIrsdp *acpi_check_rsd_ptr(vm_offset_t _pa);
struct ACPIrsdp *acpi_find_rsd_ptr(void);
void acpi_print_string(char *_s, size_t _length);
void acpi_print_rsd_ptr(struct ACPIrsdp *_rp);
@@ -181,14 +186,16 @@ struct ACPIsdt *acpi_map_sdt(vm_offset_t _pa);
void aml_dump(struct ACPIsdt *_hdr);
void acpi_print_sdt(struct ACPIsdt *_sdp);
void acpi_print_rsdt(struct ACPIsdt *_rsdp);
+void acpi_print_xsdt(struct ACPIsdt *_rsdp);
void acpi_print_facp(struct FACPbody *_facp);
void acpi_print_dsdt(struct ACPIsdt *_dsdp);
void acpi_handle_dsdt(struct ACPIsdt *_dsdp);
void acpi_handle_facp(struct FACPbody *_facp);
void acpi_handle_rsdt(struct ACPIsdt *_rsdp);
+void acpi_handle_xsdt(struct ACPIsdt *_rsdp);
void asl_dump_from_devmem(void);
void usage(void);
-u_long bios_acpi_addr(void);
+u_long efi_acpi_addr(void);
struct ACPIsdt dsdt_header = {
@@ -264,41 +271,47 @@ acpi_user_init(void)
}
struct ACPIrsdp *
+acpi_check_rsd_ptr(vm_offset_t pa)
+{
+ struct ACPIrsdp rp;
+
+ lseek(acpi_mem_fd, pa, SEEK_SET);
+ read(acpi_mem_fd, &rp, SIZEOF_RSDP_REV_0);
+ if (memcmp(rp.signature, "RSD PTR ", 8) != 0)
+ return NULL;
+
+ if (rp.rev >= 2) {
+ read(acpi_mem_fd, &(rp.len),
+ sizeof(struct ACPIrsdp) - SIZEOF_RSDP_REV_0);
+ if (acpi_checksum(&rp, sizeof(struct ACPIrsdp)) == 0)
+ return acpi_map_physical(pa, sizeof(struct ACPIrsdp));
+ }
+
+ if (acpi_checksum(&rp, SIZEOF_RSDP_REV_0) == 0)
+ return (acpi_map_physical(pa, SIZEOF_RSDP_REV_0));
+
+ return NULL;
+}
+
+struct ACPIrsdp *
acpi_find_rsd_ptr(void)
{
- int i;
- u_int8_t buf[sizeof(struct ACPIrsdp)];
+ struct ACPIrsdp *rp;
u_long addr;
- if ((addr = bios_acpi_addr()) != 0) {
- lseek(acpi_mem_fd, addr, SEEK_SET);
- read(acpi_mem_fd, buf, 16);
- if (!memcmp(buf, "RSD PTR ", 8)) {
- read(acpi_mem_fd, buf + 16,
- sizeof(struct ACPIrsdp) - 16);
- if (!acpi_checksum(buf, sizeof(struct ACPIrsdp)))
- return (acpi_map_physical(addr,
- sizeof(struct ACPIrsdp)));
- }
- lseek(acpi_mem_fd, 0, SEEK_SET);
+ if ((addr = efi_acpi_addr()) != 0) {
+ if ((rp = acpi_check_rsd_ptr(addr)))
+ return rp;
}
- for (i = 0; i < 1024 * 1024; i += 16) {
- lseek(acpi_mem_fd, i, SEEK_SET);
- 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)));
- }
+
+#if defined(__amd64__) || defined (__i386__)
+ for (addr = 0; addr < 1024 * 1024; addr += 16) {
+ if ((rp = acpi_check_rsd_ptr(addr)))
+ return rp;
}
+#endif
- return (0);
+ return NULL;
}
void
@@ -322,7 +335,13 @@ acpi_print_rsd_ptr(struct ACPIrsdp *rp)
fprintf(fhdr, "\n");
fprintf(fhdr, "RSD PTR: Checksum=%d, OEMID=", rp->sum);
acpi_print_string(rp->oem, 6);
+ fprintf(fhdr, ", Revision=%d", rp->rev);
fprintf(fhdr, ", RsdtAddress=0x%08x\n", rp->addr);
+ if (rp->rev >= 2) {
+ fprintf(fhdr, "\tLength=%d", rp->len);
+ fprintf(fhdr, ", XsdtAddress=0x%016llx", rp->xaddr);
+ fprintf(fhdr, ", Extended Checksum=%d\n", rp->xsum);
+ }
fprintf(fhdr, "\n");
}
@@ -399,6 +418,25 @@ acpi_print_rsdt(struct ACPIsdt *rsdp)
}
void
+acpi_print_xsdt(struct ACPIsdt *rsdp)
+{
+ int i, entries;
+ u_int64_t *body = (u_int64_t *) rsdp->body;
+
+ acpi_print_sdt(rsdp);
+ entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int64_t);
+ fprintf(fhdr, "\n");
+ fprintf(fhdr, "\tEntries={ ");
+ for (i = 0; i < entries; i++) {
+ if (i > 0)
+ fprintf(fhdr, ", ");
+ fprintf(fhdr, "0x%016llx", body[i]);
+ }
+ fprintf(fhdr, " }\n");
+ fprintf(fhdr, "\n");
+}
+
+void
acpi_print_facp(struct FACPbody *facp)
{
char sep;
@@ -525,6 +563,30 @@ acpi_handle_rsdt(struct ACPIsdt *rsdp)
}
void
+acpi_handle_xsdt(struct ACPIsdt *rsdp)
+{
+ int i;
+ int entries;
+ struct ACPIsdt *sdp;
+ u_int64_t *body = (u_int64_t *) rsdp->body;
+
+ aml_dump(rsdp);
+ entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int64_t);
+ acpi_print_xsdt(rsdp);
+ for (i = 0; i < entries; i++) {
+ sdp = (struct ACPIsdt *) acpi_map_sdt(body[i]);
+ if (acpi_checksum(sdp, sdp->len))
+ errx(1, "XSDT entry %d is corrupt", i);
+ aml_dump(sdp);
+ if (!memcmp(sdp->signature, "FACP", 4)) {
+ acpi_handle_facp((struct FACPbody *) sdp->body);
+ } else {
+ acpi_print_sdt(sdp);
+ }
+ }
+}
+
+void
asl_dump_from_devmem(void)
{
struct ACPIrsdp *rp;
@@ -548,12 +610,21 @@ asl_dump_from_devmem(void)
err(1, "asl_dump_from_devmem");
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");
-
- acpi_handle_rsdt(rsdp);
+ if (rp->addr != 0) {
+ rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->addr);
+ if (memcmp(rsdp->signature, "RSDT", 4) ||
+ acpi_checksum(rsdp, rsdp->len))
+ errx(1, "RSDT is corrupted");
+
+ acpi_handle_rsdt(rsdp);
+ } else {
+ rsdp = (struct ACPIsdt *) acpi_map_sdt(rp->xaddr);
+ if (memcmp(rsdp->signature, "XSDT", 4) ||
+ acpi_checksum(rsdp, rsdp->len))
+ errx(1, "XSDT is corrupted");
+
+ acpi_handle_xsdt(rsdp);
+ }
fclose(fhdr);
}
@@ -571,7 +642,7 @@ int
main(int argc, char *argv[])
{
struct stat st;
- char c;
+ int c;
while ((c = getopt(argc, argv, "o:")) != -1) {
switch (c) {
@@ -595,8 +666,40 @@ main(int argc, char *argv[])
return (0);
}
+#ifdef __aarch64__
+
u_long
-bios_acpi_addr(void)
+efi_acpi_addr(void)
+{
+ kvm_t *kd;
+ struct nlist nl[2];
+ uint64_t table;
+
+ memset(&nl, 0, sizeof(nl));
+ kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
+ if (kd == NULL)
+ goto on_error;
+ nl[0].n_name = "efi_acpi_table";
+ if (kvm_nlist(kd, nl) == -1)
+ goto on_error;
+ if (kvm_read(kd, nl[0].n_value, &table, sizeof(table)) == -1)
+ goto on_error;
+
+ kvm_close(kd);
+ return table;
+
+on_error:
+ if (kd != NULL)
+ kvm_close(kd);
+ return (0);
+}
+
+#else
+
+#include <machine/biosvar.h>
+
+u_long
+efi_acpi_addr(void)
{
kvm_t *kd;
struct nlist nl[2];
@@ -623,3 +726,5 @@ on_error:
kvm_close(kd);
return (0);
}
+
+#endif