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); 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); 63945137d9SNate Lawson static struct ACPIsdt * 64945137d9SNate Lawson acpi_map_sdt(vm_offset_t pa); 65945137d9SNate Lawson static void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 66945137d9SNate Lawson static void acpi_handle_rsdt(struct ACPIsdt *rsdp); 67c62f1cccSMitsuru IWASAKI 68e1e9a4bfSMitsuru IWASAKI static void 69e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length) 70e1e9a4bfSMitsuru IWASAKI { 71e1e9a4bfSMitsuru IWASAKI int c; 72e1e9a4bfSMitsuru IWASAKI 73e1e9a4bfSMitsuru IWASAKI /* Trim trailing spaces and NULLs */ 74e1e9a4bfSMitsuru IWASAKI while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 75e1e9a4bfSMitsuru IWASAKI length--; 76e1e9a4bfSMitsuru IWASAKI 77e1e9a4bfSMitsuru IWASAKI while (length--) { 78e1e9a4bfSMitsuru IWASAKI c = *s++; 79e1e9a4bfSMitsuru IWASAKI putchar(c); 80e1e9a4bfSMitsuru IWASAKI } 81e1e9a4bfSMitsuru IWASAKI } 82e1e9a4bfSMitsuru IWASAKI 83e1e9a4bfSMitsuru IWASAKI static void 848e6a8737SNate Lawson acpi_print_gas(struct ACPIgas *gas) 858e6a8737SNate Lawson { 868e6a8737SNate Lawson switch(gas->address_space_id) { 878e6a8737SNate Lawson case ACPI_GAS_MEMORY: 888e6a8737SNate Lawson printf("0x%08lx:%u[%u] (Memory)\n", (u_long)gas->address, 898e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 908e6a8737SNate Lawson break; 918e6a8737SNate Lawson case ACPI_GAS_IO: 928e6a8737SNate Lawson printf("0x%08lx:%u[%u] (IO)\n", (u_long)gas->address, 938e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 948e6a8737SNate Lawson break; 958e6a8737SNate Lawson case ACPI_GAS_PCI: 968e6a8737SNate Lawson printf("%x:%x+%#x (PCI)\n", (uint16_t)(gas->address >> 32), 978e6a8737SNate Lawson (uint16_t)((gas->address >> 16) & 0xffff), 988e6a8737SNate Lawson (uint16_t)gas->address); 998e6a8737SNate Lawson break; 1008e6a8737SNate Lawson /* XXX How to handle these below? */ 1018e6a8737SNate Lawson case ACPI_GAS_EMBEDDED: 1028e6a8737SNate Lawson printf("0x%#x:%u[%u] (EC)\n", (uint16_t)gas->address, 1038e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 1048e6a8737SNate Lawson break; 1058e6a8737SNate Lawson case ACPI_GAS_SMBUS: 1068e6a8737SNate Lawson printf("0x%#x:%u[%u] (SMBus)\n", (uint16_t)gas->address, 1078e6a8737SNate Lawson gas->bit_offset, gas->bit_width); 1088e6a8737SNate Lawson break; 1098e6a8737SNate Lawson case ACPI_GAS_FIXED: 1108e6a8737SNate Lawson default: 1118e6a8737SNate Lawson printf("0x%08lx (?)\n", (u_long)gas->address); 1128e6a8737SNate Lawson break; 1138e6a8737SNate Lawson } 1148e6a8737SNate Lawson } 1158e6a8737SNate Lawson 1168e6a8737SNate Lawson static void 1178e6a8737SNate Lawson acpi_handle_fadt(struct FADTbody *fadt) 118e1e9a4bfSMitsuru IWASAKI { 119e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *dsdp; 1208e6a8737SNate Lawson struct FACSbody *facs; 121e1e9a4bfSMitsuru IWASAKI 1228e6a8737SNate Lawson acpi_print_fadt(fadt); 1238e6a8737SNate Lawson 1248e6a8737SNate Lawson facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr); 1258e6a8737SNate Lawson if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64) 1268e6a8737SNate Lawson errx(1, "FACS is corrupt"); 1278e6a8737SNate Lawson acpi_print_facs(facs); 1288e6a8737SNate Lawson 1298e6a8737SNate Lawson dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 130e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(dsdp, dsdp->len)) 131945137d9SNate Lawson errx(1, "DSDT is corrupt"); 132945137d9SNate Lawson acpi_print_dsdt(dsdp); 133c62f1cccSMitsuru IWASAKI } 134c62f1cccSMitsuru IWASAKI 135c62f1cccSMitsuru IWASAKI static void 1360a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id) 1370a473124SJohn Baldwin { 1380a473124SJohn Baldwin 1390a473124SJohn Baldwin printf("\tACPI CPU="); 1400a473124SJohn Baldwin if (cpu_id == 0xff) 1410a473124SJohn Baldwin printf("ALL\n"); 1420a473124SJohn Baldwin else 1430a473124SJohn Baldwin printf("%d\n", (u_int)cpu_id); 1440a473124SJohn Baldwin } 1450a473124SJohn Baldwin 1460a473124SJohn Baldwin static void 1470a473124SJohn Baldwin acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 1480a473124SJohn Baldwin { 1490a473124SJohn Baldwin acpi_print_cpu(cpu_id); 1500a473124SJohn Baldwin printf("\tFlags={"); 1510a473124SJohn Baldwin if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 1520a473124SJohn Baldwin printf("ENABLED"); 1530a473124SJohn Baldwin else 1540a473124SJohn Baldwin printf("DISABLED"); 1550a473124SJohn Baldwin printf("}\n"); 1560a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1570a473124SJohn Baldwin } 1580a473124SJohn Baldwin 1590a473124SJohn Baldwin static void 1600a473124SJohn Baldwin acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 1610a473124SJohn Baldwin { 1620a473124SJohn Baldwin printf("\tAPIC ID=%d\n", (u_int)apic_id); 1630a473124SJohn Baldwin printf("\tINT BASE=%d\n", int_base); 164945137d9SNate Lawson printf("\tADDR=0x%016jx\n", apic_addr); 1650a473124SJohn Baldwin } 1660a473124SJohn Baldwin 1670a473124SJohn Baldwin static void 1680a473124SJohn Baldwin acpi_print_mps_flags(u_int16_t flags) 1690a473124SJohn Baldwin { 1700a473124SJohn Baldwin 1710a473124SJohn Baldwin printf("\tFlags={Polarity="); 1720a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 1730a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_CONFORM: 1740a473124SJohn Baldwin printf("conforming"); 1750a473124SJohn Baldwin break; 1760a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_HIGH: 1770a473124SJohn Baldwin printf("active-hi"); 1780a473124SJohn Baldwin break; 1790a473124SJohn Baldwin case MPS_INT_FLAG_POLARITY_LOW: 1800a473124SJohn Baldwin printf("active-lo"); 1810a473124SJohn Baldwin break; 1820a473124SJohn Baldwin default: 1830a473124SJohn Baldwin printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 1840a473124SJohn Baldwin break; 1850a473124SJohn Baldwin } 1860a473124SJohn Baldwin printf(", Trigger="); 1870a473124SJohn Baldwin switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 1880a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_CONFORM: 1890a473124SJohn Baldwin printf("conforming"); 1900a473124SJohn Baldwin break; 1910a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_EDGE: 1920a473124SJohn Baldwin printf("edge"); 1930a473124SJohn Baldwin break; 1940a473124SJohn Baldwin case MPS_INT_FLAG_TRIGGER_LEVEL: 1950a473124SJohn Baldwin printf("level"); 1960a473124SJohn Baldwin break; 1970a473124SJohn Baldwin default: 1980a473124SJohn Baldwin printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 1990a473124SJohn Baldwin } 2000a473124SJohn Baldwin printf("}\n"); 2010a473124SJohn Baldwin } 2020a473124SJohn Baldwin 2030a473124SJohn Baldwin static void 2040a473124SJohn Baldwin acpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 2050a473124SJohn Baldwin { 2060a473124SJohn Baldwin 2070a473124SJohn Baldwin printf("\tINTR=%d\n", (u_int)intr); 2080a473124SJohn Baldwin acpi_print_mps_flags(mps_flags); 2090a473124SJohn Baldwin } 2100a473124SJohn Baldwin 2110a473124SJohn Baldwin const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 2120a473124SJohn Baldwin "Local NMI", "Local APIC Override", "IO SAPIC", 2130a473124SJohn Baldwin "Local SAPIC", "Platform Interrupt" }; 2140a473124SJohn Baldwin const char *platform_int_types[] = { "PMI", "INIT", 2150a473124SJohn Baldwin "Corrected Platform Error" }; 2160a473124SJohn Baldwin 2170a473124SJohn Baldwin static void 2180a473124SJohn Baldwin acpi_print_apic(struct MADT_APIC *mp) 2190a473124SJohn Baldwin { 2200a473124SJohn Baldwin 2210a473124SJohn Baldwin printf("\tType=%s\n", apic_types[mp->type]); 2220a473124SJohn Baldwin switch (mp->type) { 2230a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 2240a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_apic.cpu_id, 2250a473124SJohn Baldwin mp->body.local_apic.apic_id, mp->body.local_apic.flags); 2260a473124SJohn Baldwin break; 2270a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_APIC: 2280a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_apic.apic_id, 2290a473124SJohn Baldwin mp->body.io_apic.int_base, 2300a473124SJohn Baldwin mp->body.io_apic.apic_addr); 2310a473124SJohn Baldwin break; 2320a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 2330a473124SJohn Baldwin printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 2340a473124SJohn Baldwin printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 2350a473124SJohn Baldwin acpi_print_intr(mp->body.int_override.intr, 2360a473124SJohn Baldwin mp->body.int_override.mps_flags); 2370a473124SJohn Baldwin break; 2380a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_NMI: 2390a473124SJohn Baldwin acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 2400a473124SJohn Baldwin break; 2410a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 2420a473124SJohn Baldwin acpi_print_cpu(mp->body.local_nmi.cpu_id); 2430a473124SJohn Baldwin printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 2440a473124SJohn Baldwin acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 2450a473124SJohn Baldwin break; 2460a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 247945137d9SNate Lawson printf("\tLocal APIC ADDR=0x%016jx\n", 248945137d9SNate Lawson mp->body.local_apic_override.apic_addr); 2490a473124SJohn Baldwin break; 2500a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_IO_SAPIC: 2510a473124SJohn Baldwin acpi_print_io_apic(mp->body.io_sapic.apic_id, 2520a473124SJohn Baldwin mp->body.io_sapic.int_base, 2530a473124SJohn Baldwin mp->body.io_sapic.apic_addr); 2540a473124SJohn Baldwin break; 2550a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 2560a473124SJohn Baldwin acpi_print_local_apic(mp->body.local_sapic.cpu_id, 2570a473124SJohn Baldwin mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 2580a473124SJohn Baldwin printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 2590a473124SJohn Baldwin break; 2600a473124SJohn Baldwin case ACPI_MADT_APIC_TYPE_INT_SRC: 2610a473124SJohn Baldwin printf("\tType=%s\n", 2620a473124SJohn Baldwin platform_int_types[mp->body.int_src.type]); 2630a473124SJohn Baldwin printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 2640a473124SJohn Baldwin printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 2650a473124SJohn Baldwin printf("\tSAPIC Vector=%d\n", 2660a473124SJohn Baldwin (u_int)mp->body.int_src.sapic_vector); 2670a473124SJohn Baldwin acpi_print_intr(mp->body.int_src.intr, 2680a473124SJohn Baldwin mp->body.int_src.mps_flags); 2690a473124SJohn Baldwin break; 2700a473124SJohn Baldwin default: 2710a473124SJohn Baldwin printf("\tUnknown type %d\n", (u_int)mp->type); 272945137d9SNate Lawson break; 2730a473124SJohn Baldwin } 2740a473124SJohn Baldwin } 2750a473124SJohn Baldwin 2760a473124SJohn Baldwin static void 2770a473124SJohn Baldwin acpi_handle_apic(struct ACPIsdt *sdp) 2780a473124SJohn Baldwin { 2790a473124SJohn Baldwin struct MADTbody *madtp; 2800a473124SJohn Baldwin struct MADT_APIC *madt_apicp; 2810a473124SJohn Baldwin 282945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/0); 2830a473124SJohn Baldwin madtp = (struct MADTbody *) sdp->body; 2840a473124SJohn Baldwin printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 2850a473124SJohn Baldwin printf("\tFlags={"); 2860a473124SJohn Baldwin if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 2870a473124SJohn Baldwin printf("PC-AT"); 2880a473124SJohn Baldwin printf("}\n"); 2890a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *)madtp->body; 2900a473124SJohn Baldwin while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 2910a473124SJohn Baldwin printf("\n"); 2920a473124SJohn Baldwin acpi_print_apic(madt_apicp); 2930a473124SJohn Baldwin madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 2940a473124SJohn Baldwin madt_apicp->len); 2950a473124SJohn Baldwin } 2960a473124SJohn Baldwin printf(END_COMMENT); 2970a473124SJohn Baldwin } 2980a473124SJohn Baldwin 2990a473124SJohn Baldwin static void 30079d7565cSPeter Wemm acpi_handle_hpet(struct ACPIsdt *sdp) 30179d7565cSPeter Wemm { 30279d7565cSPeter Wemm struct HPETbody *hpetp; 30379d7565cSPeter Wemm 304945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/0); 30579d7565cSPeter Wemm hpetp = (struct HPETbody *) sdp->body; 30679d7565cSPeter Wemm printf("\tHPET Number=%d\n", hpetp->hpet_number); 30779d7565cSPeter Wemm printf("\tADDR=0x%08x\n", hpetp->base_addr); 30879d7565cSPeter Wemm printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 30979d7565cSPeter Wemm printf("\tComparitors=%d\n", hpetp->block_comparitors); 31079d7565cSPeter Wemm printf("\tCounter Size=%d\n", hpetp->block_counter_size); 31179d7565cSPeter Wemm printf("\tLegacy IRQ routing capable={"); 31279d7565cSPeter Wemm if (hpetp->block_legacy_capable) 31379d7565cSPeter Wemm printf("TRUE}\n"); 31479d7565cSPeter Wemm else 31579d7565cSPeter Wemm printf("FALSE}\n"); 31679d7565cSPeter Wemm printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 31755da3c73SPeter Wemm printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 31879d7565cSPeter Wemm printf(END_COMMENT); 31979d7565cSPeter Wemm } 32079d7565cSPeter Wemm 32179d7565cSPeter Wemm static void 322945137d9SNate Lawson acpi_print_sdt(struct ACPIsdt *sdp, int endcomment) 323c62f1cccSMitsuru IWASAKI { 324945137d9SNate Lawson printf(BEGIN_COMMENT " "); 325e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->signature, 4); 326c62f1cccSMitsuru IWASAKI printf(": Length=%d, Revision=%d, Checksum=%d,\n", 327e1e9a4bfSMitsuru IWASAKI sdp->len, sdp->rev, sdp->check); 328e1e9a4bfSMitsuru IWASAKI printf("\tOEMID="); 329e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemid, 6); 330e1e9a4bfSMitsuru IWASAKI printf(", OEM Table ID="); 331e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemtblid, 8); 332e1e9a4bfSMitsuru IWASAKI printf(", OEM Revision=0x%x,\n", sdp->oemrev); 333e1e9a4bfSMitsuru IWASAKI printf("\tCreator ID="); 334e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->creator, 4); 335e1e9a4bfSMitsuru IWASAKI printf(", Creator Revision=0x%x\n", sdp->crerev); 336945137d9SNate Lawson if (endcomment) 337c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 338e1e9a4bfSMitsuru IWASAKI } 339e1e9a4bfSMitsuru IWASAKI 340945137d9SNate Lawson static void 341e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(struct ACPIsdt *rsdp) 342e1e9a4bfSMitsuru IWASAKI { 343e1e9a4bfSMitsuru IWASAKI int i, entries; 344e1e9a4bfSMitsuru IWASAKI 345945137d9SNate Lawson acpi_print_sdt(rsdp, /*endcomment*/0); 346e1e9a4bfSMitsuru IWASAKI entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 347e1e9a4bfSMitsuru IWASAKI printf("\tEntries={ "); 348e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 349e1e9a4bfSMitsuru IWASAKI if (i > 0) 350e1e9a4bfSMitsuru IWASAKI printf(", "); 351e1e9a4bfSMitsuru IWASAKI printf("0x%08x", rsdp->body[i]); 352e1e9a4bfSMitsuru IWASAKI } 353e1e9a4bfSMitsuru IWASAKI printf(" }\n"); 354c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 355e1e9a4bfSMitsuru IWASAKI } 356e1e9a4bfSMitsuru IWASAKI 3578e6a8737SNate Lawson static const char *acpi_pm_profiles[] = { 3588e6a8737SNate Lawson "Unspecified", "Desktop", "Mobile", "Workstation", 3598e6a8737SNate Lawson "Enterprise Server", "SOHO Server", "Appliance PC" 3608e6a8737SNate Lawson }; 3618e6a8737SNate Lawson 362945137d9SNate Lawson static void 3638e6a8737SNate Lawson acpi_print_fadt(struct FADTbody *fadt) 364e1e9a4bfSMitsuru IWASAKI { 3658e6a8737SNate Lawson const char *pm; 366e1e9a4bfSMitsuru IWASAKI char sep; 367e1e9a4bfSMitsuru IWASAKI 368c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 3698e6a8737SNate Lawson printf(" FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr, 3708e6a8737SNate Lawson fadt->dsdt_ptr); 3718e6a8737SNate Lawson printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC"); 3728e6a8737SNate Lawson if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 3738e6a8737SNate Lawson pm = "Reserved"; 3748e6a8737SNate Lawson else 3758e6a8737SNate Lawson pm = acpi_pm_profiles[fadt->pm_profile]; 3768e6a8737SNate Lawson printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile); 3778e6a8737SNate Lawson printf("\tSCI_INT=%d\n", fadt->sci_int); 3788e6a8737SNate Lawson printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd); 3798e6a8737SNate Lawson printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable); 3808e6a8737SNate Lawson printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable); 3818e6a8737SNate Lawson printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq); 3828e6a8737SNate Lawson printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt); 3838e6a8737SNate Lawson if (fadt->pm1a_evt_blk != 0) 384e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 3858e6a8737SNate Lawson fadt->pm1a_evt_blk, 3868e6a8737SNate Lawson fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1); 3878e6a8737SNate Lawson if (fadt->pm1b_evt_blk != 0) 388e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 3898e6a8737SNate Lawson fadt->pm1b_evt_blk, 3908e6a8737SNate Lawson fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1); 3918e6a8737SNate Lawson if (fadt->pm1a_cnt_blk != 0) 392e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 3938e6a8737SNate Lawson fadt->pm1a_cnt_blk, 3948e6a8737SNate Lawson fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1); 3958e6a8737SNate Lawson if (fadt->pm1b_cnt_blk != 0) 396e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 3978e6a8737SNate Lawson fadt->pm1b_cnt_blk, 3988e6a8737SNate Lawson fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1); 3998e6a8737SNate Lawson if (fadt->pm2_cnt_blk != 0) 400e1e9a4bfSMitsuru IWASAKI printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 4018e6a8737SNate Lawson fadt->pm2_cnt_blk, 4028e6a8737SNate Lawson fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1); 4038e6a8737SNate Lawson if (fadt->pm_tmr_blk != 0) 404e1e9a4bfSMitsuru IWASAKI printf("\tPM2_TMR_BLK=0x%x-0x%x\n", 4058e6a8737SNate Lawson fadt->pm_tmr_blk, 4068e6a8737SNate Lawson fadt->pm_tmr_blk + fadt->pm_tmr_len - 1); 4078e6a8737SNate Lawson if (fadt->gpe0_blk != 0) 4088e6a8737SNate Lawson printf("\tGPE0_BLK=0x%x-0x%x\n", 4098e6a8737SNate Lawson fadt->gpe0_blk, 4108e6a8737SNate Lawson fadt->gpe0_blk + fadt->gpe0_len - 1); 4118e6a8737SNate Lawson if (fadt->gpe1_blk != 0) 4128e6a8737SNate Lawson printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 4138e6a8737SNate Lawson fadt->gpe1_blk, 4148e6a8737SNate Lawson fadt->gpe1_blk + fadt->gpe1_len - 1, 4158e6a8737SNate Lawson fadt->gpe1_base); 4168e6a8737SNate Lawson if (fadt->cst_cnt != 0) 4178e6a8737SNate Lawson printf("\tCST_CNT=0x%x\n", fadt->cst_cnt); 418e1e9a4bfSMitsuru IWASAKI printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 4198e6a8737SNate Lawson fadt->p_lvl2_lat, fadt->p_lvl3_lat); 420e1e9a4bfSMitsuru IWASAKI printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 4218e6a8737SNate Lawson fadt->flush_size, fadt->flush_stride); 422e1e9a4bfSMitsuru IWASAKI printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 4238e6a8737SNate Lawson fadt->duty_off, fadt->duty_width); 424e1e9a4bfSMitsuru IWASAKI printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 4258e6a8737SNate Lawson fadt->day_alrm, fadt->mon_alrm, fadt->century); 426e1e9a4bfSMitsuru IWASAKI 4278e6a8737SNate Lawson #define PRINTFLAG(var, flag) do { \ 4288e6a8737SNate Lawson if ((var) & FADT_FLAG_## flag) { \ 4298e6a8737SNate Lawson printf("%c%s", sep, #flag); sep = ','; \ 430e1e9a4bfSMitsuru IWASAKI } \ 431e1e9a4bfSMitsuru IWASAKI } while (0) 432e1e9a4bfSMitsuru IWASAKI 4338e6a8737SNate Lawson printf("\tIAPC_BOOT_ARCH="); 4348e6a8737SNate Lawson sep = '{'; 4358e6a8737SNate Lawson PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV); 4368e6a8737SNate Lawson PRINTFLAG(fadt->iapc_boot_arch, 8042); 4378e6a8737SNate Lawson printf("}\n"); 4388e6a8737SNate Lawson 4398e6a8737SNate Lawson printf("\tFlags="); 4408e6a8737SNate Lawson sep = '{'; 4418e6a8737SNate Lawson PRINTFLAG(fadt->flags, WBINVD); 4428e6a8737SNate Lawson PRINTFLAG(fadt->flags, WBINVD_FLUSH); 4438e6a8737SNate Lawson PRINTFLAG(fadt->flags, PROC_C1); 4448e6a8737SNate Lawson PRINTFLAG(fadt->flags, P_LVL2_UP); 4458e6a8737SNate Lawson PRINTFLAG(fadt->flags, PWR_BUTTON); 4468e6a8737SNate Lawson PRINTFLAG(fadt->flags, SLP_BUTTON); 4478e6a8737SNate Lawson PRINTFLAG(fadt->flags, FIX_RTC); 4488e6a8737SNate Lawson PRINTFLAG(fadt->flags, RTC_S4); 4498e6a8737SNate Lawson PRINTFLAG(fadt->flags, TMR_VAL_EXT); 4508e6a8737SNate Lawson PRINTFLAG(fadt->flags, DCK_CAP); 4518e6a8737SNate Lawson PRINTFLAG(fadt->flags, RESET_REG); 4528e6a8737SNate Lawson PRINTFLAG(fadt->flags, SEALED_CASE); 4538e6a8737SNate Lawson PRINTFLAG(fadt->flags, HEADLESS); 4548e6a8737SNate Lawson PRINTFLAG(fadt->flags, CPU_SW_SLP); 4558e6a8737SNate Lawson printf("}\n"); 456e1e9a4bfSMitsuru IWASAKI 457e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG 458e1e9a4bfSMitsuru IWASAKI 4598e6a8737SNate Lawson if (fadt->flags & FADT_FLAG_RESET_REG) { 4608e6a8737SNate Lawson printf("\tRESET_REG="); 4618e6a8737SNate Lawson acpi_print_gas(&fadt->reset_reg); 4628e6a8737SNate Lawson printf(", RESET_VALUE=%#x\n", fadt->reset_value); 4638e6a8737SNate Lawson } 4648e6a8737SNate Lawson 4658e6a8737SNate Lawson printf(END_COMMENT); 4668e6a8737SNate Lawson } 4678e6a8737SNate Lawson 4688e6a8737SNate Lawson static void 4698e6a8737SNate Lawson acpi_print_facs(struct FACSbody *facs) 4708e6a8737SNate Lawson { 4718e6a8737SNate Lawson printf(BEGIN_COMMENT); 4728e6a8737SNate Lawson printf(" FACS:\tLength=%u, ", facs->len); 4738e6a8737SNate Lawson printf("HwSig=0x%08x, ", facs->hw_sig); 4748e6a8737SNate Lawson printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec); 4758e6a8737SNate Lawson 4768e6a8737SNate Lawson printf("\tGlobal_Lock={"); 4778e6a8737SNate Lawson if (facs->global_lock != 0) { 4788e6a8737SNate Lawson if (facs->global_lock & FACS_FLAG_LOCK_PENDING) 4798e6a8737SNate Lawson printf("PENDING,"); 4808e6a8737SNate Lawson if (facs->global_lock & FACS_FLAG_LOCK_OWNED) 4818e6a8737SNate Lawson printf("OWNED"); 4828e6a8737SNate Lawson } 483e1e9a4bfSMitsuru IWASAKI printf("}\n"); 4848e6a8737SNate Lawson 4858e6a8737SNate Lawson printf("\tFlags={"); 4868e6a8737SNate Lawson if (facs->flags & FACS_FLAG_S4BIOS_F) 4878e6a8737SNate Lawson printf("S4BIOS"); 4888e6a8737SNate Lawson printf("}\n"); 4898e6a8737SNate Lawson 4908e6a8737SNate Lawson if (facs->x_firm_wake_vec != 0) { 4918e6a8737SNate Lawson printf("\tX_Firm_Wake_Vec=%08lx\n", 4928e6a8737SNate Lawson (u_long)facs->x_firm_wake_vec); 4938e6a8737SNate Lawson } 4948e6a8737SNate Lawson 495c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 496e1e9a4bfSMitsuru IWASAKI } 497e1e9a4bfSMitsuru IWASAKI 498945137d9SNate Lawson static void 499e1e9a4bfSMitsuru IWASAKI acpi_print_dsdt(struct ACPIsdt *dsdp) 500e1e9a4bfSMitsuru IWASAKI { 501945137d9SNate Lawson acpi_print_sdt(dsdp, /*endcomment*/1); 502e1e9a4bfSMitsuru IWASAKI } 503e1e9a4bfSMitsuru IWASAKI 504e1e9a4bfSMitsuru IWASAKI int 505e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length) 506e1e9a4bfSMitsuru IWASAKI { 507e1e9a4bfSMitsuru IWASAKI u_int8_t *bp; 508e1e9a4bfSMitsuru IWASAKI u_int8_t sum; 509e1e9a4bfSMitsuru IWASAKI 510e1e9a4bfSMitsuru IWASAKI bp = p; 511e1e9a4bfSMitsuru IWASAKI sum = 0; 512e1e9a4bfSMitsuru IWASAKI while (length--) 513e1e9a4bfSMitsuru IWASAKI sum += *bp++; 514e1e9a4bfSMitsuru IWASAKI 515e1e9a4bfSMitsuru IWASAKI return (sum); 516e1e9a4bfSMitsuru IWASAKI } 517e1e9a4bfSMitsuru IWASAKI 518945137d9SNate Lawson static struct ACPIsdt * 519e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa) 520e1e9a4bfSMitsuru IWASAKI { 521e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sp; 522e1e9a4bfSMitsuru IWASAKI 523e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 524e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sp->len); 525e1e9a4bfSMitsuru IWASAKI return (sp); 526e1e9a4bfSMitsuru IWASAKI } 527e1e9a4bfSMitsuru IWASAKI 528945137d9SNate Lawson static void 529e1e9a4bfSMitsuru IWASAKI acpi_print_rsd_ptr(struct ACPIrsdp *rp) 530e1e9a4bfSMitsuru IWASAKI { 531e1e9a4bfSMitsuru IWASAKI 532c62f1cccSMitsuru IWASAKI printf(BEGIN_COMMENT); 533e1e9a4bfSMitsuru IWASAKI printf(" RSD PTR: Checksum=%d, OEMID=", rp->sum); 534e1e9a4bfSMitsuru IWASAKI acpi_print_string(rp->oem, 6); 53500d30537SMarcel Moolenaar printf(", RsdtAddress=0x%08x\n", rp->rsdt_addr); 536c62f1cccSMitsuru IWASAKI printf(END_COMMENT); 537e1e9a4bfSMitsuru IWASAKI } 538e1e9a4bfSMitsuru IWASAKI 539945137d9SNate Lawson static void 540e1e9a4bfSMitsuru IWASAKI acpi_handle_rsdt(struct ACPIsdt *rsdp) 541e1e9a4bfSMitsuru IWASAKI { 542e1e9a4bfSMitsuru IWASAKI int i; 543e1e9a4bfSMitsuru IWASAKI int entries; 544e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sdp; 545e1e9a4bfSMitsuru IWASAKI 546e1e9a4bfSMitsuru IWASAKI entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 547e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(rsdp); 548e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 549e1e9a4bfSMitsuru IWASAKI sdp = (struct ACPIsdt *)acpi_map_sdt(rsdp->body[i]); 550e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(sdp, sdp->len)) 551945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 552945137d9SNate Lawson if (!memcmp(sdp->signature, "FACP", 4)) 5538e6a8737SNate Lawson acpi_handle_fadt((struct FADTbody *) sdp->body); 554945137d9SNate Lawson else if (!memcmp(sdp->signature, "APIC", 4)) 5550a473124SJohn Baldwin acpi_handle_apic(sdp); 556945137d9SNate Lawson else if (!memcmp(sdp->signature, "HPET", 4)) 55779d7565cSPeter Wemm acpi_handle_hpet(sdp); 558945137d9SNate Lawson else 559945137d9SNate Lawson acpi_print_sdt(sdp, /*endcomment*/1); 560e1e9a4bfSMitsuru IWASAKI } 561e1e9a4bfSMitsuru IWASAKI } 562c62f1cccSMitsuru IWASAKI 563945137d9SNate Lawson struct ACPIsdt * 564945137d9SNate Lawson sdt_load_devmem() 565945137d9SNate Lawson { 566945137d9SNate Lawson struct ACPIrsdp *rp; 567945137d9SNate Lawson struct ACPIsdt *rsdp; 568945137d9SNate Lawson 569945137d9SNate Lawson rp = acpi_find_rsd_ptr(); 570945137d9SNate Lawson if (!rp) 571945137d9SNate Lawson errx(1, "Can't find ACPI information"); 572945137d9SNate Lawson 573945137d9SNate Lawson if (tflag) 574945137d9SNate Lawson acpi_print_rsd_ptr(rp); 575945137d9SNate Lawson rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 576945137d9SNate Lawson if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 577945137d9SNate Lawson acpi_checksum(rsdp, rsdp->len) != 0) 578945137d9SNate Lawson errx(1, "RSDT is corrupted"); 579945137d9SNate Lawson 580945137d9SNate Lawson return (rsdp); 581945137d9SNate Lawson } 582c62f1cccSMitsuru IWASAKI 583c62f1cccSMitsuru IWASAKI void 584945137d9SNate Lawson dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 585c62f1cccSMitsuru IWASAKI { 586945137d9SNate Lawson int fd; 587945137d9SNate Lawson mode_t mode; 588945137d9SNate Lawson 589945137d9SNate Lawson assert(outfile != NULL); 590945137d9SNate Lawson mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 591945137d9SNate Lawson fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 592945137d9SNate Lawson if (fd == -1) { 593945137d9SNate Lawson perror("dsdt_save_file"); 594945137d9SNate Lawson return; 595945137d9SNate Lawson } 596945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 597945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 598945137d9SNate Lawson close(fd); 599c62f1cccSMitsuru IWASAKI } 600c62f1cccSMitsuru IWASAKI 601945137d9SNate Lawson void 602945137d9SNate Lawson aml_disassemble(struct ACPIsdt *dsdp) 603c62f1cccSMitsuru IWASAKI { 604945137d9SNate Lawson char tmpstr[32], buf[256]; 605945137d9SNate Lawson FILE *fp; 606945137d9SNate Lawson int fd, len; 607945137d9SNate Lawson 608945137d9SNate Lawson strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 609945137d9SNate Lawson fd = mkstemp(tmpstr); 610945137d9SNate Lawson if (fd < 0) { 611945137d9SNate Lawson perror("iasl tmp file"); 612945137d9SNate Lawson return; 613c62f1cccSMitsuru IWASAKI } 614c62f1cccSMitsuru IWASAKI 615945137d9SNate Lawson /* Dump DSDT to the temp file */ 616945137d9SNate Lawson write(fd, dsdp, SIZEOF_SDT_HDR); 617945137d9SNate Lawson write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 618945137d9SNate Lawson close(fd); 619945137d9SNate Lawson 620945137d9SNate Lawson /* Run iasl -d on the temp file */ 621945137d9SNate Lawson if (fork() == 0) { 622945137d9SNate Lawson close(STDOUT_FILENO); 623945137d9SNate Lawson if (vflag == 0) 624945137d9SNate Lawson close(STDERR_FILENO); 625945137d9SNate Lawson execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 626945137d9SNate Lawson err(1, "exec"); 627c62f1cccSMitsuru IWASAKI } 628c62f1cccSMitsuru IWASAKI 629945137d9SNate Lawson wait(NULL); 630945137d9SNate Lawson unlink(tmpstr); 631945137d9SNate Lawson 632945137d9SNate Lawson /* Dump iasl's output to stdout */ 633945137d9SNate Lawson fp = fopen("acpidump.dsl", "r"); 634945137d9SNate Lawson unlink("acpidump.dsl"); 635945137d9SNate Lawson if (fp == NULL) { 636945137d9SNate Lawson perror("iasl tmp file (read)"); 637945137d9SNate Lawson return; 638945137d9SNate Lawson } 639945137d9SNate Lawson while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 640945137d9SNate Lawson fwrite(buf, 1, len, stdout); 641945137d9SNate Lawson fclose(fp); 642c62f1cccSMitsuru IWASAKI } 643c62f1cccSMitsuru IWASAKI 644945137d9SNate Lawson void 645945137d9SNate Lawson sdt_print_all(struct ACPIsdt *rsdp) 646c62f1cccSMitsuru IWASAKI { 647945137d9SNate Lawson acpi_handle_rsdt(rsdp); 648c62f1cccSMitsuru IWASAKI } 649c62f1cccSMitsuru IWASAKI 650945137d9SNate Lawson /* Fetch a table matching the given signature via the RSDT */ 651945137d9SNate Lawson struct ACPIsdt * 652945137d9SNate Lawson sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 653c62f1cccSMitsuru IWASAKI { 654945137d9SNate Lawson int i; 655945137d9SNate Lawson int entries; 656945137d9SNate Lawson struct ACPIsdt *sdt; 657945137d9SNate Lawson 658945137d9SNate Lawson entries = (rsdt->len - SIZEOF_SDT_HDR) / sizeof(uint32_t); 659945137d9SNate Lawson for (i = 0; i < entries; i++) { 660945137d9SNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(rsdt->body[i]); 661945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 662945137d9SNate Lawson errx(1, "RSDT entry %d is corrupt", i); 663945137d9SNate Lawson if (!memcmp(sdt->signature, sig, strlen(sig))) 664945137d9SNate Lawson return (sdt); 665c62f1cccSMitsuru IWASAKI } 666c62f1cccSMitsuru IWASAKI 667945137d9SNate Lawson return (NULL); 668c62f1cccSMitsuru IWASAKI } 669c62f1cccSMitsuru IWASAKI 670945137d9SNate Lawson struct ACPIsdt * 6718e6a8737SNate Lawson dsdt_from_fadt(struct FADTbody *fadt) 672c62f1cccSMitsuru IWASAKI { 673945137d9SNate Lawson struct ACPIsdt *sdt; 674c62f1cccSMitsuru IWASAKI 6758e6a8737SNate Lawson sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 676945137d9SNate Lawson if (acpi_checksum(sdt, sdt->len)) 677945137d9SNate Lawson errx(1, "DSDT is corrupt\n"); 678945137d9SNate Lawson return (sdt); 679c62f1cccSMitsuru IWASAKI } 680