The diff below adds arm64 support to acpidump(8). It renames
bios_acpi_addr() into efi_acpi_addr() and duplicates the function
because on arm64 I just need to read a 64-bit integer I'm considering
changing amd64 to use a variable with the same name to get rid of the
#ifdef. The code that grovels through low memory to discover the ACPI
tables is only enabled for amd64 and i386 now.
Since on my arm64 system there is no RSDT, this adds support for using
the XSDT instead. There is a fair bit of code reorg to handle the
discovery of the RSD PTR table as the pointer to the XSDT won't be
there on ACPI 1.0 systems.
ok?
Index: usr.sbin/acpidump/Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/acpidump/Makefile,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile
--- usr.sbin/acpidump/Makefile 24 Jan 2017 00:20:28 -0000 1.6
+++ usr.sbin/acpidump/Makefile 23 Jun 2018 14:37:02 -0000
@@ -1,6 +1,7 @@
# $OpenBSD: Makefile,v 1.6 2017/01/24 00:20:28 deraadt Exp $
-.if (${MACHINE} == "i386") || (${MACHINE} == "amd64")
+.if ${MACHINE} == "amd64" || ${MACHINE} == "arm64" || \
+ ${MACHINE} == "i386"
PROG= acpidump
SRCS= acpidump.c
LDADD= -lkvm
Index: usr.sbin/acpidump/acpidump.c
===================================================================
RCS file: /cvs/src/usr.sbin/acpidump/acpidump.c,v
retrieving revision 1.17
diff -u -p -r1.17 acpidump.c
--- usr.sbin/acpidump/acpidump.c 26 Sep 2016 19:58:26 -0000 1.17
+++ usr.sbin/acpidump/acpidump.c 23 Jun 2018 14:37:02 -0000
@@ -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 _leng
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
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");
+ 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_rsdt(rsdp);
+ 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
+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
-bios_acpi_addr(void)
+efi_acpi_addr(void)
{
kvm_t *kd;
struct nlist nl[2];
@@ -623,3 +726,5 @@ on_error:
kvm_close(kd);
return (0);
}
+
+#endif