diff --git a/usr.sbin/acpi/acpidump/acpi.c b/usr.sbin/acpi/acpidump/acpi.c index 971e0211612a..e22aad410656 100644 --- a/usr.sbin/acpi/acpidump/acpi.c +++ b/usr.sbin/acpi/acpidump/acpi.c @@ -716,8 +716,41 @@ sdt_load_devmem(void) return (rsdp); } +static int +write_dsdt(int fd, struct ACPIsdt *rsdt, struct ACPIsdt *dsdt) +{ + struct ACPIsdt sdt; + struct ACPIsdt *ssdt; + uint8_t sum; + + sdt = *dsdt; + if (rsdt != NULL) { + sdt.check = 0; + sum = acpi_checksum(dsdt->body, dsdt->len - SIZEOF_SDT_HDR); + ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL); + while (ssdt != NULL) { + sdt.len += ssdt->len - SIZEOF_SDT_HDR; + sum += acpi_checksum(ssdt->body, + ssdt->len - SIZEOF_SDT_HDR); + ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt); + } + sum += acpi_checksum(&sdt, SIZEOF_SDT_HDR); + sdt.check -= sum; + } + write(fd, &sdt, SIZEOF_SDT_HDR); + write(fd, dsdt->body, dsdt->len - SIZEOF_SDT_HDR); + if (rsdt != NULL) { + ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL); + while (ssdt != NULL) { + write(fd, ssdt->body, ssdt->len - SIZEOF_SDT_HDR); + ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt); + } + } + return (0); +} + void -dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) +dsdt_save_file(char *outfile, struct ACPIsdt *rsdt, struct ACPIsdt *dsdp) { int fd; mode_t mode; @@ -729,13 +762,12 @@ dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) perror("dsdt_save_file"); return; } - write(fd, dsdp, SIZEOF_SDT_HDR); - write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); + write_dsdt(fd, rsdt, dsdp); close(fd); } void -aml_disassemble(struct ACPIsdt *dsdp) +aml_disassemble(struct ACPIsdt *rsdt, struct ACPIsdt *dsdp) { char tmpstr[32], buf[256]; FILE *fp; @@ -747,10 +779,7 @@ aml_disassemble(struct ACPIsdt *dsdp) perror("iasl tmp file"); return; } - - /* Dump DSDT to the temp file */ - write(fd, dsdp, SIZEOF_SDT_HDR); - write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); + write_dsdt(fd, rsdt, dsdp); close(fd); /* Run iasl -d on the temp file */ @@ -783,9 +812,9 @@ sdt_print_all(struct ACPIsdt *rsdp) acpi_handle_rsdt(rsdp); } -/* Fetch a table matching the given signature via the RSDT */ +/* Fetch a table matching the given signature via the RSDT. */ struct ACPIsdt * -sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) +sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig, struct ACPIsdt *last) { struct ACPIsdt *sdt; vm_offset_t addr; @@ -804,6 +833,11 @@ sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) assert((addr = 0)); } sdt = (struct ACPIsdt *)acpi_map_sdt(addr); + if (last != NULL) { + if (sdt == last) + last = NULL; + continue; + } if (memcmp(sdt->signature, sig, strlen(sig))) continue; if (acpi_checksum(sdt, sdt->len)) diff --git a/usr.sbin/acpi/acpidump/acpidump.c b/usr.sbin/acpi/acpidump/acpidump.c index 269a595cbd43..b9b8b0a081e1 100644 --- a/usr.sbin/acpi/acpidump/acpidump.c +++ b/usr.sbin/acpi/acpidump/acpidump.c @@ -54,7 +54,7 @@ main(int argc, char *argv[]) { char c, *progname; char *dsdt_input_file, *dsdt_output_file; - struct ACPIsdt *sdt; + struct ACPIsdt *rsdt, *sdt; dsdt_input_file = dsdt_output_file = NULL; progname = argv[0]; @@ -99,38 +99,41 @@ main(int argc, char *argv[]) } if (vflag) warnx("loading DSDT file: %s", dsdt_input_file); - sdt = dsdt_load_file(dsdt_input_file); + rsdt = dsdt_load_file(dsdt_input_file); } else { if (vflag) warnx("loading RSD PTR from /dev/mem"); - sdt = sdt_load_devmem(); + rsdt = sdt_load_devmem(); } /* Display misc. SDT tables (only available when using /dev/mem) */ if (tflag) { if (vflag) warnx("printing various SDT tables"); - sdt_print_all(sdt); + sdt_print_all(rsdt); } /* Translate RSDT to DSDT pointer */ if (dsdt_input_file == NULL) { - sdt = sdt_from_rsdt(sdt, "FACP"); + sdt = sdt_from_rsdt(rsdt, "FACP", NULL); sdt = dsdt_from_fadt((struct FADTbody *)sdt->body); + } else { + sdt = rsdt; + rsdt = NULL; } /* Dump the DSDT to a file */ if (dsdt_output_file != NULL) { if (vflag) warnx("saving DSDT file: %s", dsdt_output_file); - dsdt_save_file(dsdt_output_file, sdt); + dsdt_save_file(dsdt_output_file, rsdt, sdt); } /* Disassemble the DSDT into ASL */ if (dflag) { if (vflag) warnx("disassembling DSDT, iasl messages follow"); - aml_disassemble(sdt); + aml_disassemble(rsdt, sdt); if (vflag) warnx("iasl processing complete"); } diff --git a/usr.sbin/acpi/acpidump/acpidump.h b/usr.sbin/acpi/acpidump/acpidump.h index 1ebc56d8e006..ca56398af2a9 100644 --- a/usr.sbin/acpi/acpidump/acpidump.h +++ b/usr.sbin/acpi/acpidump/acpidump.h @@ -314,18 +314,19 @@ struct ACPIsdt *sdt_load_devmem(void); struct ACPIsdt *dsdt_load_file(char *); /* Save the DSDT to a file */ -void dsdt_save_file(char *, struct ACPIsdt *); +void dsdt_save_file(char *, struct ACPIsdt *, struct ACPIsdt *); /* Print out as many fixed tables as possible, given the RSD PTR */ void sdt_print_all(struct ACPIsdt *); /* Disassemble the AML in the DSDT */ -void aml_disassemble(struct ACPIsdt *); +void aml_disassemble(struct ACPIsdt *, struct ACPIsdt *); /* Routines for accessing tables in physical memory */ struct ACPIrsdp *acpi_find_rsd_ptr(void); void *acpi_map_physical(vm_offset_t, size_t); -struct ACPIsdt *sdt_from_rsdt(struct ACPIsdt *, const char *); +struct ACPIsdt *sdt_from_rsdt(struct ACPIsdt *, const char *, + struct ACPIsdt *); struct ACPIsdt *dsdt_from_fadt(struct FADTbody *); int acpi_checksum(void *, size_t);