1e1e9a4bfSMitsuru IWASAKI /*- 2e1e9a4bfSMitsuru IWASAKI * Copyright (c) 1998 Doug Rabson 3e1e9a4bfSMitsuru IWASAKI * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 4e1e9a4bfSMitsuru IWASAKI * All rights reserved. 5e1e9a4bfSMitsuru IWASAKI * 6e1e9a4bfSMitsuru IWASAKI * Redistribution and use in source and binary forms, with or without 7e1e9a4bfSMitsuru IWASAKI * modification, are permitted provided that the following conditions 8e1e9a4bfSMitsuru IWASAKI * are met: 9e1e9a4bfSMitsuru IWASAKI * 1. Redistributions of source code must retain the above copyright 10e1e9a4bfSMitsuru IWASAKI * notice, this list of conditions and the following disclaimer. 11e1e9a4bfSMitsuru IWASAKI * 2. Redistributions in binary form must reproduce the above copyright 12e1e9a4bfSMitsuru IWASAKI * notice, this list of conditions and the following disclaimer in the 13e1e9a4bfSMitsuru IWASAKI * documentation and/or other materials provided with the distribution. 14e1e9a4bfSMitsuru IWASAKI * 15e1e9a4bfSMitsuru IWASAKI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16e1e9a4bfSMitsuru IWASAKI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e1e9a4bfSMitsuru IWASAKI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18e1e9a4bfSMitsuru IWASAKI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19e1e9a4bfSMitsuru IWASAKI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e1e9a4bfSMitsuru IWASAKI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e1e9a4bfSMitsuru IWASAKI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e1e9a4bfSMitsuru IWASAKI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e1e9a4bfSMitsuru IWASAKI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e1e9a4bfSMitsuru IWASAKI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e1e9a4bfSMitsuru IWASAKI * SUCH DAMAGE. 26e1e9a4bfSMitsuru IWASAKI * 27e1e9a4bfSMitsuru IWASAKI * $FreeBSD$ 28e1e9a4bfSMitsuru IWASAKI */ 29e1e9a4bfSMitsuru IWASAKI 30e1e9a4bfSMitsuru IWASAKI #include <sys/param.h> 31a74172abSNate Lawson #include <sys/endian.h> 32e1e9a4bfSMitsuru IWASAKI #include <sys/stat.h> 33945137d9SNate Lawson #include <sys/wait.h> 34e1e9a4bfSMitsuru IWASAKI #include <assert.h> 35e1e9a4bfSMitsuru IWASAKI #include <err.h> 36e1e9a4bfSMitsuru IWASAKI #include <fcntl.h> 37e1e9a4bfSMitsuru IWASAKI #include <stdio.h> 38945137d9SNate Lawson #include <string.h> 39e1e9a4bfSMitsuru IWASAKI #include <unistd.h> 40e1e9a4bfSMitsuru IWASAKI 41e1e9a4bfSMitsuru IWASAKI #include "acpidump.h" 42e1e9a4bfSMitsuru IWASAKI 43c62f1cccSMitsuru IWASAKI #define BEGIN_COMMENT "/*\n" 44c62f1cccSMitsuru IWASAKI #define END_COMMENT " */\n" 45c62f1cccSMitsuru IWASAKI 46945137d9SNate Lawson static void acpi_print_string(char *s, size_t length); 478e6a8737SNate Lawson static void acpi_print_gas(struct ACPIgas *gas); 488e6a8737SNate Lawson static void acpi_handle_fadt(struct FADTbody *fadt); 49945137d9SNate Lawson static void acpi_print_cpu(u_char cpu_id); 50945137d9SNate Lawson static void acpi_print_local_apic(u_char cpu_id, u_char apic_id, 51945137d9SNate Lawson u_int32_t flags); 52945137d9SNate Lawson static void acpi_print_io_apic(u_char apic_id, u_int32_t int_base, 53945137d9SNate Lawson u_int64_t apic_addr); 54945137d9SNate Lawson static void acpi_print_mps_flags(u_int16_t flags); 55945137d9SNate Lawson static void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags); 56945137d9SNate Lawson static void acpi_print_apic(struct MADT_APIC *mp); 57945137d9SNate Lawson static void acpi_handle_apic(struct ACPIsdt *sdp); 58945137d9SNate Lawson static void acpi_handle_hpet(struct ACPIsdt *sdp); 59773b6454SNate Lawson static void acpi_print_sdt(struct ACPIsdt *sdp); 608e6a8737SNate Lawson static void acpi_print_fadt(struct FADTbody *fadt); 618e6a8737SNate Lawson static void acpi_print_facs(struct FACSbody *facs); 62945137d9SNate Lawson static void acpi_print_dsdt(struct ACPIsdt *dsdp); 63a74172abSNate Lawson static struct ACPIsdt *acpi_map_sdt(vm_offset_t pa); 64945137d9SNate Lawson static void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 65945137d9SNate Lawson static void acpi_handle_rsdt(struct ACPIsdt *rsdp); 66c62f1cccSMitsuru IWASAKI 67773b6454SNate Lawson /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */ 68a74172abSNate Lawson static int addr_size; 69a74172abSNate Lawson 70e1e9a4bfSMitsuru IWASAKI static void 71e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length) 72e1e9a4bfSMitsuru IWASAKI { 73e1e9a4bfSMitsuru IWASAKI int c; 74e1e9a4bfSMitsuru IWASAKI 75e1e9a4bfSMitsuru IWASAKI /* Trim trailing spaces and NULLs */ 76e1e9a4bfSMitsuru IWASAKI while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 77e1e9a4bfSMitsuru IWASAKI length--; 78e1e9a4bfSMitsuru IWASAKI 79e1e9a4bfSMitsuru IWASAKI while (length--) { 80e1e9a4bfSMitsuru IWASAKI c = *s++; 81e1e9a4bfSMitsuru IWASAKI putchar(c); 82e1e9a4bfSMitsuru IWASAKI } 83e1e9a4bfSMitsuru IWASAKI } 84e1e9a4bfSMitsuru IWASAKI 85e1e9a4bfSMitsuru IWASAKI static void 868e6a8737SNate Lawson acpi_print_gas(struct ACPIgas *gas) 878e6a8737SNate Lawson { 888e6a8737SNate Lawson switch(gas->address_space_id) { 898e6a8737SNate Lawson case ACPI_GAS_MEMORY: 90773b6454SNate Lawson printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->address, 918e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 928e6a8737SNate Lawson break; 938e6a8737SNate Lawson case ACPI_GAS_IO: 94e47f1780SNate Lawson printf("0x%02lx:%u[%u] (IO)", (u_long)gas->address, 958e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 968e6a8737SNate Lawson break; 978e6a8737SNate Lawson case ACPI_GAS_PCI: 98e47f1780SNate Lawson printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->address >> 32), 998e6a8737SNate Lawson (uint16_t)((gas->address >> 16) & 0xffff), 1008e6a8737SNate Lawson (uint16_t)gas->address); 1018e6a8737SNate Lawson break; 1028e6a8737SNate Lawson /* XXX How to handle these below? */ 1038e6a8737SNate Lawson case ACPI_GAS_EMBEDDED: 104e47f1780SNate Lawson printf("0x%x:%u[%u] (EC)", (uint16_t)gas->address, 1058e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 1068e6a8737SNate Lawson break; 1078e6a8737SNate Lawson case ACPI_GAS_SMBUS: 108e47f1780SNate Lawson printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->address, 1098e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 1108e6a8737SNate Lawson break; 1118e6a8737SNate Lawson case ACPI_GAS_FIXED: 1128e6a8737SNate Lawson default: 113773b6454SNate Lawson printf("0x%08lx (?)", (u_long)gas->address); 1148e6a8737SNate Lawson break; 1158e6a8737SNate Lawson } 1168e6a8737SNate Lawson } 1178e6a8737SNate Lawson 1188e6a8737SNate Lawson static void 1198e6a8737SNate Lawson acpi_handle_fadt(struct FADTbody *fadt) 120e1e9a4bfSMitsuru IWASAKI { 121e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *dsdp; 1228e6a8737SNate Lawson struct FACSbody *facs; 123e1e9a4bfSMitsuru IWASAKI 1248e6a8737SNate Lawson acpi_print_fadt(fadt); 1258e6a8737SNate Lawson 126773b6454SNate Lawson /* 127773b6454SNate Lawson * My T23 is revision 2 but the 64 bit addresses are invalid. 128773b6454SNate Lawson * If revision 2 and the 32 bit address is non-zero but the 32 129773b6454SNate Lawson * and 64 bit versions don't match, prefer the 32 bit version. 130773b6454SNate Lawson */ 131773b6454SNate Lawson if (addr_size == 4 || 132773b6454SNate Lawson (addr_size == 8 && fadt->facs_ptr != 0 && 133773b6454SNate Lawson (fadt->x_facs_ptr & 0xffffffff) != fadt->facs_ptr)) 1348e6a8737SNate Lawson facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr); 135773b6454SNate Lawson else 136773b6454SNate Lawson facs = (struct FACSbody *)acpi_map_sdt(fadt->x_facs_ptr); 1378e6a8737SNate Lawson if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64) 1388e6a8737SNate Lawson errx(1, "FACS is corrupt"); 1398e6a8737SNate Lawson acpi_print_facs(facs); 1408e6a8737SNate Lawson 141773b6454SNate Lawson if (addr_size == 4 || 142773b6454SNate Lawson (addr_size == 8 && fadt->dsdt_ptr != 0 && 143773b6454SNate Lawson (fadt->x_dsdt_ptr & 0xffffffff) != fadt->dsdt_ptr)) 1448e6a8737SNate Lawson dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 145773b6454SNate Lawson else 146773b6454SNate Lawson dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr); 147e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(dsdp, dsdp->len)) 148945137d9SNate Lawson errx(1, "DSDT is corrupt"); 149945137d9SNate Lawson acpi_print_dsdt(dsdp); 150c62f1cccSMitsuru IWASAKI } 151c62f1cccSMitsuru IWASAKI 152c62f1cccSMitsuru IWASAKI static void 1530a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id) 1540a473124SJohn Baldwin { 1550a473124SJohn Baldwin 1560a473124SJohn Baldwin printf("\tACPI CPU="); 1570a473124SJohn Baldwin if (cpu_id == 0xff) 1580a473124SJohn Baldwin printf("ALL\n"); 1590a473124SJohn Baldwin else 1600a473124SJohn Baldwin printf("%d\n", (u_int)cpu_id); 1610a473124SJohn Baldwin } 1620a473124SJohn Baldwin 1630a473124SJohn Baldwin static void 1640a473124SJohn Baldwin acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 1650a473124SJohn Baldwin { 1660a473124SJohn Baldwin acpi_print_cpu(cpu_id); 1670a473124SJohn Baldwin printf("\tFlags={"); 1680a473124SJohn Baldwin if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 1690a473124SJohn Baldwin printf("ENABLED"); 1700a473124SJohn Baldwin else 1710a473124SJohn Baldwin printf("DISABLED"); 1720a473124SJohn Baldwin printf("}\n"); 1730a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1740a473124SJohn Baldwin } 1750a473124SJohn Baldwin 1760a473124SJohn Baldwin static void 1770a473124SJohn Baldwin acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 1780a473124SJohn Baldwin { 1790a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1800a473124SJohn Baldwin printf("\tINT BASE=%d\n", int_base); 181945137d9SNate Lawson printf("\tADDR=0x%016jx\n", apic_addr); 1820a473124SJohn Baldwin } 1830a473124SJohn Baldwin 1840a473124SJohn Baldwin static void 1850a473124SJohn Baldwin acpi_print_mps_flags(u_int16_t flags) 1860a473124SJohn Baldwin { 1870a473124SJohn Baldwin 1880a473124SJohn Baldwin printf("\tFlags={Polarity="); 1890a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 1900a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_CONFORM: 1910a473124SJohn Baldwin printf("conforming"); 1920a473124SJohn Baldwin break; 1930a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_HIGH: 1940a473124SJohn Baldwin printf("active-hi"); 1950a473124SJohn Baldwin break; 1960a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_LOW: 1970a473124SJohn Baldwin printf("active-lo"); 1980a473124SJohn Baldwin break; 1990a473124SJohn Baldwin default: 2000a473124SJohn Baldwin printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 2010a473124SJohn Baldwin break; 2020a473124SJohn Baldwin } 2030a473124SJohn Baldwin printf(", Trigger="); 2040a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 2050a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_CONFORM: 2060a473124SJohn Baldwin printf("conforming"); 2070a473124SJohn Baldwin break; 2080a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_EDGE: 2090a473124SJohn Baldwin printf("edge"); 2100a473124SJohn Baldwin break; 2110a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_LEVEL: 2120a473124SJohn Baldwin printf("level"); 2130a473124SJohn Baldwin break; 2140a473124SJohn Baldwin default: 2150a473124SJohn Baldwin printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 2160a473124SJohn Baldwin } 2170a473124SJohn Baldwin printf("}\n"); 2180a473124SJohn Baldwin } 2190a473124SJohn Baldwin 2200a473124SJohn Baldwin static void 2210a473124SJohn Baldwin acpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 2220a473124SJohn Baldwin { 2230a473124SJohn Baldwin 2240a473124SJohn Baldwin printf("\tINTR=%d\n", (u_int)intr); 2250a473124SJohn Baldwin acpi_print_mps_flags(mps_flags); 2260a473124SJohn Baldwin } 2270a473124SJohn Baldwin 2280a473124SJohn Baldwin const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 2290a473124SJohn Baldwin "Local NMI", "Local APIC Override", "IO SAPIC", 2300a473124SJohn Baldwin "Local SAPIC", "Platform Interrupt" }; 2310a473124SJohn Baldwin const char *platform_int_types[] = { "PMI", "INIT", 2320a473124SJohn Baldwin "Corrected Platform Error" }; 2330a473124SJohn Baldwin 2340a473124SJohn Baldwin static void 2350a473124SJohn Baldwin acpi_print_apic(struct MADT_APIC *mp) 2360a473124SJohn Baldwin { 2370a473124SJohn Baldwin 2380a473124SJohn Baldwin printf("\tType=%s\n", apic_types[mp->type]); 2390a473124SJohn Baldwin switch (mp->type) { 2400a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 2410a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_apic.cpu_id, 2420a473124SJohn Baldwin mp->body.local_apic.apic_id, mp->body.local_apic.flags); 2430a473124SJohn Baldwin break; 2440a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_APIC: 2450a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_apic.apic_id, 2460a473124SJohn Baldwin mp->body.io_apic.int_base, 2470a473124SJohn Baldwin mp->body.io_apic.apic_addr); 2480a473124SJohn Baldwin break; 2490a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 2500a473124SJohn Baldwin printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 2510a473124SJohn Baldwin printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 2520a473124SJohn Baldwin acpi_print_intr(mp->body.int_override.intr, 2530a473124SJohn Baldwin mp->body.int_override.mps_flags); 2540a473124SJohn Baldwin break; 2550a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_NMI: 2560a473124SJohn Baldwin acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 2570a473124SJohn Baldwin break; 2580a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 2590a473124SJohn Baldwin acpi_print_cpu(mp->body.local_nmi.cpu_id); 2600a473124SJohn Baldwin printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 2610a473124SJohn Baldwin acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 2620a473124SJohn Baldwin break; 2630a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 264945137d9SNate Lawson printf("\tLocal APIC ADDR=0x%016jx\n", 265945137d9SNate Lawson mp->body.local_apic_override.apic_addr); 2660a473124SJohn Baldwin break; 2670a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_SAPIC: 2680a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_sapic.apic_id, 2690a473124SJohn Baldwin mp->body.io_sapic.int_base, 2700a473124SJohn Baldwin mp->body.io_sapic.apic_addr); 2710a473124SJohn Baldwin break; 2720a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 2730a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_sapic.cpu_id, 2740a473124SJohn Baldwin mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 2750a473124SJohn Baldwin printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 2760a473124SJohn Baldwin break; 2770a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_SRC: 2780a473124SJohn Baldwin printf("\tType=%s\n", 2790a473124SJohn Baldwin platform_int_types[mp->body.int_src.type]); 2800a473124SJohn Baldwin printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 2810a473124SJohn Baldwin printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 2820a473124SJohn Baldwin printf("\tSAPIC Vector=%d\n", 2830a473124SJohn Baldwin (u_int)mp->body.int_src.sapic_vector); 2840a473124SJohn Baldwin acpi_print_intr(mp->body.int_src.intr, 2850a473124SJohn Baldwin mp->body.int_src.mps_flags); 2860a473124SJohn Baldwin break; 2870a473124SJohn Baldwin default: 2880a473124SJohn Baldwin printf("\tUnknown type %d\n", (u_int)mp->type); 289945137d9SNate Lawson break; 2900a473124SJohn Baldwin } 2910a473124SJohn Baldwin } 2920a473124SJohn Baldwin 2930a473124SJohn Baldwin static void 2940a473124SJohn Baldwin acpi_handle_apic(struct ACPIsdt *sdp) 2950a473124SJohn Baldwin { 2960a473124SJohn Baldwin struct MADTbody *madtp; 2970a473124SJohn Baldwin struct MADT_APIC *madt_apicp; 2980a473124SJohn Baldwin 299773b6454SNate Lawson printf(BEGIN_COMMENT); 300773b6454SNate Lawson acpi_print_sdt(sdp); 3010a473124SJohn Baldwin madtp = (struct MADTbody *) sdp->body; 3020a473124SJohn Baldwin printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 3030a473124SJohn Baldwin printf("\tFlags={"); 3040a473124SJohn Baldwin if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 3050a473124SJohn Baldwin printf("PC-AT"); 3060a473124SJohn Baldwin printf("}\n"); 3070a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *)madtp->body; 3080a473124SJohn Baldwin while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 3090a473124SJohn Baldwin printf("\n"); 3100a473124SJohn Baldwin acpi_print_apic(madt_apicp); 3110a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 3120a473124SJohn Baldwin madt_apicp->len); 3130a473124SJohn Baldwin } 3140a473124SJohn Baldwin printf(END_COMMENT); 3150a473124SJohn Baldwin } 3160a473124SJohn Baldwin 3170a473124SJohn Baldwin static void 31879d7565cSPeter Wemm acpi_handle_hpet(struct ACPIsdt *sdp) 31979d7565cSPeter Wemm { 32079d7565cSPeter Wemm struct HPETbody *hpetp; 32179d7565cSPeter Wemm 322773b6454SNate Lawson printf(BEGIN_COMMENT); 323773b6454SNate Lawson acpi_print_sdt(sdp); 32479d7565cSPeter Wemm hpetp = (struct HPETbody *) sdp->body; 32579d7565cSPeter Wemm printf("\tHPET Number=%d\n", hpetp->hpet_number); 32679d7565cSPeter Wemm printf("\tADDR=0x%08x\n", hpetp->base_addr); 32779d7565cSPeter Wemm printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 32879d7565cSPeter Wemm printf("\tComparitors=%d\n", hpetp->block_comparitors); 32979d7565cSPeter Wemm printf("\tCounter Size=%d\n", hpetp->block_counter_size); 33079d7565cSPeter Wemm printf("\tLegacy IRQ routing capable={"); 33179d7565cSPeter Wemm if (hpetp->block_legacy_capable) 33279d7565cSPeter Wemm printf("TRUE}\n"); 33379d7565cSPeter Wemm else 33479d7565cSPeter Wemm printf("FALSE}\n"); 33579d7565cSPeter Wemm printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 33655da3c73SPeter Wemm printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 33779d7565cSPeter Wemm printf(END_COMMENT); 33879d7565cSPeter Wemm } 33979d7565cSPeter Wemm 34079d7565cSPeter Wemm static void 34155d7ff9eSNate Lawson acpi_handle_ecdt(struct ACPIsdt *sdp) 34255d7ff9eSNate Lawson { 34355d7ff9eSNate Lawson struct ECDTbody *ecdt; 34455d7ff9eSNate Lawson 34555d7ff9eSNate Lawson printf(BEGIN_COMMENT); 34655d7ff9eSNate Lawson acpi_print_sdt(sdp); 34755d7ff9eSNate Lawson ecdt = (struct ECDTbody *) sdp->body; 34855d7ff9eSNate Lawson printf("\tEC_CONTROL="); 34955d7ff9eSNate Lawson acpi_print_gas(&ecdt->ec_control); 35055d7ff9eSNate Lawson printf("\n\tEC_DATA="); 35155d7ff9eSNate Lawson acpi_print_gas(&ecdt->ec_data); 35255d7ff9eSNate Lawson printf("\n\tUID=%#x, ", ecdt->uid); 35355d7ff9eSNate Lawson printf("GPE_BIT=%#x\n", ecdt->gpe_bit); 35455d7ff9eSNate Lawson printf("\tEC_ID=%s\n", ecdt->ec_id); 35555d7ff9eSNate Lawson printf(END_COMMENT); 35655d7ff9eSNate Lawson } 35755d7ff9eSNate Lawson 35855d7ff9eSNate Lawson static void 359773b6454SNate Lawson acpi_print_sdt(struct ACPIsdt *sdp) 360c62f1cccSMitsuru IWASAKI { 361773b6454SNate Lawson printf(" "); 362e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->signature, 4); 363c62f1cccSMitsuru IWASAKI printf(": Length=%d, Revision=%d, Checksum=%d,\n", 364e1e9a4bfSMitsuru IWASAKI sdp->len, sdp->rev, sdp->check); 365e1e9a4bfSMitsuru IWASAKI printf("\tOEMID="); 366e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemid, 6); 367e1e9a4bfSMitsuru IWASAKI printf(", OEM Table ID="); 368e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemtblid, 8); 369e1e9a4bfSMitsuru IWASAKI printf(", OEM Revision=0x%x,\n", sdp->oemrev); 370e1e9a4bfSMitsuru IWASAKI printf("\tCreator ID="); 371e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->creator, 4); 372e1e9a4bfSMitsuru IWASAKI printf(", Creator Revision=0x%x\n", sdp->crerev); 373e1e9a4bfSMitsuru IWASAKI } 374e1e9a4bfSMitsuru IWASAKI 375945137d9SNate Lawson static void 376e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(struct ACPIsdt *rsdp) 377e1e9a4bfSMitsuru IWASAKI { 378e1e9a4bfSMitsuru IWASAKI int i, entries; 379a74172abSNate Lawson u_long addr; 380e1e9a4bfSMitsuru IWASAKI 381773b6454SNate Lawson printf(BEGIN_COMMENT); 382773b6454SNate Lawson acpi_print_sdt(rsdp); 383a74172abSNate Lawson entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 384e1e9a4bfSMitsuru IWASAKI printf("\tEntries={ "); 385e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 386e1e9a4bfSMitsuru IWASAKI if (i > 0) 387e1e9a4bfSMitsuru IWASAKI printf(", "); 388a74172abSNate Lawson switch (addr_size) { 389a74172abSNate Lawson case 4: 390a74172abSNate Lawson addr = le32dec((char*)rsdp->body + i * addr_size); 391a74172abSNate Lawson break; 392a74172abSNate Lawson case 8: 393a74172abSNate Lawson addr = le64dec((char*)rsdp->body + i * addr_size); 394a74172abSNate Lawson break; 395a74172abSNate Lawson default: 396a74172abSNate Lawson addr = 0; 397a74172abSNate Lawson } 398a74172abSNate Lawson assert(addr != 0); 399a74172abSNate Lawson printf("0x%08lx", addr); 400e1e9a4bfSMitsuru IWASAKI } 401e1e9a4bfSMitsuru IWASAKI printf(" }\n"); 402c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 403e1e9a4bfSMitsuru IWASAKI } 404e1e9a4bfSMitsuru IWASAKI 4058e6a8737SNate Lawson static const char *acpi_pm_profiles[] = { 4068e6a8737SNate Lawson "Unspecified", "Desktop", "Mobile", "Workstation", 4078e6a8737SNate Lawson "Enterprise Server", "SOHO Server", "Appliance PC" 4088e6a8737SNate Lawson }; 4098e6a8737SNate Lawson 410945137d9SNate Lawson static void 4118e6a8737SNate Lawson acpi_print_fadt(struct FADTbody *fadt) 412e1e9a4bfSMitsuru IWASAKI { 4138e6a8737SNate Lawson const char *pm; 414e1e9a4bfSMitsuru IWASAKI char sep; 415e1e9a4bfSMitsuru IWASAKI 416c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 4178e6a8737SNate Lawson printf(" FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr, 4188e6a8737SNate Lawson fadt->dsdt_ptr); 4198e6a8737SNate Lawson printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC"); 4208e6a8737SNate Lawson if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 4218e6a8737SNate Lawson pm = "Reserved"; 4228e6a8737SNate Lawson else 4238e6a8737SNate Lawson pm = acpi_pm_profiles[fadt->pm_profile]; 4248e6a8737SNate Lawson printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile); 4258e6a8737SNate Lawson printf("\tSCI_INT=%d\n", fadt->sci_int); 4268e6a8737SNate Lawson printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd); 4278e6a8737SNate Lawson printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable); 4288e6a8737SNate Lawson printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable); 4298e6a8737SNate Lawson printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq); 4308e6a8737SNate Lawson printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt); 431e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 4328e6a8737SNate Lawson fadt->pm1a_evt_blk, 4338e6a8737SNate Lawson fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1); 4348e6a8737SNate Lawson if (fadt->pm1b_evt_blk != 0) 435e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 4368e6a8737SNate Lawson fadt->pm1b_evt_blk, 4378e6a8737SNate Lawson fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1); 438e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 4398e6a8737SNate Lawson fadt->pm1a_cnt_blk, 4408e6a8737SNate Lawson fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1); 4418e6a8737SNate Lawson if (fadt->pm1b_cnt_blk != 0) 442e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 4438e6a8737SNate Lawson fadt->pm1b_cnt_blk, 4448e6a8737SNate Lawson fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1); 4458e6a8737SNate Lawson if (fadt->pm2_cnt_blk != 0) 446e1e9a4bfSMitsuru IWASAKI printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 4478e6a8737SNate Lawson fadt->pm2_cnt_blk, 4488e6a8737SNate Lawson fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1); 449c08c4e81SNate Lawson printf("\tPM_TMR_BLK=0x%x-0x%x\n", 4508e6a8737SNate Lawson fadt->pm_tmr_blk, 4518e6a8737SNate Lawson fadt->pm_tmr_blk + fadt->pm_tmr_len - 1); 4528e6a8737SNate Lawson if (fadt->gpe0_blk != 0) 4538e6a8737SNate Lawson printf("\tGPE0_BLK=0x%x-0x%x\n", 4548e6a8737SNate Lawson fadt->gpe0_blk, 4558e6a8737SNate Lawson fadt->gpe0_blk + fadt->gpe0_len - 1); 4568e6a8737SNate Lawson if (fadt->gpe1_blk != 0) 4578e6a8737SNate Lawson printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 4588e6a8737SNate Lawson fadt->gpe1_blk, 4598e6a8737SNate Lawson fadt->gpe1_blk + fadt->gpe1_len - 1, 4608e6a8737SNate Lawson fadt->gpe1_base); 4618e6a8737SNate Lawson if (fadt->cst_cnt != 0) 4628e6a8737SNate Lawson printf("\tCST_CNT=0x%x\n", fadt->cst_cnt); 463e1e9a4bfSMitsuru IWASAKI printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 4648e6a8737SNate Lawson fadt->p_lvl2_lat, fadt->p_lvl3_lat); 465e1e9a4bfSMitsuru IWASAKI printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 4668e6a8737SNate Lawson fadt->flush_size, fadt->flush_stride); 467e1e9a4bfSMitsuru IWASAKI printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 4688e6a8737SNate Lawson fadt->duty_off, fadt->duty_width); 469e1e9a4bfSMitsuru IWASAKI printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 4708e6a8737SNate Lawson fadt->day_alrm, fadt->mon_alrm, fadt->century); 471e1e9a4bfSMitsuru IWASAKI 4728e6a8737SNate Lawson #define PRINTFLAG(var, flag) do { \ 4738e6a8737SNate Lawson if ((var) & FADT_FLAG_## flag) { \ 4748e6a8737SNate Lawson printf("%c%s", sep, #flag); sep = ','; \ 475e1e9a4bfSMitsuru IWASAKI } \ 476e1e9a4bfSMitsuru IWASAKI } while (0) 477e1e9a4bfSMitsuru IWASAKI 4788e6a8737SNate Lawson printf("\tIAPC_BOOT_ARCH="); 4798e6a8737SNate Lawson sep = '{'; 4808e6a8737SNate Lawson PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV); 4818e6a8737SNate Lawson PRINTFLAG(fadt->iapc_boot_arch, 8042); 4828e6a8737SNate Lawson printf("}\n"); 4838e6a8737SNate Lawson 4848e6a8737SNate Lawson printf("\tFlags="); 4858e6a8737SNate Lawson sep = '{'; 4868e6a8737SNate Lawson PRINTFLAG(fadt->flags, WBINVD); 4878e6a8737SNate Lawson PRINTFLAG(fadt->flags, WBINVD_FLUSH); 4888e6a8737SNate Lawson PRINTFLAG(fadt->flags, PROC_C1); 4898e6a8737SNate Lawson PRINTFLAG(fadt->flags, P_LVL2_UP); 4908e6a8737SNate Lawson PRINTFLAG(fadt->flags, PWR_BUTTON); 4918e6a8737SNate Lawson PRINTFLAG(fadt->flags, SLP_BUTTON); 4928e6a8737SNate Lawson PRINTFLAG(fadt->flags, FIX_RTC); 4938e6a8737SNate Lawson PRINTFLAG(fadt->flags, RTC_S4); 4948e6a8737SNate Lawson PRINTFLAG(fadt->flags, TMR_VAL_EXT); 4958e6a8737SNate Lawson PRINTFLAG(fadt->flags, DCK_CAP); 4968e6a8737SNate Lawson PRINTFLAG(fadt->flags, RESET_REG); 4978e6a8737SNate Lawson PRINTFLAG(fadt->flags, SEALED_CASE); 4988e6a8737SNate Lawson PRINTFLAG(fadt->flags, HEADLESS); 4998e6a8737SNate Lawson PRINTFLAG(fadt->flags, CPU_SW_SLP); 5008e6a8737SNate Lawson printf("}\n"); 501e1e9a4bfSMitsuru IWASAKI 502e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG 503e1e9a4bfSMitsuru IWASAKI 5048e6a8737SNate Lawson if (fadt->flags & FADT_FLAG_RESET_REG) { 5058e6a8737SNate Lawson printf("\tRESET_REG="); 5068e6a8737SNate Lawson acpi_print_gas(&fadt->reset_reg); 5078e6a8737SNate Lawson printf(", RESET_VALUE=%#x\n", fadt->reset_value); 5088e6a8737SNate Lawson } 509773b6454SNate Lawson if (addr_size == 8) { 510773b6454SNate Lawson printf("\tX_FACS=0x%08lx, ", (u_long)fadt->x_facs_ptr); 511773b6454SNate Lawson printf("X_DSDT=0x%08lx\n", (u_long)fadt->x_dsdt_ptr); 512c08c4e81SNate Lawson printf("\tX_PM1a_EVT_BLK="); 513773b6454SNate Lawson acpi_print_gas(&fadt->x_pm1a_evt_blk); 514c08c4e81SNate Lawson if (fadt->x_pm1b_evt_blk.address != 0) { 515c08c4e81SNate Lawson printf("\n\tX_PM1b_EVT_BLK="); 516773b6454SNate Lawson acpi_print_gas(&fadt->x_pm1b_evt_blk); 517c08c4e81SNate Lawson } 518c08c4e81SNate Lawson printf("\n\tX_PM1a_CNT_BLK="); 519773b6454SNate Lawson acpi_print_gas(&fadt->x_pm1a_cnt_blk); 520c08c4e81SNate Lawson if (fadt->x_pm1b_cnt_blk.address != 0) { 521c08c4e81SNate Lawson printf("\n\tX_PM1b_CNT_BLK="); 522773b6454SNate Lawson acpi_print_gas(&fadt->x_pm1b_cnt_blk); 523c08c4e81SNate Lawson } 524c08c4e81SNate Lawson if (fadt->x_pm1b_cnt_blk.address != 0) { 525773b6454SNate Lawson printf("\n\tX_PM2_CNT_BLK="); 526773b6454SNate Lawson acpi_print_gas(&fadt->x_pm2_cnt_blk); 527c08c4e81SNate Lawson } 528773b6454SNate Lawson printf("\n\tX_PM_TMR_BLK="); 529773b6454SNate Lawson acpi_print_gas(&fadt->x_pm_tmr_blk); 530c08c4e81SNate Lawson if (fadt->x_gpe0_blk.address != 0) { 531773b6454SNate Lawson printf("\n\tX_GPE0_BLK="); 532773b6454SNate Lawson acpi_print_gas(&fadt->x_gpe0_blk); 533c08c4e81SNate Lawson } 534c08c4e81SNate Lawson if (fadt->x_gpe1_blk.address != 0) { 535773b6454SNate Lawson printf("\n\tX_GPE1_BLK="); 536773b6454SNate Lawson acpi_print_gas(&fadt->x_gpe1_blk); 537c08c4e81SNate Lawson } 538773b6454SNate Lawson printf("\n"); 539773b6454SNate Lawson } 5408e6a8737SNate Lawson 5418e6a8737SNate Lawson printf(END_COMMENT); 5428e6a8737SNate Lawson } 5438e6a8737SNate Lawson 5448e6a8737SNate Lawson static void 5458e6a8737SNate Lawson acpi_print_facs(struct FACSbody *facs) 5468e6a8737SNate Lawson { 5478e6a8737SNate Lawson printf(BEGIN_COMMENT); 5488e6a8737SNate Lawson printf(" FACS:\tLength=%u, ", facs->len); 5498e6a8737SNate Lawson printf("HwSig=0x%08x, ", facs->hw_sig); 5508e6a8737SNate Lawson printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec); 5518e6a8737SNate Lawson 552773b6454SNate Lawson printf("\tGlobal_Lock="); 5538e6a8737SNate Lawson if (facs->global_lock != 0) { 5548e6a8737SNate Lawson if (facs->global_lock & FACS_FLAG_LOCK_PENDING) 5558e6a8737SNate Lawson printf("PENDING,"); 5568e6a8737SNate Lawson if (facs->global_lock & FACS_FLAG_LOCK_OWNED) 5578e6a8737SNate Lawson printf("OWNED"); 5588e6a8737SNate Lawson } 559773b6454SNate Lawson printf("\n"); 5608e6a8737SNate Lawson 561773b6454SNate Lawson printf("\tFlags="); 5628e6a8737SNate Lawson if (facs->flags & FACS_FLAG_S4BIOS_F) 5638e6a8737SNate Lawson printf("S4BIOS"); 564773b6454SNate Lawson printf("\n"); 5658e6a8737SNate Lawson 5668e6a8737SNate Lawson if (facs->x_firm_wake_vec != 0) { 5678e6a8737SNate Lawson printf("\tX_Firm_Wake_Vec=%08lx\n", 5688e6a8737SNate Lawson (u_long)facs->x_firm_wake_vec); 5698e6a8737SNate Lawson } 570773b6454SNate Lawson printf("\tVersion=%u\n", facs->version); 5718e6a8737SNate Lawson 572c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 573e1e9a4bfSMitsuru IWASAKI } 574e1e9a4bfSMitsuru IWASAKI 575945137d9SNate Lawson static void 576e1e9a4bfSMitsuru IWASAKI acpi_print_dsdt(struct ACPIsdt *dsdp) 577e1e9a4bfSMitsuru IWASAKI { 578773b6454SNate Lawson printf(BEGIN_COMMENT); 579773b6454SNate Lawson acpi_print_sdt(dsdp); 580773b6454SNate Lawson printf(END_COMMENT); 581e1e9a4bfSMitsuru IWASAKI } 582e1e9a4bfSMitsuru IWASAKI 583e1e9a4bfSMitsuru IWASAKI int 584e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length) 585e1e9a4bfSMitsuru IWASAKI { 586e1e9a4bfSMitsuru IWASAKI u_int8_t *bp; 587e1e9a4bfSMitsuru IWASAKI u_int8_t sum; 588e1e9a4bfSMitsuru IWASAKI 589e1e9a4bfSMitsuru IWASAKI bp = p; 590e1e9a4bfSMitsuru IWASAKI sum = 0; 591e1e9a4bfSMitsuru IWASAKI while (length--) 592e1e9a4bfSMitsuru IWASAKI sum += *bp++; 593e1e9a4bfSMitsuru IWASAKI 594e1e9a4bfSMitsuru IWASAKI return (sum); 595e1e9a4bfSMitsuru IWASAKI } 596e1e9a4bfSMitsuru IWASAKI 597945137d9SNate Lawson static struct ACPIsdt * 598e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa) 599e1e9a4bfSMitsuru IWASAKI { 600e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sp; 601e1e9a4bfSMitsuru IWASAKI 602e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 603e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sp->len); 604e1e9a4bfSMitsuru IWASAKI return (sp); 605e1e9a4bfSMitsuru IWASAKI } 606e1e9a4bfSMitsuru IWASAKI 607945137d9SNate Lawson static void 608e1e9a4bfSMitsuru IWASAKI acpi_print_rsd_ptr(struct ACPIrsdp *rp) 609e1e9a4bfSMitsuru IWASAKI { 610c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 611a74172abSNate Lawson printf(" RSD PTR: OEM="); 612e1e9a4bfSMitsuru IWASAKI acpi_print_string(rp->oem, 6); 613773b6454SNate Lawson printf(", ACPI_Rev=%s (%d)\n", rp->revision < 2 ? "1.0x" : "2.0x", 614a74172abSNate Lawson rp->revision); 615a74172abSNate Lawson if (rp->revision < 2) { 616a74172abSNate Lawson printf("\tRSDT=0x%08x, cksum=%u\n", rp->rsdt_addr, rp->sum); 617a74172abSNate Lawson } else { 618a74172abSNate Lawson printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n", 619a74172abSNate Lawson (u_long)rp->xsdt_addr, rp->length, rp->xsum); 620a74172abSNate Lawson } 621c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 622e1e9a4bfSMitsuru IWASAKI } 623e1e9a4bfSMitsuru IWASAKI 624945137d9SNate Lawson static void 625e1e9a4bfSMitsuru IWASAKI acpi_handle_rsdt(struct ACPIsdt *rsdp) 626e1e9a4bfSMitsuru IWASAKI { 627e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sdp; 628a74172abSNate Lawson vm_offset_t addr; 629a74172abSNate Lawson int entries, i; 630e1e9a4bfSMitsuru IWASAKI 631e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(rsdp); 632a74172abSNate Lawson entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 633e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 634a74172abSNate Lawson switch (addr_size) { 635a74172abSNate Lawson case 4: 636a74172abSNate Lawson addr = le32dec((char*)rsdp->body + i * addr_size); 637a74172abSNate Lawson break; 638a74172abSNate Lawson case 8: 639a74172abSNate Lawson addr = le64dec((char*)rsdp->body + i * addr_size); 640a74172abSNate Lawson break; 641a74172abSNate Lawson default: 642a74172abSNate Lawson assert((addr = 0)); 643a74172abSNate Lawson } 644a74172abSNate Lawson 645a74172abSNate Lawson sdp = (struct ACPIsdt *)acpi_map_sdt(addr); 646e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(sdp, sdp->len)) 647945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 648945137d9SNate Lawson if (!memcmp(sdp->signature, "FACP", 4)) 6498e6a8737SNate Lawson acpi_handle_fadt((struct FADTbody *) sdp->body); 650945137d9SNate Lawson else if (!memcmp(sdp->signature, "APIC", 4)) 6510a473124SJohn Baldwin acpi_handle_apic(sdp); 652945137d9SNate Lawson else if (!memcmp(sdp->signature, "HPET", 4)) 65379d7565cSPeter Wemm acpi_handle_hpet(sdp); 65455d7ff9eSNate Lawson else if (!memcmp(sdp->signature, "ECDT", 4)) 65555d7ff9eSNate Lawson acpi_handle_ecdt(sdp); 656773b6454SNate Lawson else { 657773b6454SNate Lawson printf(BEGIN_COMMENT); 658773b6454SNate Lawson acpi_print_sdt(sdp); 659773b6454SNate Lawson printf(END_COMMENT); 660773b6454SNate Lawson } 661e1e9a4bfSMitsuru IWASAKI } 662e1e9a4bfSMitsuru IWASAKI } 663c62f1cccSMitsuru IWASAKI 664945137d9SNate Lawson struct ACPIsdt * 665945137d9SNate Lawson sdt_load_devmem() 666945137d9SNate Lawson { 667945137d9SNate Lawson struct ACPIrsdp *rp; 668945137d9SNate Lawson struct ACPIsdt *rsdp; 669945137d9SNate Lawson 670945137d9SNate Lawson rp = acpi_find_rsd_ptr(); 671945137d9SNate Lawson if (!rp) 672945137d9SNate Lawson errx(1, "Can't find ACPI information"); 673945137d9SNate Lawson 674945137d9SNate Lawson if (tflag) 675945137d9SNate Lawson acpi_print_rsd_ptr(rp); 676a74172abSNate Lawson if (rp->revision < 2) { 677945137d9SNate Lawson rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 678945137d9SNate Lawson if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 679945137d9SNate Lawson acpi_checksum(rsdp, rsdp->len) != 0) 680945137d9SNate Lawson errx(1, "RSDT is corrupted"); 681a74172abSNate Lawson addr_size = sizeof(uint32_t); 682a74172abSNate Lawson } else { 683a74172abSNate Lawson rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr); 684a74172abSNate Lawson if (memcmp(rsdp->signature, "XSDT", 4) != 0 || 685a74172abSNate Lawson acpi_checksum(rsdp, rsdp->len) != 0) 686a74172abSNate Lawson errx(1, "XSDT is corrupted"); 687a74172abSNate Lawson addr_size = sizeof(uint64_t); 688a74172abSNate Lawson } 689945137d9SNate Lawson return (rsdp); 690945137d9SNate Lawson } 691c62f1cccSMitsuru IWASAKI 692c62f1cccSMitsuru IWASAKI void 693945137d9SNate Lawson dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 694c62f1cccSMitsuru IWASAKI { 695945137d9SNate Lawson int fd; 696945137d9SNate Lawson mode_t mode; 697945137d9SNate Lawson 698945137d9SNate Lawson assert(outfile != NULL); 699945137d9SNate Lawson mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 700945137d9SNate Lawson fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 701945137d9SNate Lawson if (fd == -1) { 702945137d9SNate Lawson perror("dsdt_save_file"); 703945137d9SNate Lawson return; 704945137d9SNate Lawson } 705945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 706945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 707945137d9SNate Lawson close(fd); 708c62f1cccSMitsuru IWASAKI } 709c62f1cccSMitsuru IWASAKI 710945137d9SNate Lawson void 711945137d9SNate Lawson aml_disassemble(struct ACPIsdt *dsdp) 712c62f1cccSMitsuru IWASAKI { 713945137d9SNate Lawson char tmpstr[32], buf[256]; 714945137d9SNate Lawson FILE *fp; 715945137d9SNate Lawson int fd, len; 716945137d9SNate Lawson 717945137d9SNate Lawson strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 718945137d9SNate Lawson fd = mkstemp(tmpstr); 719945137d9SNate Lawson if (fd < 0) { 720945137d9SNate Lawson perror("iasl tmp file"); 721945137d9SNate Lawson return; 722c62f1cccSMitsuru IWASAKI } 723c62f1cccSMitsuru IWASAKI 724945137d9SNate Lawson /* Dump DSDT to the temp file */ 725945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 726945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 727945137d9SNate Lawson close(fd); 728945137d9SNate Lawson 729945137d9SNate Lawson /* Run iasl -d on the temp file */ 730945137d9SNate Lawson if (fork() == 0) { 731945137d9SNate Lawson close(STDOUT_FILENO); 732945137d9SNate Lawson if (vflag == 0) 733945137d9SNate Lawson close(STDERR_FILENO); 734945137d9SNate Lawson execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 735945137d9SNate Lawson err(1, "exec"); 736c62f1cccSMitsuru IWASAKI } 737c62f1cccSMitsuru IWASAKI 738945137d9SNate Lawson wait(NULL); 739945137d9SNate Lawson unlink(tmpstr); 740945137d9SNate Lawson 741945137d9SNate Lawson /* Dump iasl's output to stdout */ 742945137d9SNate Lawson fp = fopen("acpidump.dsl", "r"); 743945137d9SNate Lawson unlink("acpidump.dsl"); 744945137d9SNate Lawson if (fp == NULL) { 745945137d9SNate Lawson perror("iasl tmp file (read)"); 746945137d9SNate Lawson return; 747945137d9SNate Lawson } 748945137d9SNate Lawson while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 749945137d9SNate Lawson fwrite(buf, 1, len, stdout); 750945137d9SNate Lawson fclose(fp); 751c62f1cccSMitsuru IWASAKI } 752c62f1cccSMitsuru IWASAKI 753945137d9SNate Lawson void 754945137d9SNate Lawson sdt_print_all(struct ACPIsdt *rsdp) 755c62f1cccSMitsuru IWASAKI { 756945137d9SNate Lawson acpi_handle_rsdt(rsdp); 757c62f1cccSMitsuru IWASAKI } 758c62f1cccSMitsuru IWASAKI 759945137d9SNate Lawson /* Fetch a table matching the given signature via the RSDT */ 760945137d9SNate Lawson struct ACPIsdt * 761945137d9SNate Lawson sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 762c62f1cccSMitsuru IWASAKI { 763945137d9SNate Lawson struct ACPIsdt *sdt; 764a74172abSNate Lawson vm_offset_t addr; 765a74172abSNate Lawson int entries, i; 766945137d9SNate Lawson 767a74172abSNate Lawson entries = (rsdt->len - SIZEOF_SDT_HDR) / addr_size; 768945137d9SNate Lawson for (i = 0; i < entries; i++) { 769a74172abSNate Lawson switch (addr_size) { 770a74172abSNate Lawson case 4: 771a74172abSNate Lawson addr = le32dec((char*)rsdt->body + i * addr_size); 772a74172abSNate Lawson break; 773a74172abSNate Lawson case 8: 774a74172abSNate Lawson addr = le64dec((char*)rsdt->body + i * addr_size); 775a74172abSNate Lawson break; 776a74172abSNate Lawson default: 777a74172abSNate Lawson assert((addr = 0)); 778a74172abSNate Lawson } 779a74172abSNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(addr); 780a74172abSNate Lawson if (memcmp(sdt->signature, sig, strlen(sig))) 781a74172abSNate Lawson continue; 782945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 783945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 784945137d9SNate Lawson return (sdt); 785c62f1cccSMitsuru IWASAKI } 786c62f1cccSMitsuru IWASAKI 787945137d9SNate Lawson return (NULL); 788c62f1cccSMitsuru IWASAKI } 789c62f1cccSMitsuru IWASAKI 790945137d9SNate Lawson struct ACPIsdt * 7918e6a8737SNate Lawson dsdt_from_fadt(struct FADTbody *fadt) 792c62f1cccSMitsuru IWASAKI { 793945137d9SNate Lawson struct ACPIsdt *sdt; 794c62f1cccSMitsuru IWASAKI 7958e6a8737SNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 796945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 797945137d9SNate Lawson errx(1, "DSDT is corrupt\n"); 798945137d9SNate Lawson return (sdt); 799c62f1cccSMitsuru IWASAKI } 800