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); 59945137d9SNate Lawson static void acpi_print_sdt(struct ACPIsdt *sdp, int endcomment); 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 67a74172abSNate Lawson /* 68a74172abSNate Lawson * Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. 69a74172abSNate Lawson */ 70a74172abSNate Lawson static int addr_size; 71a74172abSNate Lawson 72e1e9a4bfSMitsuru IWASAKI static void 73e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length) 74e1e9a4bfSMitsuru IWASAKI { 75e1e9a4bfSMitsuru IWASAKI int c; 76e1e9a4bfSMitsuru IWASAKI 77e1e9a4bfSMitsuru IWASAKI /* Trim trailing spaces and NULLs */ 78e1e9a4bfSMitsuru IWASAKI while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 79e1e9a4bfSMitsuru IWASAKI length--; 80e1e9a4bfSMitsuru IWASAKI 81e1e9a4bfSMitsuru IWASAKI while (length--) { 82e1e9a4bfSMitsuru IWASAKI c = *s++; 83e1e9a4bfSMitsuru IWASAKI putchar(c); 84e1e9a4bfSMitsuru IWASAKI } 85e1e9a4bfSMitsuru IWASAKI } 86e1e9a4bfSMitsuru IWASAKI 87e1e9a4bfSMitsuru IWASAKI static void 888e6a8737SNate Lawson acpi_print_gas(struct ACPIgas *gas) 898e6a8737SNate Lawson { 908e6a8737SNate Lawson switch(gas->address_space_id) { 918e6a8737SNate Lawson case ACPI_GAS_MEMORY: 928e6a8737SNate Lawson printf("0x%08lx:%u[%u] (Memory)\n", (u_long)gas->address, 938e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 948e6a8737SNate Lawson break; 958e6a8737SNate Lawson case ACPI_GAS_IO: 968e6a8737SNate Lawson printf("0x%08lx:%u[%u] (IO)\n", (u_long)gas->address, 978e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 988e6a8737SNate Lawson break; 998e6a8737SNate Lawson case ACPI_GAS_PCI: 1008e6a8737SNate Lawson printf("%x:%x+%#x (PCI)\n", (uint16_t)(gas->address >> 32), 1018e6a8737SNate Lawson (uint16_t)((gas->address >> 16) & 0xffff), 1028e6a8737SNate Lawson (uint16_t)gas->address); 1038e6a8737SNate Lawson break; 1048e6a8737SNate Lawson /* XXX How to handle these below? */ 1058e6a8737SNate Lawson case ACPI_GAS_EMBEDDED: 1068e6a8737SNate Lawson printf("0x%#x:%u[%u] (EC)\n", (uint16_t)gas->address, 1078e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 1088e6a8737SNate Lawson break; 1098e6a8737SNate Lawson case ACPI_GAS_SMBUS: 1108e6a8737SNate Lawson printf("0x%#x:%u[%u] (SMBus)\n", (uint16_t)gas->address, 1118e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 1128e6a8737SNate Lawson break; 1138e6a8737SNate Lawson case ACPI_GAS_FIXED: 1148e6a8737SNate Lawson default: 1158e6a8737SNate Lawson printf("0x%08lx (?)\n", (u_long)gas->address); 1168e6a8737SNate Lawson break; 1178e6a8737SNate Lawson } 1188e6a8737SNate Lawson } 1198e6a8737SNate Lawson 1208e6a8737SNate Lawson static void 1218e6a8737SNate Lawson acpi_handle_fadt(struct FADTbody *fadt) 122e1e9a4bfSMitsuru IWASAKI { 123e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *dsdp; 1248e6a8737SNate Lawson struct FACSbody *facs; 125e1e9a4bfSMitsuru IWASAKI 1268e6a8737SNate Lawson acpi_print_fadt(fadt); 1278e6a8737SNate Lawson 1288e6a8737SNate Lawson facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr); 1298e6a8737SNate Lawson if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64) 1308e6a8737SNate Lawson errx(1, "FACS is corrupt"); 1318e6a8737SNate Lawson acpi_print_facs(facs); 1328e6a8737SNate Lawson 1338e6a8737SNate Lawson dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 134e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(dsdp, dsdp->len)) 135945137d9SNate Lawson errx(1, "DSDT is corrupt"); 136945137d9SNate Lawson acpi_print_dsdt(dsdp); 137c62f1cccSMitsuru IWASAKI } 138c62f1cccSMitsuru IWASAKI 139c62f1cccSMitsuru IWASAKI static void 1400a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id) 1410a473124SJohn Baldwin { 1420a473124SJohn Baldwin 1430a473124SJohn Baldwin printf("\tACPI CPU="); 1440a473124SJohn Baldwin if (cpu_id == 0xff) 1450a473124SJohn Baldwin printf("ALL\n"); 1460a473124SJohn Baldwin else 1470a473124SJohn Baldwin printf("%d\n", (u_int)cpu_id); 1480a473124SJohn Baldwin } 1490a473124SJohn Baldwin 1500a473124SJohn Baldwin static void 1510a473124SJohn Baldwin acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 1520a473124SJohn Baldwin { 1530a473124SJohn Baldwin acpi_print_cpu(cpu_id); 1540a473124SJohn Baldwin printf("\tFlags={"); 1550a473124SJohn Baldwin if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 1560a473124SJohn Baldwin printf("ENABLED"); 1570a473124SJohn Baldwin else 1580a473124SJohn Baldwin printf("DISABLED"); 1590a473124SJohn Baldwin printf("}\n"); 1600a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1610a473124SJohn Baldwin } 1620a473124SJohn Baldwin 1630a473124SJohn Baldwin static void 1640a473124SJohn Baldwin acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 1650a473124SJohn Baldwin { 1660a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1670a473124SJohn Baldwin printf("\tINT BASE=%d\n", int_base); 168945137d9SNate Lawson printf("\tADDR=0x%016jx\n", apic_addr); 1690a473124SJohn Baldwin } 1700a473124SJohn Baldwin 1710a473124SJohn Baldwin static void 1720a473124SJohn Baldwin acpi_print_mps_flags(u_int16_t flags) 1730a473124SJohn Baldwin { 1740a473124SJohn Baldwin 1750a473124SJohn Baldwin printf("\tFlags={Polarity="); 1760a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 1770a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_CONFORM: 1780a473124SJohn Baldwin printf("conforming"); 1790a473124SJohn Baldwin break; 1800a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_HIGH: 1810a473124SJohn Baldwin printf("active-hi"); 1820a473124SJohn Baldwin break; 1830a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_LOW: 1840a473124SJohn Baldwin printf("active-lo"); 1850a473124SJohn Baldwin break; 1860a473124SJohn Baldwin default: 1870a473124SJohn Baldwin printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 1880a473124SJohn Baldwin break; 1890a473124SJohn Baldwin } 1900a473124SJohn Baldwin printf(", Trigger="); 1910a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 1920a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_CONFORM: 1930a473124SJohn Baldwin printf("conforming"); 1940a473124SJohn Baldwin break; 1950a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_EDGE: 1960a473124SJohn Baldwin printf("edge"); 1970a473124SJohn Baldwin break; 1980a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_LEVEL: 1990a473124SJohn Baldwin printf("level"); 2000a473124SJohn Baldwin break; 2010a473124SJohn Baldwin default: 2020a473124SJohn Baldwin printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 2030a473124SJohn Baldwin } 2040a473124SJohn Baldwin printf("}\n"); 2050a473124SJohn Baldwin } 2060a473124SJohn Baldwin 2070a473124SJohn Baldwin static void 2080a473124SJohn Baldwin acpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 2090a473124SJohn Baldwin { 2100a473124SJohn Baldwin 2110a473124SJohn Baldwin printf("\tINTR=%d\n", (u_int)intr); 2120a473124SJohn Baldwin acpi_print_mps_flags(mps_flags); 2130a473124SJohn Baldwin } 2140a473124SJohn Baldwin 2150a473124SJohn Baldwin const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 2160a473124SJohn Baldwin "Local NMI", "Local APIC Override", "IO SAPIC", 2170a473124SJohn Baldwin "Local SAPIC", "Platform Interrupt" }; 2180a473124SJohn Baldwin const char *platform_int_types[] = { "PMI", "INIT", 2190a473124SJohn Baldwin "Corrected Platform Error" }; 2200a473124SJohn Baldwin 2210a473124SJohn Baldwin static void 2220a473124SJohn Baldwin acpi_print_apic(struct MADT_APIC *mp) 2230a473124SJohn Baldwin { 2240a473124SJohn Baldwin 2250a473124SJohn Baldwin printf("\tType=%s\n", apic_types[mp->type]); 2260a473124SJohn Baldwin switch (mp->type) { 2270a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 2280a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_apic.cpu_id, 2290a473124SJohn Baldwin mp->body.local_apic.apic_id, mp->body.local_apic.flags); 2300a473124SJohn Baldwin break; 2310a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_APIC: 2320a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_apic.apic_id, 2330a473124SJohn Baldwin mp->body.io_apic.int_base, 2340a473124SJohn Baldwin mp->body.io_apic.apic_addr); 2350a473124SJohn Baldwin break; 2360a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 2370a473124SJohn Baldwin printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 2380a473124SJohn Baldwin printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 2390a473124SJohn Baldwin acpi_print_intr(mp->body.int_override.intr, 2400a473124SJohn Baldwin mp->body.int_override.mps_flags); 2410a473124SJohn Baldwin break; 2420a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_NMI: 2430a473124SJohn Baldwin acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 2440a473124SJohn Baldwin break; 2450a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 2460a473124SJohn Baldwin acpi_print_cpu(mp->body.local_nmi.cpu_id); 2470a473124SJohn Baldwin printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 2480a473124SJohn Baldwin acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 2490a473124SJohn Baldwin break; 2500a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 251945137d9SNate Lawson printf("\tLocal APIC ADDR=0x%016jx\n", 252945137d9SNate Lawson mp->body.local_apic_override.apic_addr); 2530a473124SJohn Baldwin break; 2540a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_SAPIC: 2550a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_sapic.apic_id, 2560a473124SJohn Baldwin mp->body.io_sapic.int_base, 2570a473124SJohn Baldwin mp->body.io_sapic.apic_addr); 2580a473124SJohn Baldwin break; 2590a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 2600a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_sapic.cpu_id, 2610a473124SJohn Baldwin mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 2620a473124SJohn Baldwin printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 2630a473124SJohn Baldwin break; 2640a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_SRC: 2650a473124SJohn Baldwin printf("\tType=%s\n", 2660a473124SJohn Baldwin platform_int_types[mp->body.int_src.type]); 2670a473124SJohn Baldwin printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 2680a473124SJohn Baldwin printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 2690a473124SJohn Baldwin printf("\tSAPIC Vector=%d\n", 2700a473124SJohn Baldwin (u_int)mp->body.int_src.sapic_vector); 2710a473124SJohn Baldwin acpi_print_intr(mp->body.int_src.intr, 2720a473124SJohn Baldwin mp->body.int_src.mps_flags); 2730a473124SJohn Baldwin break; 2740a473124SJohn Baldwin default: 2750a473124SJohn Baldwin printf("\tUnknown type %d\n", (u_int)mp->type); 276945137d9SNate Lawson break; 2770a473124SJohn Baldwin } 2780a473124SJohn Baldwin } 2790a473124SJohn Baldwin 2800a473124SJohn Baldwin static void 2810a473124SJohn Baldwin acpi_handle_apic(struct ACPIsdt *sdp) 2820a473124SJohn Baldwin { 2830a473124SJohn Baldwin struct MADTbody *madtp; 2840a473124SJohn Baldwin struct MADT_APIC *madt_apicp; 2850a473124SJohn Baldwin 286945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/0); 2870a473124SJohn Baldwin madtp = (struct MADTbody *) sdp->body; 2880a473124SJohn Baldwin printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 2890a473124SJohn Baldwin printf("\tFlags={"); 2900a473124SJohn Baldwin if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 2910a473124SJohn Baldwin printf("PC-AT"); 2920a473124SJohn Baldwin printf("}\n"); 2930a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *)madtp->body; 2940a473124SJohn Baldwin while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 2950a473124SJohn Baldwin printf("\n"); 2960a473124SJohn Baldwin acpi_print_apic(madt_apicp); 2970a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 2980a473124SJohn Baldwin madt_apicp->len); 2990a473124SJohn Baldwin } 3000a473124SJohn Baldwin printf(END_COMMENT); 3010a473124SJohn Baldwin } 3020a473124SJohn Baldwin 3030a473124SJohn Baldwin static void 30479d7565cSPeter Wemm acpi_handle_hpet(struct ACPIsdt *sdp) 30579d7565cSPeter Wemm { 30679d7565cSPeter Wemm struct HPETbody *hpetp; 30779d7565cSPeter Wemm 308945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/0); 30979d7565cSPeter Wemm hpetp = (struct HPETbody *) sdp->body; 31079d7565cSPeter Wemm printf("\tHPET Number=%d\n", hpetp->hpet_number); 31179d7565cSPeter Wemm printf("\tADDR=0x%08x\n", hpetp->base_addr); 31279d7565cSPeter Wemm printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 31379d7565cSPeter Wemm printf("\tComparitors=%d\n", hpetp->block_comparitors); 31479d7565cSPeter Wemm printf("\tCounter Size=%d\n", hpetp->block_counter_size); 31579d7565cSPeter Wemm printf("\tLegacy IRQ routing capable={"); 31679d7565cSPeter Wemm if (hpetp->block_legacy_capable) 31779d7565cSPeter Wemm printf("TRUE}\n"); 31879d7565cSPeter Wemm else 31979d7565cSPeter Wemm printf("FALSE}\n"); 32079d7565cSPeter Wemm printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 32155da3c73SPeter Wemm printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 32279d7565cSPeter Wemm printf(END_COMMENT); 32379d7565cSPeter Wemm } 32479d7565cSPeter Wemm 32579d7565cSPeter Wemm static void 326945137d9SNate Lawson acpi_print_sdt(struct ACPIsdt *sdp, int endcomment) 327c62f1cccSMitsuru IWASAKI { 328945137d9SNate Lawson printf(BEGIN_COMMENT " "); 329e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->signature, 4); 330c62f1cccSMitsuru IWASAKI printf(": Length=%d, Revision=%d, Checksum=%d,\n", 331e1e9a4bfSMitsuru IWASAKI sdp->len, sdp->rev, sdp->check); 332e1e9a4bfSMitsuru IWASAKI printf("\tOEMID="); 333e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemid, 6); 334e1e9a4bfSMitsuru IWASAKI printf(", OEM Table ID="); 335e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemtblid, 8); 336e1e9a4bfSMitsuru IWASAKI printf(", OEM Revision=0x%x,\n", sdp->oemrev); 337e1e9a4bfSMitsuru IWASAKI printf("\tCreator ID="); 338e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->creator, 4); 339e1e9a4bfSMitsuru IWASAKI printf(", Creator Revision=0x%x\n", sdp->crerev); 340945137d9SNate Lawson if (endcomment) 341c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 342e1e9a4bfSMitsuru IWASAKI } 343e1e9a4bfSMitsuru IWASAKI 344945137d9SNate Lawson static void 345e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(struct ACPIsdt *rsdp) 346e1e9a4bfSMitsuru IWASAKI { 347e1e9a4bfSMitsuru IWASAKI int i, entries; 348a74172abSNate Lawson u_long addr; 349e1e9a4bfSMitsuru IWASAKI 350945137d9SNate Lawson acpi_print_sdt(rsdp, /*endcomment*/0); 351a74172abSNate Lawson entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 352e1e9a4bfSMitsuru IWASAKI printf("\tEntries={ "); 353e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 354e1e9a4bfSMitsuru IWASAKI if (i > 0) 355e1e9a4bfSMitsuru IWASAKI printf(", "); 356a74172abSNate Lawson switch (addr_size) { 357a74172abSNate Lawson case 4: 358a74172abSNate Lawson addr = le32dec((char*)rsdp->body + i * addr_size); 359a74172abSNate Lawson break; 360a74172abSNate Lawson case 8: 361a74172abSNate Lawson addr = le64dec((char*)rsdp->body + i * addr_size); 362a74172abSNate Lawson break; 363a74172abSNate Lawson default: 364a74172abSNate Lawson addr = 0; 365a74172abSNate Lawson } 366a74172abSNate Lawson assert(addr != 0); 367a74172abSNate Lawson printf("0x%08lx", addr); 368e1e9a4bfSMitsuru IWASAKI } 369e1e9a4bfSMitsuru IWASAKI printf(" }\n"); 370c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 371e1e9a4bfSMitsuru IWASAKI } 372e1e9a4bfSMitsuru IWASAKI 3738e6a8737SNate Lawson static const char *acpi_pm_profiles[] = { 3748e6a8737SNate Lawson "Unspecified", "Desktop", "Mobile", "Workstation", 3758e6a8737SNate Lawson "Enterprise Server", "SOHO Server", "Appliance PC" 3768e6a8737SNate Lawson }; 3778e6a8737SNate Lawson 378945137d9SNate Lawson static void 3798e6a8737SNate Lawson acpi_print_fadt(struct FADTbody *fadt) 380e1e9a4bfSMitsuru IWASAKI { 3818e6a8737SNate Lawson const char *pm; 382e1e9a4bfSMitsuru IWASAKI char sep; 383e1e9a4bfSMitsuru IWASAKI 384c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 3858e6a8737SNate Lawson printf(" FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr, 3868e6a8737SNate Lawson fadt->dsdt_ptr); 3878e6a8737SNate Lawson printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC"); 3888e6a8737SNate Lawson if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 3898e6a8737SNate Lawson pm = "Reserved"; 3908e6a8737SNate Lawson else 3918e6a8737SNate Lawson pm = acpi_pm_profiles[fadt->pm_profile]; 3928e6a8737SNate Lawson printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile); 3938e6a8737SNate Lawson printf("\tSCI_INT=%d\n", fadt->sci_int); 3948e6a8737SNate Lawson printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd); 3958e6a8737SNate Lawson printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable); 3968e6a8737SNate Lawson printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable); 3978e6a8737SNate Lawson printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq); 3988e6a8737SNate Lawson printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt); 3998e6a8737SNate Lawson if (fadt->pm1a_evt_blk != 0) 400e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 4018e6a8737SNate Lawson fadt->pm1a_evt_blk, 4028e6a8737SNate Lawson fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1); 4038e6a8737SNate Lawson if (fadt->pm1b_evt_blk != 0) 404e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 4058e6a8737SNate Lawson fadt->pm1b_evt_blk, 4068e6a8737SNate Lawson fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1); 4078e6a8737SNate Lawson if (fadt->pm1a_cnt_blk != 0) 408e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 4098e6a8737SNate Lawson fadt->pm1a_cnt_blk, 4108e6a8737SNate Lawson fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1); 4118e6a8737SNate Lawson if (fadt->pm1b_cnt_blk != 0) 412e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 4138e6a8737SNate Lawson fadt->pm1b_cnt_blk, 4148e6a8737SNate Lawson fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1); 4158e6a8737SNate Lawson if (fadt->pm2_cnt_blk != 0) 416e1e9a4bfSMitsuru IWASAKI printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 4178e6a8737SNate Lawson fadt->pm2_cnt_blk, 4188e6a8737SNate Lawson fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1); 4198e6a8737SNate Lawson if (fadt->pm_tmr_blk != 0) 420e1e9a4bfSMitsuru IWASAKI printf("\tPM2_TMR_BLK=0x%x-0x%x\n", 4218e6a8737SNate Lawson fadt->pm_tmr_blk, 4228e6a8737SNate Lawson fadt->pm_tmr_blk + fadt->pm_tmr_len - 1); 4238e6a8737SNate Lawson if (fadt->gpe0_blk != 0) 4248e6a8737SNate Lawson printf("\tGPE0_BLK=0x%x-0x%x\n", 4258e6a8737SNate Lawson fadt->gpe0_blk, 4268e6a8737SNate Lawson fadt->gpe0_blk + fadt->gpe0_len - 1); 4278e6a8737SNate Lawson if (fadt->gpe1_blk != 0) 4288e6a8737SNate Lawson printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 4298e6a8737SNate Lawson fadt->gpe1_blk, 4308e6a8737SNate Lawson fadt->gpe1_blk + fadt->gpe1_len - 1, 4318e6a8737SNate Lawson fadt->gpe1_base); 4328e6a8737SNate Lawson if (fadt->cst_cnt != 0) 4338e6a8737SNate Lawson printf("\tCST_CNT=0x%x\n", fadt->cst_cnt); 434e1e9a4bfSMitsuru IWASAKI printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 4358e6a8737SNate Lawson fadt->p_lvl2_lat, fadt->p_lvl3_lat); 436e1e9a4bfSMitsuru IWASAKI printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 4378e6a8737SNate Lawson fadt->flush_size, fadt->flush_stride); 438e1e9a4bfSMitsuru IWASAKI printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 4398e6a8737SNate Lawson fadt->duty_off, fadt->duty_width); 440e1e9a4bfSMitsuru IWASAKI printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 4418e6a8737SNate Lawson fadt->day_alrm, fadt->mon_alrm, fadt->century); 442e1e9a4bfSMitsuru IWASAKI 4438e6a8737SNate Lawson #define PRINTFLAG(var, flag) do { \ 4448e6a8737SNate Lawson if ((var) & FADT_FLAG_## flag) { \ 4458e6a8737SNate Lawson printf("%c%s", sep, #flag); sep = ','; \ 446e1e9a4bfSMitsuru IWASAKI } \ 447e1e9a4bfSMitsuru IWASAKI } while (0) 448e1e9a4bfSMitsuru IWASAKI 4498e6a8737SNate Lawson printf("\tIAPC_BOOT_ARCH="); 4508e6a8737SNate Lawson sep = '{'; 4518e6a8737SNate Lawson PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV); 4528e6a8737SNate Lawson PRINTFLAG(fadt->iapc_boot_arch, 8042); 4538e6a8737SNate Lawson printf("}\n"); 4548e6a8737SNate Lawson 4558e6a8737SNate Lawson printf("\tFlags="); 4568e6a8737SNate Lawson sep = '{'; 4578e6a8737SNate Lawson PRINTFLAG(fadt->flags, WBINVD); 4588e6a8737SNate Lawson PRINTFLAG(fadt->flags, WBINVD_FLUSH); 4598e6a8737SNate Lawson PRINTFLAG(fadt->flags, PROC_C1); 4608e6a8737SNate Lawson PRINTFLAG(fadt->flags, P_LVL2_UP); 4618e6a8737SNate Lawson PRINTFLAG(fadt->flags, PWR_BUTTON); 4628e6a8737SNate Lawson PRINTFLAG(fadt->flags, SLP_BUTTON); 4638e6a8737SNate Lawson PRINTFLAG(fadt->flags, FIX_RTC); 4648e6a8737SNate Lawson PRINTFLAG(fadt->flags, RTC_S4); 4658e6a8737SNate Lawson PRINTFLAG(fadt->flags, TMR_VAL_EXT); 4668e6a8737SNate Lawson PRINTFLAG(fadt->flags, DCK_CAP); 4678e6a8737SNate Lawson PRINTFLAG(fadt->flags, RESET_REG); 4688e6a8737SNate Lawson PRINTFLAG(fadt->flags, SEALED_CASE); 4698e6a8737SNate Lawson PRINTFLAG(fadt->flags, HEADLESS); 4708e6a8737SNate Lawson PRINTFLAG(fadt->flags, CPU_SW_SLP); 4718e6a8737SNate Lawson printf("}\n"); 472e1e9a4bfSMitsuru IWASAKI 473e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG 474e1e9a4bfSMitsuru IWASAKI 4758e6a8737SNate Lawson if (fadt->flags & FADT_FLAG_RESET_REG) { 4768e6a8737SNate Lawson printf("\tRESET_REG="); 4778e6a8737SNate Lawson acpi_print_gas(&fadt->reset_reg); 4788e6a8737SNate Lawson printf(", RESET_VALUE=%#x\n", fadt->reset_value); 4798e6a8737SNate Lawson } 4808e6a8737SNate Lawson 4818e6a8737SNate Lawson printf(END_COMMENT); 4828e6a8737SNate Lawson } 4838e6a8737SNate Lawson 4848e6a8737SNate Lawson static void 4858e6a8737SNate Lawson acpi_print_facs(struct FACSbody *facs) 4868e6a8737SNate Lawson { 4878e6a8737SNate Lawson printf(BEGIN_COMMENT); 4888e6a8737SNate Lawson printf(" FACS:\tLength=%u, ", facs->len); 4898e6a8737SNate Lawson printf("HwSig=0x%08x, ", facs->hw_sig); 4908e6a8737SNate Lawson printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec); 4918e6a8737SNate Lawson 4928e6a8737SNate Lawson printf("\tGlobal_Lock={"); 4938e6a8737SNate Lawson if (facs->global_lock != 0) { 4948e6a8737SNate Lawson if (facs->global_lock & FACS_FLAG_LOCK_PENDING) 4958e6a8737SNate Lawson printf("PENDING,"); 4968e6a8737SNate Lawson if (facs->global_lock & FACS_FLAG_LOCK_OWNED) 4978e6a8737SNate Lawson printf("OWNED"); 4988e6a8737SNate Lawson } 499e1e9a4bfSMitsuru IWASAKI printf("}\n"); 5008e6a8737SNate Lawson 5018e6a8737SNate Lawson printf("\tFlags={"); 5028e6a8737SNate Lawson if (facs->flags & FACS_FLAG_S4BIOS_F) 5038e6a8737SNate Lawson printf("S4BIOS"); 5048e6a8737SNate Lawson printf("}\n"); 5058e6a8737SNate Lawson 5068e6a8737SNate Lawson if (facs->x_firm_wake_vec != 0) { 5078e6a8737SNate Lawson printf("\tX_Firm_Wake_Vec=%08lx\n", 5088e6a8737SNate Lawson (u_long)facs->x_firm_wake_vec); 5098e6a8737SNate Lawson } 5108e6a8737SNate Lawson 511c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 512e1e9a4bfSMitsuru IWASAKI } 513e1e9a4bfSMitsuru IWASAKI 514945137d9SNate Lawson static void 515e1e9a4bfSMitsuru IWASAKI acpi_print_dsdt(struct ACPIsdt *dsdp) 516e1e9a4bfSMitsuru IWASAKI { 517945137d9SNate Lawson acpi_print_sdt(dsdp, /*endcomment*/1); 518e1e9a4bfSMitsuru IWASAKI } 519e1e9a4bfSMitsuru IWASAKI 520e1e9a4bfSMitsuru IWASAKI int 521e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length) 522e1e9a4bfSMitsuru IWASAKI { 523e1e9a4bfSMitsuru IWASAKI u_int8_t *bp; 524e1e9a4bfSMitsuru IWASAKI u_int8_t sum; 525e1e9a4bfSMitsuru IWASAKI 526e1e9a4bfSMitsuru IWASAKI bp = p; 527e1e9a4bfSMitsuru IWASAKI sum = 0; 528e1e9a4bfSMitsuru IWASAKI while (length--) 529e1e9a4bfSMitsuru IWASAKI sum += *bp++; 530e1e9a4bfSMitsuru IWASAKI 531e1e9a4bfSMitsuru IWASAKI return (sum); 532e1e9a4bfSMitsuru IWASAKI } 533e1e9a4bfSMitsuru IWASAKI 534945137d9SNate Lawson static struct ACPIsdt * 535e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa) 536e1e9a4bfSMitsuru IWASAKI { 537e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sp; 538e1e9a4bfSMitsuru IWASAKI 539e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 540e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sp->len); 541e1e9a4bfSMitsuru IWASAKI return (sp); 542e1e9a4bfSMitsuru IWASAKI } 543e1e9a4bfSMitsuru IWASAKI 544945137d9SNate Lawson static void 545e1e9a4bfSMitsuru IWASAKI acpi_print_rsd_ptr(struct ACPIrsdp *rp) 546e1e9a4bfSMitsuru IWASAKI { 547c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 548a74172abSNate Lawson printf(" RSD PTR: OEM="); 549e1e9a4bfSMitsuru IWASAKI acpi_print_string(rp->oem, 6); 550a74172abSNate Lawson printf(", ACPI_Rev=%s (%d)\n", rp->revision < 2 ? "1.x" : "2.x", 551a74172abSNate Lawson rp->revision); 552a74172abSNate Lawson if (rp->revision < 2) { 553a74172abSNate Lawson printf("\tRSDT=0x%08x, cksum=%u\n", rp->rsdt_addr, rp->sum); 554a74172abSNate Lawson } else { 555a74172abSNate Lawson printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n", 556a74172abSNate Lawson (u_long)rp->xsdt_addr, rp->length, rp->xsum); 557a74172abSNate Lawson } 558c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 559e1e9a4bfSMitsuru IWASAKI } 560e1e9a4bfSMitsuru IWASAKI 561945137d9SNate Lawson static void 562e1e9a4bfSMitsuru IWASAKI acpi_handle_rsdt(struct ACPIsdt *rsdp) 563e1e9a4bfSMitsuru IWASAKI { 564e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sdp; 565a74172abSNate Lawson vm_offset_t addr; 566a74172abSNate Lawson int entries, i; 567e1e9a4bfSMitsuru IWASAKI 568e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(rsdp); 569a74172abSNate Lawson entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 570e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 571a74172abSNate Lawson switch (addr_size) { 572a74172abSNate Lawson case 4: 573a74172abSNate Lawson addr = le32dec((char*)rsdp->body + i * addr_size); 574a74172abSNate Lawson break; 575a74172abSNate Lawson case 8: 576a74172abSNate Lawson addr = le64dec((char*)rsdp->body + i * addr_size); 577a74172abSNate Lawson break; 578a74172abSNate Lawson default: 579a74172abSNate Lawson assert((addr = 0)); 580a74172abSNate Lawson } 581a74172abSNate Lawson 582a74172abSNate Lawson sdp = (struct ACPIsdt *)acpi_map_sdt(addr); 583e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(sdp, sdp->len)) 584945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 585945137d9SNate Lawson if (!memcmp(sdp->signature, "FACP", 4)) 5868e6a8737SNate Lawson acpi_handle_fadt((struct FADTbody *) sdp->body); 587945137d9SNate Lawson else if (!memcmp(sdp->signature, "APIC", 4)) 5880a473124SJohn Baldwin acpi_handle_apic(sdp); 589945137d9SNate Lawson else if (!memcmp(sdp->signature, "HPET", 4)) 59079d7565cSPeter Wemm acpi_handle_hpet(sdp); 591945137d9SNate Lawson else 592945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/1); 593e1e9a4bfSMitsuru IWASAKI } 594e1e9a4bfSMitsuru IWASAKI } 595c62f1cccSMitsuru IWASAKI 596945137d9SNate Lawson struct ACPIsdt * 597945137d9SNate Lawson sdt_load_devmem() 598945137d9SNate Lawson { 599945137d9SNate Lawson struct ACPIrsdp *rp; 600945137d9SNate Lawson struct ACPIsdt *rsdp; 601945137d9SNate Lawson 602945137d9SNate Lawson rp = acpi_find_rsd_ptr(); 603945137d9SNate Lawson if (!rp) 604945137d9SNate Lawson errx(1, "Can't find ACPI information"); 605945137d9SNate Lawson 606945137d9SNate Lawson if (tflag) 607945137d9SNate Lawson acpi_print_rsd_ptr(rp); 608a74172abSNate Lawson if (rp->revision < 2) { 609945137d9SNate Lawson rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 610945137d9SNate Lawson if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 611945137d9SNate Lawson acpi_checksum(rsdp, rsdp->len) != 0) 612945137d9SNate Lawson errx(1, "RSDT is corrupted"); 613a74172abSNate Lawson addr_size = sizeof(uint32_t); 614a74172abSNate Lawson } else { 615a74172abSNate Lawson rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr); 616a74172abSNate Lawson if (memcmp(rsdp->signature, "XSDT", 4) != 0 || 617a74172abSNate Lawson acpi_checksum(rsdp, rsdp->len) != 0) 618a74172abSNate Lawson errx(1, "XSDT is corrupted"); 619a74172abSNate Lawson addr_size = sizeof(uint64_t); 620a74172abSNate Lawson } 621945137d9SNate Lawson return (rsdp); 622945137d9SNate Lawson } 623c62f1cccSMitsuru IWASAKI 624c62f1cccSMitsuru IWASAKI void 625945137d9SNate Lawson dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 626c62f1cccSMitsuru IWASAKI { 627945137d9SNate Lawson int fd; 628945137d9SNate Lawson mode_t mode; 629945137d9SNate Lawson 630945137d9SNate Lawson assert(outfile != NULL); 631945137d9SNate Lawson mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 632945137d9SNate Lawson fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 633945137d9SNate Lawson if (fd == -1) { 634945137d9SNate Lawson perror("dsdt_save_file"); 635945137d9SNate Lawson return; 636945137d9SNate Lawson } 637945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 638945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 639945137d9SNate Lawson close(fd); 640c62f1cccSMitsuru IWASAKI } 641c62f1cccSMitsuru IWASAKI 642945137d9SNate Lawson void 643945137d9SNate Lawson aml_disassemble(struct ACPIsdt *dsdp) 644c62f1cccSMitsuru IWASAKI { 645945137d9SNate Lawson char tmpstr[32], buf[256]; 646945137d9SNate Lawson FILE *fp; 647945137d9SNate Lawson int fd, len; 648945137d9SNate Lawson 649945137d9SNate Lawson strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 650945137d9SNate Lawson fd = mkstemp(tmpstr); 651945137d9SNate Lawson if (fd < 0) { 652945137d9SNate Lawson perror("iasl tmp file"); 653945137d9SNate Lawson return; 654c62f1cccSMitsuru IWASAKI } 655c62f1cccSMitsuru IWASAKI 656945137d9SNate Lawson /* Dump DSDT to the temp file */ 657945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 658945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 659945137d9SNate Lawson close(fd); 660945137d9SNate Lawson 661945137d9SNate Lawson /* Run iasl -d on the temp file */ 662945137d9SNate Lawson if (fork() == 0) { 663945137d9SNate Lawson close(STDOUT_FILENO); 664945137d9SNate Lawson if (vflag == 0) 665945137d9SNate Lawson close(STDERR_FILENO); 666945137d9SNate Lawson execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 667945137d9SNate Lawson err(1, "exec"); 668c62f1cccSMitsuru IWASAKI } 669c62f1cccSMitsuru IWASAKI 670945137d9SNate Lawson wait(NULL); 671945137d9SNate Lawson unlink(tmpstr); 672945137d9SNate Lawson 673945137d9SNate Lawson /* Dump iasl's output to stdout */ 674945137d9SNate Lawson fp = fopen("acpidump.dsl", "r"); 675945137d9SNate Lawson unlink("acpidump.dsl"); 676945137d9SNate Lawson if (fp == NULL) { 677945137d9SNate Lawson perror("iasl tmp file (read)"); 678945137d9SNate Lawson return; 679945137d9SNate Lawson } 680945137d9SNate Lawson while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 681945137d9SNate Lawson fwrite(buf, 1, len, stdout); 682945137d9SNate Lawson fclose(fp); 683c62f1cccSMitsuru IWASAKI } 684c62f1cccSMitsuru IWASAKI 685945137d9SNate Lawson void 686945137d9SNate Lawson sdt_print_all(struct ACPIsdt *rsdp) 687c62f1cccSMitsuru IWASAKI { 688945137d9SNate Lawson acpi_handle_rsdt(rsdp); 689c62f1cccSMitsuru IWASAKI } 690c62f1cccSMitsuru IWASAKI 691945137d9SNate Lawson /* Fetch a table matching the given signature via the RSDT */ 692945137d9SNate Lawson struct ACPIsdt * 693945137d9SNate Lawson sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 694c62f1cccSMitsuru IWASAKI { 695945137d9SNate Lawson struct ACPIsdt *sdt; 696a74172abSNate Lawson vm_offset_t addr; 697a74172abSNate Lawson int entries, i; 698945137d9SNate Lawson 699a74172abSNate Lawson entries = (rsdt->len - SIZEOF_SDT_HDR) / addr_size; 700945137d9SNate Lawson for (i = 0; i < entries; i++) { 701a74172abSNate Lawson switch (addr_size) { 702a74172abSNate Lawson case 4: 703a74172abSNate Lawson addr = le32dec((char*)rsdt->body + i * addr_size); 704a74172abSNate Lawson break; 705a74172abSNate Lawson case 8: 706a74172abSNate Lawson addr = le64dec((char*)rsdt->body + i * addr_size); 707a74172abSNate Lawson break; 708a74172abSNate Lawson default: 709a74172abSNate Lawson assert((addr = 0)); 710a74172abSNate Lawson } 711a74172abSNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(addr); 712a74172abSNate Lawson if (memcmp(sdt->signature, sig, strlen(sig))) 713a74172abSNate Lawson continue; 714945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 715945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 716945137d9SNate Lawson return (sdt); 717c62f1cccSMitsuru IWASAKI } 718c62f1cccSMitsuru IWASAKI 719945137d9SNate Lawson return (NULL); 720c62f1cccSMitsuru IWASAKI } 721c62f1cccSMitsuru IWASAKI 722945137d9SNate Lawson struct ACPIsdt * 7238e6a8737SNate Lawson dsdt_from_fadt(struct FADTbody *fadt) 724c62f1cccSMitsuru IWASAKI { 725945137d9SNate Lawson struct ACPIsdt *sdt; 726c62f1cccSMitsuru IWASAKI 7278e6a8737SNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 728945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 729945137d9SNate Lawson errx(1, "DSDT is corrupt\n"); 730945137d9SNate Lawson return (sdt); 731c62f1cccSMitsuru IWASAKI } 732