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 30945137d9SNate Lawson #include <sys/types.h> 31e1e9a4bfSMitsuru IWASAKI #include <sys/param.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); 47945137d9SNate Lawson static void acpi_handle_facp(struct FACPbody *facp); 48945137d9SNate Lawson static void acpi_print_cpu(u_char cpu_id); 49945137d9SNate Lawson static void acpi_print_local_apic(u_char cpu_id, u_char apic_id, 50945137d9SNate Lawson u_int32_t flags); 51945137d9SNate Lawson static void acpi_print_io_apic(u_char apic_id, u_int32_t int_base, 52945137d9SNate Lawson u_int64_t apic_addr); 53945137d9SNate Lawson static void acpi_print_mps_flags(u_int16_t flags); 54945137d9SNate Lawson static void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags); 55945137d9SNate Lawson static void acpi_print_apic(struct MADT_APIC *mp); 56945137d9SNate Lawson static void acpi_handle_apic(struct ACPIsdt *sdp); 57945137d9SNate Lawson static void acpi_handle_hpet(struct ACPIsdt *sdp); 58945137d9SNate Lawson static void acpi_print_sdt(struct ACPIsdt *sdp, int endcomment); 59945137d9SNate Lawson static void acpi_print_facp(struct FACPbody *facp); 60945137d9SNate Lawson static void acpi_print_dsdt(struct ACPIsdt *dsdp); 61945137d9SNate Lawson static struct ACPIsdt * 62945137d9SNate Lawson acpi_map_sdt(vm_offset_t pa); 63945137d9SNate Lawson static void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 64945137d9SNate Lawson static void acpi_handle_rsdt(struct ACPIsdt *rsdp); 65c62f1cccSMitsuru IWASAKI 66e1e9a4bfSMitsuru IWASAKI static void 67e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length) 68e1e9a4bfSMitsuru IWASAKI { 69e1e9a4bfSMitsuru IWASAKI int c; 70e1e9a4bfSMitsuru IWASAKI 71e1e9a4bfSMitsuru IWASAKI /* Trim trailing spaces and NULLs */ 72e1e9a4bfSMitsuru IWASAKI while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 73e1e9a4bfSMitsuru IWASAKI length--; 74e1e9a4bfSMitsuru IWASAKI 75e1e9a4bfSMitsuru IWASAKI while (length--) { 76e1e9a4bfSMitsuru IWASAKI c = *s++; 77e1e9a4bfSMitsuru IWASAKI putchar(c); 78e1e9a4bfSMitsuru IWASAKI } 79e1e9a4bfSMitsuru IWASAKI } 80e1e9a4bfSMitsuru IWASAKI 81e1e9a4bfSMitsuru IWASAKI static void 82e1e9a4bfSMitsuru IWASAKI acpi_handle_facp(struct FACPbody *facp) 83e1e9a4bfSMitsuru IWASAKI { 84e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *dsdp; 85e1e9a4bfSMitsuru IWASAKI 86e1e9a4bfSMitsuru IWASAKI acpi_print_facp(facp); 87e1e9a4bfSMitsuru IWASAKI dsdp = (struct ACPIsdt *)acpi_map_sdt(facp->dsdt_ptr); 88e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(dsdp, dsdp->len)) 89945137d9SNate Lawson errx(1, "DSDT is corrupt"); 90945137d9SNate Lawson acpi_print_dsdt(dsdp); 91c62f1cccSMitsuru IWASAKI } 92c62f1cccSMitsuru IWASAKI 93c62f1cccSMitsuru IWASAKI static void 940a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id) 950a473124SJohn Baldwin { 960a473124SJohn Baldwin 970a473124SJohn Baldwin printf("\tACPI CPU="); 980a473124SJohn Baldwin if (cpu_id == 0xff) 990a473124SJohn Baldwin printf("ALL\n"); 1000a473124SJohn Baldwin else 1010a473124SJohn Baldwin printf("%d\n", (u_int)cpu_id); 1020a473124SJohn Baldwin } 1030a473124SJohn Baldwin 1040a473124SJohn Baldwin static void 1050a473124SJohn Baldwin acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 1060a473124SJohn Baldwin { 1070a473124SJohn Baldwin acpi_print_cpu(cpu_id); 1080a473124SJohn Baldwin printf("\tFlags={"); 1090a473124SJohn Baldwin if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 1100a473124SJohn Baldwin printf("ENABLED"); 1110a473124SJohn Baldwin else 1120a473124SJohn Baldwin printf("DISABLED"); 1130a473124SJohn Baldwin printf("}\n"); 1140a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1150a473124SJohn Baldwin } 1160a473124SJohn Baldwin 1170a473124SJohn Baldwin static void 1180a473124SJohn Baldwin acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 1190a473124SJohn Baldwin { 1200a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1210a473124SJohn Baldwin printf("\tINT BASE=%d\n", int_base); 122945137d9SNate Lawson printf("\tADDR=0x%016jx\n", apic_addr); 1230a473124SJohn Baldwin } 1240a473124SJohn Baldwin 1250a473124SJohn Baldwin static void 1260a473124SJohn Baldwin acpi_print_mps_flags(u_int16_t flags) 1270a473124SJohn Baldwin { 1280a473124SJohn Baldwin 1290a473124SJohn Baldwin printf("\tFlags={Polarity="); 1300a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 1310a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_CONFORM: 1320a473124SJohn Baldwin printf("conforming"); 1330a473124SJohn Baldwin break; 1340a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_HIGH: 1350a473124SJohn Baldwin printf("active-hi"); 1360a473124SJohn Baldwin break; 1370a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_LOW: 1380a473124SJohn Baldwin printf("active-lo"); 1390a473124SJohn Baldwin break; 1400a473124SJohn Baldwin default: 1410a473124SJohn Baldwin printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 1420a473124SJohn Baldwin break; 1430a473124SJohn Baldwin } 1440a473124SJohn Baldwin printf(", Trigger="); 1450a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 1460a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_CONFORM: 1470a473124SJohn Baldwin printf("conforming"); 1480a473124SJohn Baldwin break; 1490a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_EDGE: 1500a473124SJohn Baldwin printf("edge"); 1510a473124SJohn Baldwin break; 1520a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_LEVEL: 1530a473124SJohn Baldwin printf("level"); 1540a473124SJohn Baldwin break; 1550a473124SJohn Baldwin default: 1560a473124SJohn Baldwin printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 1570a473124SJohn Baldwin } 1580a473124SJohn Baldwin printf("}\n"); 1590a473124SJohn Baldwin } 1600a473124SJohn Baldwin 1610a473124SJohn Baldwin static void 1620a473124SJohn Baldwin acpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 1630a473124SJohn Baldwin { 1640a473124SJohn Baldwin 1650a473124SJohn Baldwin printf("\tINTR=%d\n", (u_int)intr); 1660a473124SJohn Baldwin acpi_print_mps_flags(mps_flags); 1670a473124SJohn Baldwin } 1680a473124SJohn Baldwin 1690a473124SJohn Baldwin const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 1700a473124SJohn Baldwin "Local NMI", "Local APIC Override", "IO SAPIC", 1710a473124SJohn Baldwin "Local SAPIC", "Platform Interrupt" }; 1720a473124SJohn Baldwin const char *platform_int_types[] = { "PMI", "INIT", 1730a473124SJohn Baldwin "Corrected Platform Error" }; 1740a473124SJohn Baldwin 1750a473124SJohn Baldwin static void 1760a473124SJohn Baldwin acpi_print_apic(struct MADT_APIC *mp) 1770a473124SJohn Baldwin { 1780a473124SJohn Baldwin 1790a473124SJohn Baldwin printf("\tType=%s\n", apic_types[mp->type]); 1800a473124SJohn Baldwin switch (mp->type) { 1810a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 1820a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_apic.cpu_id, 1830a473124SJohn Baldwin mp->body.local_apic.apic_id, mp->body.local_apic.flags); 1840a473124SJohn Baldwin break; 1850a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_APIC: 1860a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_apic.apic_id, 1870a473124SJohn Baldwin mp->body.io_apic.int_base, 1880a473124SJohn Baldwin mp->body.io_apic.apic_addr); 1890a473124SJohn Baldwin break; 1900a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 1910a473124SJohn Baldwin printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 1920a473124SJohn Baldwin printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 1930a473124SJohn Baldwin acpi_print_intr(mp->body.int_override.intr, 1940a473124SJohn Baldwin mp->body.int_override.mps_flags); 1950a473124SJohn Baldwin break; 1960a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_NMI: 1970a473124SJohn Baldwin acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 1980a473124SJohn Baldwin break; 1990a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 2000a473124SJohn Baldwin acpi_print_cpu(mp->body.local_nmi.cpu_id); 2010a473124SJohn Baldwin printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 2020a473124SJohn Baldwin acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 2030a473124SJohn Baldwin break; 2040a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 205945137d9SNate Lawson printf("\tLocal APIC ADDR=0x%016jx\n", 206945137d9SNate Lawson mp->body.local_apic_override.apic_addr); 2070a473124SJohn Baldwin break; 2080a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_SAPIC: 2090a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_sapic.apic_id, 2100a473124SJohn Baldwin mp->body.io_sapic.int_base, 2110a473124SJohn Baldwin mp->body.io_sapic.apic_addr); 2120a473124SJohn Baldwin break; 2130a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 2140a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_sapic.cpu_id, 2150a473124SJohn Baldwin mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 2160a473124SJohn Baldwin printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 2170a473124SJohn Baldwin break; 2180a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_SRC: 2190a473124SJohn Baldwin printf("\tType=%s\n", 2200a473124SJohn Baldwin platform_int_types[mp->body.int_src.type]); 2210a473124SJohn Baldwin printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 2220a473124SJohn Baldwin printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 2230a473124SJohn Baldwin printf("\tSAPIC Vector=%d\n", 2240a473124SJohn Baldwin (u_int)mp->body.int_src.sapic_vector); 2250a473124SJohn Baldwin acpi_print_intr(mp->body.int_src.intr, 2260a473124SJohn Baldwin mp->body.int_src.mps_flags); 2270a473124SJohn Baldwin break; 2280a473124SJohn Baldwin default: 2290a473124SJohn Baldwin printf("\tUnknown type %d\n", (u_int)mp->type); 230945137d9SNate Lawson break; 2310a473124SJohn Baldwin } 2320a473124SJohn Baldwin } 2330a473124SJohn Baldwin 2340a473124SJohn Baldwin static void 2350a473124SJohn Baldwin acpi_handle_apic(struct ACPIsdt *sdp) 2360a473124SJohn Baldwin { 2370a473124SJohn Baldwin struct MADTbody *madtp; 2380a473124SJohn Baldwin struct MADT_APIC *madt_apicp; 2390a473124SJohn Baldwin 240945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/0); 2410a473124SJohn Baldwin madtp = (struct MADTbody *) sdp->body; 2420a473124SJohn Baldwin printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 2430a473124SJohn Baldwin printf("\tFlags={"); 2440a473124SJohn Baldwin if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 2450a473124SJohn Baldwin printf("PC-AT"); 2460a473124SJohn Baldwin printf("}\n"); 2470a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *)madtp->body; 2480a473124SJohn Baldwin while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 2490a473124SJohn Baldwin printf("\n"); 2500a473124SJohn Baldwin acpi_print_apic(madt_apicp); 2510a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 2520a473124SJohn Baldwin madt_apicp->len); 2530a473124SJohn Baldwin } 2540a473124SJohn Baldwin printf(END_COMMENT); 2550a473124SJohn Baldwin } 2560a473124SJohn Baldwin 2570a473124SJohn Baldwin static void 25879d7565cSPeter Wemm acpi_handle_hpet(struct ACPIsdt *sdp) 25979d7565cSPeter Wemm { 26079d7565cSPeter Wemm struct HPETbody *hpetp; 26179d7565cSPeter Wemm 262945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/0); 26379d7565cSPeter Wemm hpetp = (struct HPETbody *) sdp->body; 26479d7565cSPeter Wemm printf("\tHPET Number=%d\n", hpetp->hpet_number); 26579d7565cSPeter Wemm printf("\tADDR=0x%08x\n", hpetp->base_addr); 26679d7565cSPeter Wemm printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 26779d7565cSPeter Wemm printf("\tComparitors=%d\n", hpetp->block_comparitors); 26879d7565cSPeter Wemm printf("\tCounter Size=%d\n", hpetp->block_counter_size); 26979d7565cSPeter Wemm printf("\tLegacy IRQ routing capable={"); 27079d7565cSPeter Wemm if (hpetp->block_legacy_capable) 27179d7565cSPeter Wemm printf("TRUE}\n"); 27279d7565cSPeter Wemm else 27379d7565cSPeter Wemm printf("FALSE}\n"); 27479d7565cSPeter Wemm printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 27555da3c73SPeter Wemm printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 27679d7565cSPeter Wemm printf(END_COMMENT); 27779d7565cSPeter Wemm } 27879d7565cSPeter Wemm 27979d7565cSPeter Wemm static void 280945137d9SNate Lawson acpi_print_sdt(struct ACPIsdt *sdp, int endcomment) 281c62f1cccSMitsuru IWASAKI { 282945137d9SNate Lawson printf(BEGIN_COMMENT " "); 283e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->signature, 4); 284c62f1cccSMitsuru IWASAKI printf(": Length=%d, Revision=%d, Checksum=%d,\n", 285e1e9a4bfSMitsuru IWASAKI sdp->len, sdp->rev, sdp->check); 286e1e9a4bfSMitsuru IWASAKI printf("\tOEMID="); 287e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemid, 6); 288e1e9a4bfSMitsuru IWASAKI printf(", OEM Table ID="); 289e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemtblid, 8); 290e1e9a4bfSMitsuru IWASAKI printf(", OEM Revision=0x%x,\n", sdp->oemrev); 291e1e9a4bfSMitsuru IWASAKI printf("\tCreator ID="); 292e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->creator, 4); 293e1e9a4bfSMitsuru IWASAKI printf(", Creator Revision=0x%x\n", sdp->crerev); 294945137d9SNate Lawson if (endcomment) 295c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 296e1e9a4bfSMitsuru IWASAKI } 297e1e9a4bfSMitsuru IWASAKI 298945137d9SNate Lawson static void 299e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(struct ACPIsdt *rsdp) 300e1e9a4bfSMitsuru IWASAKI { 301e1e9a4bfSMitsuru IWASAKI int i, entries; 302e1e9a4bfSMitsuru IWASAKI 303945137d9SNate Lawson acpi_print_sdt(rsdp, /*endcomment*/0); 304e1e9a4bfSMitsuru IWASAKI entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 305e1e9a4bfSMitsuru IWASAKI printf("\tEntries={ "); 306e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 307e1e9a4bfSMitsuru IWASAKI if (i > 0) 308e1e9a4bfSMitsuru IWASAKI printf(", "); 309e1e9a4bfSMitsuru IWASAKI printf("0x%08x", rsdp->body[i]); 310e1e9a4bfSMitsuru IWASAKI } 311e1e9a4bfSMitsuru IWASAKI printf(" }\n"); 312c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 313e1e9a4bfSMitsuru IWASAKI } 314e1e9a4bfSMitsuru IWASAKI 315945137d9SNate Lawson static void 316e1e9a4bfSMitsuru IWASAKI acpi_print_facp(struct FACPbody *facp) 317e1e9a4bfSMitsuru IWASAKI { 318e1e9a4bfSMitsuru IWASAKI char sep; 319e1e9a4bfSMitsuru IWASAKI 320c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 321945137d9SNate Lawson printf(" FACP:\tDSDT=0x%x\n", facp->dsdt_ptr); 322e1e9a4bfSMitsuru IWASAKI printf("\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC"); 323e1e9a4bfSMitsuru IWASAKI printf("\tSCI_INT=%d\n", facp->sci_int); 324e1e9a4bfSMitsuru IWASAKI printf("\tSMI_CMD=0x%x, ", facp->smi_cmd); 325e1e9a4bfSMitsuru IWASAKI printf("ACPI_ENABLE=0x%x, ", facp->acpi_enable); 326e1e9a4bfSMitsuru IWASAKI printf("ACPI_DISABLE=0x%x, ", facp->acpi_disable); 327e1e9a4bfSMitsuru IWASAKI printf("S4BIOS_REQ=0x%x\n", facp->s4biosreq); 328e1e9a4bfSMitsuru IWASAKI if (facp->pm1a_evt_blk) 329e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 330e1e9a4bfSMitsuru IWASAKI facp->pm1a_evt_blk, 331e1e9a4bfSMitsuru IWASAKI facp->pm1a_evt_blk + facp->pm1_evt_len - 1); 332e1e9a4bfSMitsuru IWASAKI if (facp->pm1b_evt_blk) 333e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 334e1e9a4bfSMitsuru IWASAKI facp->pm1b_evt_blk, 335e1e9a4bfSMitsuru IWASAKI facp->pm1b_evt_blk + facp->pm1_evt_len - 1); 336e1e9a4bfSMitsuru IWASAKI if (facp->pm1a_cnt_blk) 337e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 338e1e9a4bfSMitsuru IWASAKI facp->pm1a_cnt_blk, 339e1e9a4bfSMitsuru IWASAKI facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1); 340e1e9a4bfSMitsuru IWASAKI if (facp->pm1b_cnt_blk) 341e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 342e1e9a4bfSMitsuru IWASAKI facp->pm1b_cnt_blk, 343e1e9a4bfSMitsuru IWASAKI facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1); 344e1e9a4bfSMitsuru IWASAKI if (facp->pm2_cnt_blk) 345e1e9a4bfSMitsuru IWASAKI printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 346e1e9a4bfSMitsuru IWASAKI facp->pm2_cnt_blk, 347e1e9a4bfSMitsuru IWASAKI facp->pm2_cnt_blk + facp->pm2_cnt_len - 1); 348e1e9a4bfSMitsuru IWASAKI if (facp->pm_tmr_blk) 349e1e9a4bfSMitsuru IWASAKI printf("\tPM2_TMR_BLK=0x%x-0x%x\n", 350e1e9a4bfSMitsuru IWASAKI facp->pm_tmr_blk, 351e1e9a4bfSMitsuru IWASAKI facp->pm_tmr_blk + facp->pm_tmr_len - 1); 352e1e9a4bfSMitsuru IWASAKI if (facp->gpe0_blk) 353e1e9a4bfSMitsuru IWASAKI printf("\tPM2_GPE0_BLK=0x%x-0x%x\n", 354e1e9a4bfSMitsuru IWASAKI facp->gpe0_blk, 355e1e9a4bfSMitsuru IWASAKI facp->gpe0_blk + facp->gpe0_len - 1); 356e1e9a4bfSMitsuru IWASAKI if (facp->gpe1_blk) 357e1e9a4bfSMitsuru IWASAKI printf("\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 358e1e9a4bfSMitsuru IWASAKI facp->gpe1_blk, 359e1e9a4bfSMitsuru IWASAKI facp->gpe1_blk + facp->gpe1_len - 1, 360e1e9a4bfSMitsuru IWASAKI facp->gpe1_base); 361e1e9a4bfSMitsuru IWASAKI printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 362e1e9a4bfSMitsuru IWASAKI facp->p_lvl2_lat, facp->p_lvl3_lat); 363e1e9a4bfSMitsuru IWASAKI printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 364e1e9a4bfSMitsuru IWASAKI facp->flush_size, facp->flush_stride); 365e1e9a4bfSMitsuru IWASAKI printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 366e1e9a4bfSMitsuru IWASAKI facp->duty_off, facp->duty_width); 367e1e9a4bfSMitsuru IWASAKI printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 368e1e9a4bfSMitsuru IWASAKI facp->day_alrm, facp->mon_alrm, facp->century); 369e1e9a4bfSMitsuru IWASAKI printf("\tFlags="); 370e1e9a4bfSMitsuru IWASAKI sep = '{'; 371e1e9a4bfSMitsuru IWASAKI 372e1e9a4bfSMitsuru IWASAKI #define PRINTFLAG(xx) do { \ 373e1e9a4bfSMitsuru IWASAKI if (facp->flags & ACPI_FACP_FLAG_## xx) { \ 374e1e9a4bfSMitsuru IWASAKI printf("%c%s", sep, #xx); sep = ','; \ 375e1e9a4bfSMitsuru IWASAKI } \ 376e1e9a4bfSMitsuru IWASAKI } while (0) 377e1e9a4bfSMitsuru IWASAKI 378e1e9a4bfSMitsuru IWASAKI PRINTFLAG(WBINVD); 379e1e9a4bfSMitsuru IWASAKI PRINTFLAG(WBINVD_FLUSH); 380e1e9a4bfSMitsuru IWASAKI PRINTFLAG(PROC_C1); 381e1e9a4bfSMitsuru IWASAKI PRINTFLAG(P_LVL2_UP); 382e1e9a4bfSMitsuru IWASAKI PRINTFLAG(PWR_BUTTON); 383e1e9a4bfSMitsuru IWASAKI PRINTFLAG(SLP_BUTTON); 384e1e9a4bfSMitsuru IWASAKI PRINTFLAG(FIX_RTC); 385e1e9a4bfSMitsuru IWASAKI PRINTFLAG(RTC_S4); 386e1e9a4bfSMitsuru IWASAKI PRINTFLAG(TMR_VAL_EXT); 387e1e9a4bfSMitsuru IWASAKI PRINTFLAG(DCK_CAP); 388e1e9a4bfSMitsuru IWASAKI 389e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG 390e1e9a4bfSMitsuru IWASAKI 391e1e9a4bfSMitsuru IWASAKI printf("}\n"); 392c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 393e1e9a4bfSMitsuru IWASAKI } 394e1e9a4bfSMitsuru IWASAKI 395945137d9SNate Lawson static void 396e1e9a4bfSMitsuru IWASAKI acpi_print_dsdt(struct ACPIsdt *dsdp) 397e1e9a4bfSMitsuru IWASAKI { 398945137d9SNate Lawson acpi_print_sdt(dsdp, /*endcomment*/1); 399e1e9a4bfSMitsuru IWASAKI } 400e1e9a4bfSMitsuru IWASAKI 401e1e9a4bfSMitsuru IWASAKI int 402e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length) 403e1e9a4bfSMitsuru IWASAKI { 404e1e9a4bfSMitsuru IWASAKI u_int8_t *bp; 405e1e9a4bfSMitsuru IWASAKI u_int8_t sum; 406e1e9a4bfSMitsuru IWASAKI 407e1e9a4bfSMitsuru IWASAKI bp = p; 408e1e9a4bfSMitsuru IWASAKI sum = 0; 409e1e9a4bfSMitsuru IWASAKI while (length--) 410e1e9a4bfSMitsuru IWASAKI sum += *bp++; 411e1e9a4bfSMitsuru IWASAKI 412e1e9a4bfSMitsuru IWASAKI return (sum); 413e1e9a4bfSMitsuru IWASAKI } 414e1e9a4bfSMitsuru IWASAKI 415945137d9SNate Lawson static struct ACPIsdt * 416e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa) 417e1e9a4bfSMitsuru IWASAKI { 418e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sp; 419e1e9a4bfSMitsuru IWASAKI 420e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 421e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sp->len); 422e1e9a4bfSMitsuru IWASAKI return (sp); 423e1e9a4bfSMitsuru IWASAKI } 424e1e9a4bfSMitsuru IWASAKI 425945137d9SNate Lawson static void 426e1e9a4bfSMitsuru IWASAKI acpi_print_rsd_ptr(struct ACPIrsdp *rp) 427e1e9a4bfSMitsuru IWASAKI { 428e1e9a4bfSMitsuru IWASAKI 429c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 430e1e9a4bfSMitsuru IWASAKI printf(" RSD PTR: Checksum=%d, OEMID=", rp->sum); 431e1e9a4bfSMitsuru IWASAKI acpi_print_string(rp->oem, 6); 43200d30537SMarcel Moolenaar printf(", RsdtAddress=0x%08x\n", rp->rsdt_addr); 433c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 434e1e9a4bfSMitsuru IWASAKI } 435e1e9a4bfSMitsuru IWASAKI 436945137d9SNate Lawson static void 437e1e9a4bfSMitsuru IWASAKI acpi_handle_rsdt(struct ACPIsdt *rsdp) 438e1e9a4bfSMitsuru IWASAKI { 439e1e9a4bfSMitsuru IWASAKI int i; 440e1e9a4bfSMitsuru IWASAKI int entries; 441e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sdp; 442e1e9a4bfSMitsuru IWASAKI 443e1e9a4bfSMitsuru IWASAKI entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 444e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(rsdp); 445e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 446e1e9a4bfSMitsuru IWASAKI sdp = (struct ACPIsdt *)acpi_map_sdt(rsdp->body[i]); 447e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(sdp, sdp->len)) 448945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 449945137d9SNate Lawson if (!memcmp(sdp->signature, "FACP", 4)) 450e1e9a4bfSMitsuru IWASAKI acpi_handle_facp((struct FACPbody *) sdp->body); 451945137d9SNate Lawson else if (!memcmp(sdp->signature, "APIC", 4)) 4520a473124SJohn Baldwin acpi_handle_apic(sdp); 453945137d9SNate Lawson else if (!memcmp(sdp->signature, "HPET", 4)) 45479d7565cSPeter Wemm acpi_handle_hpet(sdp); 455945137d9SNate Lawson else 456945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/1); 457e1e9a4bfSMitsuru IWASAKI } 458e1e9a4bfSMitsuru IWASAKI } 459c62f1cccSMitsuru IWASAKI 460945137d9SNate Lawson struct ACPIsdt * 461945137d9SNate Lawson sdt_load_devmem() 462945137d9SNate Lawson { 463945137d9SNate Lawson struct ACPIrsdp *rp; 464945137d9SNate Lawson struct ACPIsdt *rsdp; 465945137d9SNate Lawson 466945137d9SNate Lawson rp = acpi_find_rsd_ptr(); 467945137d9SNate Lawson if (!rp) 468945137d9SNate Lawson errx(1, "Can't find ACPI information"); 469945137d9SNate Lawson 470945137d9SNate Lawson if (tflag) 471945137d9SNate Lawson acpi_print_rsd_ptr(rp); 472945137d9SNate Lawson rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 473945137d9SNate Lawson if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 474945137d9SNate Lawson acpi_checksum(rsdp, rsdp->len) != 0) 475945137d9SNate Lawson errx(1, "RSDT is corrupted"); 476945137d9SNate Lawson 477945137d9SNate Lawson return (rsdp); 478945137d9SNate Lawson } 479c62f1cccSMitsuru IWASAKI 480c62f1cccSMitsuru IWASAKI void 481945137d9SNate Lawson dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 482c62f1cccSMitsuru IWASAKI { 483945137d9SNate Lawson int fd; 484945137d9SNate Lawson mode_t mode; 485945137d9SNate Lawson 486945137d9SNate Lawson assert(outfile != NULL); 487945137d9SNate Lawson mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 488945137d9SNate Lawson fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 489945137d9SNate Lawson if (fd == -1) { 490945137d9SNate Lawson perror("dsdt_save_file"); 491945137d9SNate Lawson return; 492945137d9SNate Lawson } 493945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 494945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 495945137d9SNate Lawson close(fd); 496c62f1cccSMitsuru IWASAKI } 497c62f1cccSMitsuru IWASAKI 498945137d9SNate Lawson void 499945137d9SNate Lawson aml_disassemble(struct ACPIsdt *dsdp) 500c62f1cccSMitsuru IWASAKI { 501945137d9SNate Lawson char tmpstr[32], buf[256]; 502945137d9SNate Lawson FILE *fp; 503945137d9SNate Lawson int fd, len; 504945137d9SNate Lawson 505945137d9SNate Lawson strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 506945137d9SNate Lawson fd = mkstemp(tmpstr); 507945137d9SNate Lawson if (fd < 0) { 508945137d9SNate Lawson perror("iasl tmp file"); 509945137d9SNate Lawson return; 510c62f1cccSMitsuru IWASAKI } 511c62f1cccSMitsuru IWASAKI 512945137d9SNate Lawson /* Dump DSDT to the temp file */ 513945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 514945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 515945137d9SNate Lawson close(fd); 516945137d9SNate Lawson 517945137d9SNate Lawson /* Run iasl -d on the temp file */ 518945137d9SNate Lawson if (fork() == 0) { 519945137d9SNate Lawson close(STDOUT_FILENO); 520945137d9SNate Lawson if (vflag == 0) 521945137d9SNate Lawson close(STDERR_FILENO); 522945137d9SNate Lawson execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 523945137d9SNate Lawson err(1, "exec"); 524c62f1cccSMitsuru IWASAKI } 525c62f1cccSMitsuru IWASAKI 526945137d9SNate Lawson wait(NULL); 527945137d9SNate Lawson unlink(tmpstr); 528945137d9SNate Lawson 529945137d9SNate Lawson /* Dump iasl's output to stdout */ 530945137d9SNate Lawson fp = fopen("acpidump.dsl", "r"); 531945137d9SNate Lawson unlink("acpidump.dsl"); 532945137d9SNate Lawson if (fp == NULL) { 533945137d9SNate Lawson perror("iasl tmp file (read)"); 534945137d9SNate Lawson return; 535945137d9SNate Lawson } 536945137d9SNate Lawson while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 537945137d9SNate Lawson fwrite(buf, 1, len, stdout); 538945137d9SNate Lawson fclose(fp); 539c62f1cccSMitsuru IWASAKI } 540c62f1cccSMitsuru IWASAKI 541945137d9SNate Lawson void 542945137d9SNate Lawson sdt_print_all(struct ACPIsdt *rsdp) 543c62f1cccSMitsuru IWASAKI { 544945137d9SNate Lawson acpi_handle_rsdt(rsdp); 545c62f1cccSMitsuru IWASAKI } 546c62f1cccSMitsuru IWASAKI 547945137d9SNate Lawson /* Fetch a table matching the given signature via the RSDT */ 548945137d9SNate Lawson struct ACPIsdt * 549945137d9SNate Lawson sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 550c62f1cccSMitsuru IWASAKI { 551945137d9SNate Lawson int i; 552945137d9SNate Lawson int entries; 553945137d9SNate Lawson struct ACPIsdt *sdt; 554945137d9SNate Lawson 555945137d9SNate Lawson entries = (rsdt->len - SIZEOF_SDT_HDR) / sizeof(uint32_t); 556945137d9SNate Lawson for (i = 0; i < entries; i++) { 557945137d9SNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(rsdt->body[i]); 558945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 559945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 560945137d9SNate Lawson if (!memcmp(sdt->signature, sig, strlen(sig))) 561945137d9SNate Lawson return (sdt); 562c62f1cccSMitsuru IWASAKI } 563c62f1cccSMitsuru IWASAKI 564945137d9SNate Lawson return (NULL); 565c62f1cccSMitsuru IWASAKI } 566c62f1cccSMitsuru IWASAKI 567945137d9SNate Lawson struct ACPIsdt * 568945137d9SNate Lawson dsdt_from_facp(struct FACPbody *facp) 569c62f1cccSMitsuru IWASAKI { 570945137d9SNate Lawson struct ACPIsdt *sdt; 571c62f1cccSMitsuru IWASAKI 572945137d9SNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(facp->dsdt_ptr); 573945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 574945137d9SNate Lawson errx(1, "DSDT is corrupt\n"); 575945137d9SNate Lawson return (sdt); 576c62f1cccSMitsuru IWASAKI } 577