acpi.c revision 120309
1161475Sdelphij/*- 260786Sps * Copyright (c) 1998 Doug Rabson 360786Sps * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 460786Sps * All rights reserved. 5170256Sdelphij * 660786Sps * Redistribution and use in source and binary forms, with or without 760786Sps * modification, are permitted provided that the following conditions 8170256Sdelphij * are met: 9170256Sdelphij * 1. Redistributions of source code must retain the above copyright 10170256Sdelphij * notice, this list of conditions and the following disclaimer. 11170256Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 12170256Sdelphij * notice, this list of conditions and the following disclaimer in the 13170256Sdelphij * documentation and/or other materials provided with the distribution. 14170256Sdelphij * 15170256Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16170256Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17170256Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18161475Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19161475Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2060786Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2160786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22170256Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23170256Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24170256Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25161475Sdelphij * SUCH DAMAGE. 26170256Sdelphij * 27161475Sdelphij * $FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 120309 2003-09-21 03:51:48Z njl $ 28161475Sdelphij */ 29161475Sdelphij 30161475Sdelphij#include <sys/param.h> 3160786Sps#include <sys/endian.h> 32170256Sdelphij#include <sys/stat.h> 33161475Sdelphij#include <sys/wait.h> 34161475Sdelphij#include <assert.h> 3560786Sps#include <err.h> 3660786Sps#include <fcntl.h> 37170256Sdelphij#include <stdio.h> 38161475Sdelphij#include <string.h> 39161475Sdelphij#include <unistd.h> 40161475Sdelphij 4160786Sps#include "acpidump.h" 42161475Sdelphij 43161475Sdelphij#define BEGIN_COMMENT "/*\n" 4460786Sps#define END_COMMENT " */\n" 4560786Sps 46161475Sdelphijstatic void acpi_print_string(char *s, size_t length); 47161475Sdelphijstatic void acpi_print_gas(struct ACPIgas *gas); 48161475Sdelphijstatic void acpi_handle_fadt(struct FADTbody *fadt); 49161475Sdelphijstatic void acpi_print_cpu(u_char cpu_id); 5060786Spsstatic void acpi_print_local_apic(u_char cpu_id, u_char apic_id, 51161475Sdelphij u_int32_t flags); 52161475Sdelphijstatic void acpi_print_io_apic(u_char apic_id, u_int32_t int_base, 5360786Sps u_int64_t apic_addr); 5460786Spsstatic void acpi_print_mps_flags(u_int16_t flags); 55161475Sdelphijstatic void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags); 56161475Sdelphijstatic void acpi_print_apic(struct MADT_APIC *mp); 5760786Spsstatic void acpi_handle_apic(struct ACPIsdt *sdp); 5860786Spsstatic void acpi_handle_hpet(struct ACPIsdt *sdp); 59161475Sdelphijstatic void acpi_print_sdt(struct ACPIsdt *sdp); 60161475Sdelphijstatic void acpi_print_fadt(struct FADTbody *fadt); 6160786Spsstatic void acpi_print_facs(struct FACSbody *facs); 6260786Spsstatic void acpi_print_dsdt(struct ACPIsdt *dsdp); 63161475Sdelphijstatic struct ACPIsdt *acpi_map_sdt(vm_offset_t pa); 64161475Sdelphijstatic void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 65161475Sdelphijstatic void acpi_handle_rsdt(struct ACPIsdt *rsdp); 6660786Sps 6760786Sps/* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */ 68161475Sdelphijstatic int addr_size; 69161475Sdelphij 70161475Sdelphijstatic void 7160786Spsacpi_print_string(char *s, size_t length) 72161475Sdelphij{ 73161475Sdelphij int c; 7460786Sps 7560786Sps /* Trim trailing spaces and NULLs */ 76161475Sdelphij while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 77161475Sdelphij length--; 78161475Sdelphij 7960786Sps while (length--) { 8060786Sps c = *s++; 81161475Sdelphij putchar(c); 82161475Sdelphij } 83161475Sdelphij} 8460786Sps 8560786Spsstatic void 86161475Sdelphijacpi_print_gas(struct ACPIgas *gas) 87161475Sdelphij{ 88161475Sdelphij switch(gas->address_space_id) { 89161475Sdelphij case ACPI_GAS_MEMORY: 9089019Sps printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->address, 9160786Sps gas->bit_offset, gas->bit_width); 9260786Sps break; 93161475Sdelphij case ACPI_GAS_IO: 94161475Sdelphij printf("0x%02lx:%u[%u] (IO)", (u_long)gas->address, 95161475Sdelphij gas->bit_offset, gas->bit_width); 96161475Sdelphij break; 9760786Sps case ACPI_GAS_PCI: 9860786Sps printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->address >> 32), 9960786Sps (uint16_t)((gas->address >> 16) & 0xffff), 10060786Sps (uint16_t)gas->address); 101161475Sdelphij break; 102161475Sdelphij /* XXX How to handle these below? */ 10360786Sps case ACPI_GAS_EMBEDDED: 104161475Sdelphij printf("0x%x:%u[%u] (EC)", (uint16_t)gas->address, 105161475Sdelphij gas->bit_offset, gas->bit_width); 106161475Sdelphij break; 107161475Sdelphij case ACPI_GAS_SMBUS: 10860786Sps printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->address, 10960786Sps gas->bit_offset, gas->bit_width); 11060786Sps break; 111161475Sdelphij case ACPI_GAS_FIXED: 112161475Sdelphij default: 11360786Sps printf("0x%08lx (?)", (u_long)gas->address); 11460786Sps break; 115161475Sdelphij } 116161475Sdelphij} 117161475Sdelphij 11860786Spsstatic void 119161475Sdelphijacpi_handle_fadt(struct FADTbody *fadt) 120170256Sdelphij{ 12160786Sps struct ACPIsdt *dsdp; 122170256Sdelphij struct FACSbody *facs; 123170256Sdelphij 124161475Sdelphij acpi_print_fadt(fadt); 125161475Sdelphij 126161475Sdelphij /* 127161475Sdelphij * My T23 is revision 2 but the 64 bit addresses are invalid. 128161475Sdelphij * If revision 2 and the 32 bit address is non-zero but the 32 129161475Sdelphij * and 64 bit versions don't match, prefer the 32 bit version. 13060786Sps */ 131161475Sdelphij if (addr_size == 4 || 132161475Sdelphij (addr_size == 8 && fadt->facs_ptr != 0 && 133161475Sdelphij (fadt->x_facs_ptr & 0xffffffff) != fadt->facs_ptr)) 134161475Sdelphij facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr); 135161475Sdelphij else 136161475Sdelphij facs = (struct FACSbody *)acpi_map_sdt(fadt->x_facs_ptr); 13760786Sps if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64) 138161475Sdelphij errx(1, "FACS is corrupt"); 13960786Sps acpi_print_facs(facs); 140161475Sdelphij 14160786Sps if (addr_size == 4 || 142161475Sdelphij (addr_size == 8 && fadt->dsdt_ptr != 0 && 143161475Sdelphij (fadt->x_dsdt_ptr & 0xffffffff) != fadt->dsdt_ptr)) 14460786Sps dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 145161475Sdelphij else 146161475Sdelphij dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr); 14760786Sps if (acpi_checksum(dsdp, dsdp->len)) 148161475Sdelphij errx(1, "DSDT is corrupt"); 149161475Sdelphij acpi_print_dsdt(dsdp); 150161475Sdelphij} 151161475Sdelphij 15260786Spsstatic void 153161475Sdelphijacpi_print_cpu(u_char cpu_id) 154161475Sdelphij{ 155161475Sdelphij 156161475Sdelphij printf("\tACPI CPU="); 15760786Sps if (cpu_id == 0xff) 158161475Sdelphij printf("ALL\n"); 159161475Sdelphij else 16060786Sps printf("%d\n", (u_int)cpu_id); 161161475Sdelphij} 162161475Sdelphij 163161475Sdelphijstatic void 164161475Sdelphijacpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 165161475Sdelphij{ 166161475Sdelphij acpi_print_cpu(cpu_id); 167161475Sdelphij printf("\tFlags={"); 16860786Sps if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 16960786Sps printf("ENABLED"); 17060786Sps else 17160786Sps printf("DISABLED"); 172161475Sdelphij printf("}\n"); 173161475Sdelphij printf("\tAPIC ID=%d\n", (u_int)apic_id); 174161475Sdelphij} 175161475Sdelphij 17660786Spsstatic void 17760786Spsacpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 178161475Sdelphij{ 179161475Sdelphij printf("\tAPIC ID=%d\n", (u_int)apic_id); 180161475Sdelphij printf("\tINT BASE=%d\n", int_base); 18160786Sps printf("\tADDR=0x%016jx\n", apic_addr); 18260786Sps} 183161475Sdelphij 18460786Spsstatic void 18560786Spsacpi_print_mps_flags(u_int16_t flags) 186161475Sdelphij{ 187161475Sdelphij 188161475Sdelphij printf("\tFlags={Polarity="); 18960786Sps switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 19060786Sps case MPS_INT_FLAG_POLARITY_CONFORM: 19160786Sps printf("conforming"); 192161475Sdelphij break; 193161475Sdelphij case MPS_INT_FLAG_POLARITY_HIGH: 194161475Sdelphij printf("active-hi"); 19560786Sps break; 19660786Sps case MPS_INT_FLAG_POLARITY_LOW: 197161475Sdelphij printf("active-lo"); 198170256Sdelphij break; 199170256Sdelphij default: 20060786Sps printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 201161475Sdelphij break; 202161475Sdelphij } 20360786Sps printf(", Trigger="); 20463128Sps switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 205161475Sdelphij case MPS_INT_FLAG_TRIGGER_CONFORM: 206161475Sdelphij printf("conforming"); 207161475Sdelphij break; 20863128Sps case MPS_INT_FLAG_TRIGGER_EDGE: 20960786Sps printf("edge"); 21060786Sps break; 21160786Sps case MPS_INT_FLAG_TRIGGER_LEVEL: 212161475Sdelphij printf("level"); 21360786Sps break; 21460786Sps default: 215161475Sdelphij printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 216161475Sdelphij } 217161475Sdelphij printf("}\n"); 218161475Sdelphij} 21960786Sps 22060786Spsstatic void 221161475Sdelphijacpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 222161475Sdelphij{ 223161475Sdelphij 22460786Sps printf("\tINTR=%d\n", (u_int)intr); 22560786Sps acpi_print_mps_flags(mps_flags); 22660786Sps} 22760786Sps 22860786Spsconst char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 22960786Sps "Local NMI", "Local APIC Override", "IO SAPIC", 23060786Sps "Local SAPIC", "Platform Interrupt" }; 23160786Spsconst char *platform_int_types[] = { "PMI", "INIT", 23260786Sps "Corrected Platform Error" }; 23360786Sps 23460786Spsstatic void 23560786Spsacpi_print_apic(struct MADT_APIC *mp) 236161475Sdelphij{ 237161475Sdelphij 238161475Sdelphij printf("\tType=%s\n", apic_types[mp->type]); 239161475Sdelphij switch (mp->type) { 240161475Sdelphij case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 241161475Sdelphij acpi_print_local_apic(mp->body.local_apic.cpu_id, 242161475Sdelphij mp->body.local_apic.apic_id, mp->body.local_apic.flags); 243161475Sdelphij break; 24460786Sps case ACPI_MADT_APIC_TYPE_IO_APIC: 245161475Sdelphij acpi_print_io_apic(mp->body.io_apic.apic_id, 24660786Sps mp->body.io_apic.int_base, 247161475Sdelphij mp->body.io_apic.apic_addr); 248161475Sdelphij break; 24960786Sps case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 250161475Sdelphij printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 251161475Sdelphij printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 25260786Sps acpi_print_intr(mp->body.int_override.intr, 253161475Sdelphij mp->body.int_override.mps_flags); 254161475Sdelphij break; 255161475Sdelphij case ACPI_MADT_APIC_TYPE_NMI: 256161475Sdelphij acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 257161475Sdelphij break; 258161475Sdelphij case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 25960786Sps acpi_print_cpu(mp->body.local_nmi.cpu_id); 26060786Sps printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 261161475Sdelphij acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 262161475Sdelphij break; 263161475Sdelphij case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 264161475Sdelphij printf("\tLocal APIC ADDR=0x%016jx\n", 265161475Sdelphij mp->body.local_apic_override.apic_addr); 266161475Sdelphij break; 267161475Sdelphij case ACPI_MADT_APIC_TYPE_IO_SAPIC: 268161475Sdelphij acpi_print_io_apic(mp->body.io_sapic.apic_id, 269161475Sdelphij mp->body.io_sapic.int_base, 270161475Sdelphij mp->body.io_sapic.apic_addr); 271161475Sdelphij break; 272161475Sdelphij case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 273161475Sdelphij acpi_print_local_apic(mp->body.local_sapic.cpu_id, 274161475Sdelphij mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 275161475Sdelphij printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 27660786Sps break; 27760786Sps case ACPI_MADT_APIC_TYPE_INT_SRC: 278161475Sdelphij printf("\tType=%s\n", 279161475Sdelphij platform_int_types[mp->body.int_src.type]); 280161475Sdelphij printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 28160786Sps printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 282161475Sdelphij printf("\tSAPIC Vector=%d\n", 283161475Sdelphij (u_int)mp->body.int_src.sapic_vector); 284161475Sdelphij acpi_print_intr(mp->body.int_src.intr, 28560786Sps mp->body.int_src.mps_flags); 286161475Sdelphij break; 287161475Sdelphij default: 28860786Sps printf("\tUnknown type %d\n", (u_int)mp->type); 289161475Sdelphij break; 290161475Sdelphij } 29160786Sps} 29260786Sps 29360786Spsstatic void 294161475Sdelphijacpi_handle_apic(struct ACPIsdt *sdp) 295161475Sdelphij{ 29660786Sps struct MADTbody *madtp; 297161475Sdelphij struct MADT_APIC *madt_apicp; 298161475Sdelphij 29960786Sps printf(BEGIN_COMMENT); 30089019Sps acpi_print_sdt(sdp); 301161475Sdelphij madtp = (struct MADTbody *) sdp->body; 302161475Sdelphij printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 303161475Sdelphij printf("\tFlags={"); 304161475Sdelphij if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 305161475Sdelphij printf("PC-AT"); 30660786Sps printf("}\n"); 307161475Sdelphij madt_apicp = (struct MADT_APIC *)madtp->body; 308161475Sdelphij while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 309161475Sdelphij printf("\n"); 310161475Sdelphij acpi_print_apic(madt_apicp); 311161475Sdelphij madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 312161475Sdelphij madt_apicp->len); 313161475Sdelphij } 314161475Sdelphij printf(END_COMMENT); 315161475Sdelphij} 31660786Sps 317161475Sdelphijstatic void 318161475Sdelphijacpi_handle_hpet(struct ACPIsdt *sdp) 319161475Sdelphij{ 320161475Sdelphij struct HPETbody *hpetp; 321161475Sdelphij 32260786Sps printf(BEGIN_COMMENT); 323161475Sdelphij acpi_print_sdt(sdp); 324161475Sdelphij hpetp = (struct HPETbody *) sdp->body; 325170256Sdelphij printf("\tHPET Number=%d\n", hpetp->hpet_number); 326170256Sdelphij printf("\tADDR=0x%08x\n", hpetp->base_addr); 32760786Sps printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 32860786Sps printf("\tComparitors=%d\n", hpetp->block_comparitors); 329161475Sdelphij printf("\tCounter Size=%d\n", hpetp->block_counter_size); 330161475Sdelphij printf("\tLegacy IRQ routing capable={"); 33160786Sps if (hpetp->block_legacy_capable) 332161475Sdelphij printf("TRUE}\n"); 333161475Sdelphij else 334161475Sdelphij printf("FALSE}\n"); 335161475Sdelphij printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 33660786Sps printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 337161475Sdelphij printf(END_COMMENT); 338161475Sdelphij} 33960786Sps 340161475Sdelphijstatic void 341161475Sdelphijacpi_handle_ecdt(struct ACPIsdt *sdp) 342161475Sdelphij{ 34360786Sps struct ECDTbody *ecdt; 344161475Sdelphij 345161475Sdelphij printf(BEGIN_COMMENT); 346161475Sdelphij acpi_print_sdt(sdp); 34760786Sps ecdt = (struct ECDTbody *) sdp->body; 348161475Sdelphij printf("\tEC_CONTROL="); 349170256Sdelphij acpi_print_gas(&ecdt->ec_control); 350161475Sdelphij printf("\n\tEC_DATA="); 35160786Sps acpi_print_gas(&ecdt->ec_data); 352170256Sdelphij printf("\n\tUID=%#x, ", ecdt->uid); 35360786Sps printf("GPE_BIT=%#x\n", ecdt->gpe_bit); 35460786Sps printf("\tEC_ID=%s\n", ecdt->ec_id); 355170256Sdelphij printf(END_COMMENT); 35660786Sps} 357161475Sdelphij 358161475Sdelphijstatic void 35960786Spsacpi_print_sdt(struct ACPIsdt *sdp) 36060786Sps{ 361161475Sdelphij printf(" "); 362161475Sdelphij acpi_print_string(sdp->signature, 4); 363161475Sdelphij printf(": Length=%d, Revision=%d, Checksum=%d,\n", 364161475Sdelphij sdp->len, sdp->rev, sdp->check); 36560786Sps printf("\tOEMID="); 36660786Sps acpi_print_string(sdp->oemid, 6); 36760786Sps printf(", OEM Table ID="); 368161475Sdelphij acpi_print_string(sdp->oemtblid, 8); 369161475Sdelphij printf(", OEM Revision=0x%x,\n", sdp->oemrev); 370161475Sdelphij printf("\tCreator ID="); 371161475Sdelphij acpi_print_string(sdp->creator, 4); 372161475Sdelphij printf(", Creator Revision=0x%x\n", sdp->crerev); 373161475Sdelphij} 374161475Sdelphij 375161475Sdelphijstatic void 37660786Spsacpi_print_rsdt(struct ACPIsdt *rsdp) 37760786Sps{ 378161475Sdelphij int i, entries; 379161475Sdelphij u_long addr; 380161475Sdelphij 381161475Sdelphij printf(BEGIN_COMMENT); 382161475Sdelphij acpi_print_sdt(rsdp); 383161475Sdelphij entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 38460786Sps printf("\tEntries={ "); 38560786Sps for (i = 0; i < entries; i++) { 386161475Sdelphij if (i > 0) 387161475Sdelphij printf(", "); 38860786Sps switch (addr_size) { 38960786Sps case 4: 390170256Sdelphij addr = le32dec((char*)rsdp->body + i * addr_size); 391161475Sdelphij break; 392170256Sdelphij case 8: 39389019Sps addr = le64dec((char*)rsdp->body + i * addr_size); 394161475Sdelphij break; 395161475Sdelphij default: 396161475Sdelphij addr = 0; 397161475Sdelphij } 398161475Sdelphij assert(addr != 0); 399161475Sdelphij printf("0x%08lx", addr); 400170256Sdelphij } 401170256Sdelphij printf(" }\n"); 402170256Sdelphij printf(END_COMMENT); 40360786Sps} 404161475Sdelphij 405170256Sdelphijstatic const char *acpi_pm_profiles[] = { 406170256Sdelphij "Unspecified", "Desktop", "Mobile", "Workstation", 40760786Sps "Enterprise Server", "SOHO Server", "Appliance PC" 40860786Sps}; 40960786Sps 410170256Sdelphijstatic void 41160786Spsacpi_print_fadt(struct FADTbody *fadt) 41260786Sps{ 41360786Sps const char *pm; 414161475Sdelphij char sep; 415161475Sdelphij 41660786Sps printf(BEGIN_COMMENT); 417161475Sdelphij printf(" FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr, 418161475Sdelphij fadt->dsdt_ptr); 419161475Sdelphij printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC"); 420161475Sdelphij if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 42160786Sps pm = "Reserved"; 422161475Sdelphij else 423161475Sdelphij pm = acpi_pm_profiles[fadt->pm_profile]; 424161475Sdelphij printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile); 425161475Sdelphij printf("\tSCI_INT=%d\n", fadt->sci_int); 42660786Sps printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd); 42760786Sps printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable); 42860786Sps printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable); 42960786Sps printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq); 43060786Sps printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt); 431170256Sdelphij printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 432161475Sdelphij fadt->pm1a_evt_blk, 433161475Sdelphij fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1); 434161475Sdelphij if (fadt->pm1b_evt_blk != 0) 43560786Sps printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 43660786Sps fadt->pm1b_evt_blk, 437161475Sdelphij fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1); 438161475Sdelphij printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 439161475Sdelphij fadt->pm1a_cnt_blk, 440161475Sdelphij fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1); 44160786Sps if (fadt->pm1b_cnt_blk != 0) 442170256Sdelphij printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 443170256Sdelphij fadt->pm1b_cnt_blk, 444161475Sdelphij fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1); 445161475Sdelphij if (fadt->pm2_cnt_blk != 0) 446170256Sdelphij printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 447170256Sdelphij fadt->pm2_cnt_blk, 448161475Sdelphij fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1); 449161475Sdelphij printf("\tPM_TMR_BLK=0x%x-0x%x\n", 45063128Sps fadt->pm_tmr_blk, 45160786Sps fadt->pm_tmr_blk + fadt->pm_tmr_len - 1); 452161475Sdelphij if (fadt->gpe0_blk != 0) 453161475Sdelphij printf("\tGPE0_BLK=0x%x-0x%x\n", 454161475Sdelphij fadt->gpe0_blk, 455161475Sdelphij fadt->gpe0_blk + fadt->gpe0_len - 1); 456161475Sdelphij if (fadt->gpe1_blk != 0) 457161475Sdelphij printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 458161475Sdelphij fadt->gpe1_blk, 459161475Sdelphij fadt->gpe1_blk + fadt->gpe1_len - 1, 460128345Stjr fadt->gpe1_base); 46160786Sps if (fadt->cst_cnt != 0) 46260786Sps printf("\tCST_CNT=0x%x\n", fadt->cst_cnt); 463161475Sdelphij printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n", 464161475Sdelphij fadt->p_lvl2_lat, fadt->p_lvl3_lat); 465161475Sdelphij printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 46660786Sps fadt->flush_size, fadt->flush_stride); 46760786Sps printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 468170256Sdelphij fadt->duty_off, fadt->duty_width); 46960786Sps printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 47060786Sps fadt->day_alrm, fadt->mon_alrm, fadt->century); 471161475Sdelphij 472170256Sdelphij#define PRINTFLAG(var, flag) do { \ 473161475Sdelphij if ((var) & FADT_FLAG_## flag) { \ 474170256Sdelphij printf("%c%s", sep, #flag); sep = ','; \ 475128345Stjr } \ 47660786Sps} while (0) 477170256Sdelphij 478170256Sdelphij printf("\tIAPC_BOOT_ARCH="); 479170256Sdelphij sep = '{'; 480170256Sdelphij PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV); 481170256Sdelphij PRINTFLAG(fadt->iapc_boot_arch, 8042); 482170256Sdelphij if (fadt->iapc_boot_arch != 0) 483170256Sdelphij printf("}\n"); 484170256Sdelphij 48560786Sps printf("\tFlags="); 486128345Stjr sep = '{'; 487170256Sdelphij PRINTFLAG(fadt->flags, WBINVD); 488170256Sdelphij PRINTFLAG(fadt->flags, WBINVD_FLUSH); 489161475Sdelphij PRINTFLAG(fadt->flags, PROC_C1); 49063128Sps PRINTFLAG(fadt->flags, P_LVL2_UP); 49189019Sps PRINTFLAG(fadt->flags, PWR_BUTTON); 492170256Sdelphij PRINTFLAG(fadt->flags, SLP_BUTTON); 493161475Sdelphij PRINTFLAG(fadt->flags, FIX_RTC); 49460786Sps PRINTFLAG(fadt->flags, RTC_S4); 49563128Sps PRINTFLAG(fadt->flags, TMR_VAL_EXT); 496161475Sdelphij PRINTFLAG(fadt->flags, DCK_CAP); 497170256Sdelphij PRINTFLAG(fadt->flags, RESET_REG); 498170256Sdelphij PRINTFLAG(fadt->flags, SEALED_CASE); 499170256Sdelphij PRINTFLAG(fadt->flags, HEADLESS); 500170256Sdelphij PRINTFLAG(fadt->flags, CPU_SW_SLP); 50160786Sps if (fadt->flags != 0) 50260786Sps printf("}\n"); 503170256Sdelphij 504161475Sdelphij#undef PRINTFLAG 50560786Sps 50660786Sps if (fadt->flags & FADT_FLAG_RESET_REG) { 507170256Sdelphij printf("\tRESET_REG="); 508161475Sdelphij acpi_print_gas(&fadt->reset_reg); 509161475Sdelphij printf(", RESET_VALUE=%#x\n", fadt->reset_value); 510170256Sdelphij } 511161475Sdelphij if (addr_size == 8) { 51260786Sps printf("\tX_FACS=0x%08lx, ", (u_long)fadt->x_facs_ptr); 51360786Sps printf("X_DSDT=0x%08lx\n", (u_long)fadt->x_dsdt_ptr); 514161475Sdelphij printf("\tX_PM1a_EVT_BLK="); 515161475Sdelphij acpi_print_gas(&fadt->x_pm1a_evt_blk); 51660786Sps if (fadt->x_pm1b_evt_blk.address != 0) { 517170256Sdelphij printf("\n\tX_PM1b_EVT_BLK="); 518161475Sdelphij acpi_print_gas(&fadt->x_pm1b_evt_blk); 519170256Sdelphij } 520161475Sdelphij printf("\n\tX_PM1a_CNT_BLK="); 521161475Sdelphij acpi_print_gas(&fadt->x_pm1a_cnt_blk); 52260786Sps if (fadt->x_pm1b_cnt_blk.address != 0) { 52360786Sps printf("\n\tX_PM1b_CNT_BLK="); 524161475Sdelphij acpi_print_gas(&fadt->x_pm1b_cnt_blk); 525161475Sdelphij } 526161475Sdelphij if (fadt->x_pm1b_cnt_blk.address != 0) { 527161475Sdelphij printf("\n\tX_PM2_CNT_BLK="); 528161475Sdelphij acpi_print_gas(&fadt->x_pm2_cnt_blk); 52960786Sps } 53060786Sps printf("\n\tX_PM_TMR_BLK="); 531161475Sdelphij acpi_print_gas(&fadt->x_pm_tmr_blk); 532161475Sdelphij if (fadt->x_gpe0_blk.address != 0) { 53360786Sps printf("\n\tX_GPE0_BLK="); 534170256Sdelphij acpi_print_gas(&fadt->x_gpe0_blk); 535161475Sdelphij } 536161475Sdelphij if (fadt->x_gpe1_blk.address != 0) { 537161475Sdelphij printf("\n\tX_GPE1_BLK="); 538170256Sdelphij acpi_print_gas(&fadt->x_gpe1_blk); 539170256Sdelphij } 540161475Sdelphij printf("\n"); 541161475Sdelphij } 542170256Sdelphij 543170256Sdelphij printf(END_COMMENT); 544170256Sdelphij} 545170256Sdelphij 546170256Sdelphijstatic void 547170256Sdelphijacpi_print_facs(struct FACSbody *facs) 548170256Sdelphij{ 549170256Sdelphij printf(BEGIN_COMMENT); 550170256Sdelphij printf(" FACS:\tLength=%u, ", facs->len); 551170256Sdelphij printf("HwSig=0x%08x, ", facs->hw_sig); 552170256Sdelphij printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec); 55360786Sps 55463128Sps printf("\tGlobal_Lock="); 555161475Sdelphij if (facs->global_lock != 0) { 556161475Sdelphij if (facs->global_lock & FACS_FLAG_LOCK_PENDING) 557161475Sdelphij printf("PENDING,"); 558161475Sdelphij if (facs->global_lock & FACS_FLAG_LOCK_OWNED) 55963128Sps printf("OWNED"); 560170256Sdelphij } 561170256Sdelphij printf("\n"); 562161475Sdelphij 563161475Sdelphij printf("\tFlags="); 564161475Sdelphij if (facs->flags & FACS_FLAG_S4BIOS_F) 565170256Sdelphij printf("S4BIOS"); 56660786Sps printf("\n"); 567161475Sdelphij 568170256Sdelphij if (facs->x_firm_wake_vec != 0) { 569161475Sdelphij printf("\tX_Firm_Wake_Vec=%08lx\n", 570170256Sdelphij (u_long)facs->x_firm_wake_vec); 571161475Sdelphij } 572161475Sdelphij printf("\tVersion=%u\n", facs->version); 573128345Stjr 574161475Sdelphij printf(END_COMMENT); 575170256Sdelphij} 576161475Sdelphij 577161475Sdelphijstatic void 578128345Stjracpi_print_dsdt(struct ACPIsdt *dsdp) 57960786Sps{ 580170256Sdelphij printf(BEGIN_COMMENT); 581170256Sdelphij acpi_print_sdt(dsdp); 58260786Sps printf(END_COMMENT); 58360786Sps} 584170256Sdelphij 58560786Spsint 58660786Spsacpi_checksum(void *p, size_t length) 587161475Sdelphij{ 588170256Sdelphij u_int8_t *bp; 589161475Sdelphij u_int8_t sum; 590161475Sdelphij 591161475Sdelphij bp = p; 592161475Sdelphij sum = 0; 593161475Sdelphij while (length--) 594161475Sdelphij sum += *bp++; 59560786Sps 596128345Stjr return (sum); 597161475Sdelphij} 598161475Sdelphij 59960786Spsstatic struct ACPIsdt * 600170256Sdelphijacpi_map_sdt(vm_offset_t pa) 601170256Sdelphij{ 602161475Sdelphij struct ACPIsdt *sp; 603170256Sdelphij 604161475Sdelphij sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 60560786Sps sp = acpi_map_physical(pa, sp->len); 606170256Sdelphij return (sp); 607161475Sdelphij} 608161475Sdelphij 60960786Spsstatic void 610161475Sdelphijacpi_print_rsd_ptr(struct ACPIrsdp *rp) 611170256Sdelphij{ 612161475Sdelphij printf(BEGIN_COMMENT); 613170256Sdelphij printf(" RSD PTR: OEM="); 61463128Sps acpi_print_string(rp->oem, 6); 615170256Sdelphij printf(", ACPI_Rev=%s (%d)\n", rp->revision < 2 ? "1.0x" : "2.0x", 616161475Sdelphij rp->revision); 617170256Sdelphij if (rp->revision < 2) { 618170256Sdelphij printf("\tRSDT=0x%08x, cksum=%u\n", rp->rsdt_addr, rp->sum); 61963128Sps } else { 620170256Sdelphij printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n", 621161475Sdelphij (u_long)rp->xsdt_addr, rp->length, rp->xsum); 622161475Sdelphij } 623170256Sdelphij printf(END_COMMENT); 624161475Sdelphij} 625161475Sdelphij 626161475Sdelphijstatic void 627161475Sdelphijacpi_handle_rsdt(struct ACPIsdt *rsdp) 628161475Sdelphij{ 629161475Sdelphij struct ACPIsdt *sdp; 630161475Sdelphij vm_offset_t addr; 631161475Sdelphij int entries, i; 632161475Sdelphij 63360786Sps acpi_print_rsdt(rsdp); 63460786Sps entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 635161475Sdelphij for (i = 0; i < entries; i++) { 636161475Sdelphij switch (addr_size) { 637161475Sdelphij case 4: 638161475Sdelphij addr = le32dec((char*)rsdp->body + i * addr_size); 639161475Sdelphij break; 640161475Sdelphij case 8: 64160786Sps addr = le64dec((char*)rsdp->body + i * addr_size); 642128345Stjr break; 643161475Sdelphij default: 644161475Sdelphij assert((addr = 0)); 645128345Stjr } 646128345Stjr 647161475Sdelphij sdp = (struct ACPIsdt *)acpi_map_sdt(addr); 648161475Sdelphij if (acpi_checksum(sdp, sdp->len)) 649161475Sdelphij errx(1, "RSDT entry %d is corrupt", i); 650170256Sdelphij if (!memcmp(sdp->signature, "FACP", 4)) 651161475Sdelphij acpi_handle_fadt((struct FADTbody *) sdp->body); 652161475Sdelphij else if (!memcmp(sdp->signature, "APIC", 4)) 653161475Sdelphij acpi_handle_apic(sdp); 654161475Sdelphij else if (!memcmp(sdp->signature, "HPET", 4)) 65560786Sps acpi_handle_hpet(sdp); 65663128Sps else if (!memcmp(sdp->signature, "ECDT", 4)) 657161475Sdelphij acpi_handle_ecdt(sdp); 658161475Sdelphij else { 659161475Sdelphij printf(BEGIN_COMMENT); 660161475Sdelphij acpi_print_sdt(sdp); 66163128Sps printf(END_COMMENT); 66263128Sps } 66363128Sps } 664161475Sdelphij} 665161475Sdelphij 666161475Sdelphijstruct ACPIsdt * 667170256Sdelphijsdt_load_devmem() 668161475Sdelphij{ 669161475Sdelphij struct ACPIrsdp *rp; 670170256Sdelphij struct ACPIsdt *rsdp; 671161475Sdelphij 672161475Sdelphij rp = acpi_find_rsd_ptr(); 673161475Sdelphij if (!rp) 67460786Sps errx(1, "Can't find ACPI information"); 67560786Sps 676161475Sdelphij if (tflag) 677170256Sdelphij acpi_print_rsd_ptr(rp); 67860786Sps if (rp->revision < 2) { 67960786Sps rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 680161475Sdelphij if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 681161475Sdelphij acpi_checksum(rsdp, rsdp->len) != 0) 682161475Sdelphij errx(1, "RSDT is corrupted"); 683161475Sdelphij addr_size = sizeof(uint32_t); 68460786Sps } else { 685170256Sdelphij rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr); 686161475Sdelphij if (memcmp(rsdp->signature, "XSDT", 4) != 0 || 687161475Sdelphij acpi_checksum(rsdp, rsdp->len) != 0) 688161475Sdelphij errx(1, "XSDT is corrupted"); 689170256Sdelphij addr_size = sizeof(uint64_t); 690161475Sdelphij } 691161475Sdelphij return (rsdp); 692170256Sdelphij} 693161475Sdelphij 694170256Sdelphijvoid 695161475Sdelphijdsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 696170256Sdelphij{ 69760786Sps int fd; 698170256Sdelphij mode_t mode; 69989019Sps 70060786Sps assert(outfile != NULL); 70189019Sps mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 702161475Sdelphij fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 703161475Sdelphij if (fd == -1) { 704161475Sdelphij perror("dsdt_save_file"); 70560786Sps return; 70689019Sps } 707161475Sdelphij write(fd, dsdp, SIZEOF_SDT_HDR); 708161475Sdelphij write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 709161475Sdelphij close(fd); 71060786Sps} 711161475Sdelphij 712161475Sdelphijvoid 713161475Sdelphijaml_disassemble(struct ACPIsdt *dsdp) 714161475Sdelphij{ 715161475Sdelphij char tmpstr[32], buf[256]; 716161475Sdelphij FILE *fp; 717161475Sdelphij int fd, len; 718161475Sdelphij 719161475Sdelphij strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 720161475Sdelphij fd = mkstemp(tmpstr); 721161475Sdelphij if (fd < 0) { 72260786Sps perror("iasl tmp file"); 72360786Sps return; 724170256Sdelphij } 72560786Sps 72660786Sps /* Dump DSDT to the temp file */ 727161475Sdelphij write(fd, dsdp, SIZEOF_SDT_HDR); 728161475Sdelphij write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 729161475Sdelphij close(fd); 730161475Sdelphij 731161475Sdelphij /* Run iasl -d on the temp file */ 732161475Sdelphij if (fork() == 0) { 733161475Sdelphij close(STDOUT_FILENO); 73460786Sps if (vflag == 0) 73560786Sps close(STDERR_FILENO); 736161475Sdelphij execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 737161475Sdelphij err(1, "exec"); 73860786Sps } 739170256Sdelphij 740170256Sdelphij wait(NULL); 741170256Sdelphij unlink(tmpstr); 742170256Sdelphij 743170256Sdelphij /* Dump iasl's output to stdout */ 744170256Sdelphij fp = fopen("acpidump.dsl", "r"); 745170256Sdelphij unlink("acpidump.dsl"); 74660786Sps if (fp == NULL) { 74789019Sps perror("iasl tmp file (read)"); 748161475Sdelphij return; 749161475Sdelphij } 750161475Sdelphij while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 751161475Sdelphij fwrite(buf, 1, len, stdout); 75260786Sps fclose(fp); 75389019Sps} 754161475Sdelphij 755161475Sdelphijvoid 756161475Sdelphijsdt_print_all(struct ACPIsdt *rsdp) 75760786Sps{ 758170256Sdelphij acpi_handle_rsdt(rsdp); 759161475Sdelphij} 760170256Sdelphij 761161475Sdelphij/* Fetch a table matching the given signature via the RSDT */ 762161475Sdelphijstruct ACPIsdt * 76389019Spssdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 76460786Sps{ 765170256Sdelphij struct ACPIsdt *sdt; 766170256Sdelphij vm_offset_t addr; 767161475Sdelphij int entries, i; 768161475Sdelphij 769170256Sdelphij entries = (rsdt->len - SIZEOF_SDT_HDR) / addr_size; 770170256Sdelphij for (i = 0; i < entries; i++) { 771170256Sdelphij switch (addr_size) { 772170256Sdelphij case 4: 773170256Sdelphij addr = le32dec((char*)rsdt->body + i * addr_size); 77463128Sps break; 775170256Sdelphij case 8: 776161475Sdelphij addr = le64dec((char*)rsdt->body + i * addr_size); 777161475Sdelphij break; 778161475Sdelphij default: 779161475Sdelphij assert((addr = 0)); 780161475Sdelphij } 781161475Sdelphij sdt = (struct ACPIsdt *)acpi_map_sdt(addr); 782161475Sdelphij if (memcmp(sdt->signature, sig, strlen(sig))) 783161475Sdelphij continue; 784161475Sdelphij if (acpi_checksum(sdt, sdt->len)) 785161475Sdelphij errx(1, "RSDT entry %d is corrupt", i); 786161475Sdelphij return (sdt); 787161475Sdelphij } 78860786Sps 789128345Stjr return (NULL); 790161475Sdelphij} 791161475Sdelphij 792161475Sdelphijstruct ACPIsdt * 79360786Spsdsdt_from_fadt(struct FADTbody *fadt) 79463128Sps{ 795161475Sdelphij struct ACPIsdt *sdt; 796161475Sdelphij 797161475Sdelphij /* Use the DSDT address if it is valid and version 1, else X_DSDT */ 798161475Sdelphij if (addr_size == 4 || 79963128Sps (addr_size == 8 && fadt->dsdt_ptr != 0 && 800161475Sdelphij (fadt->x_dsdt_ptr & 0xffffffff) != fadt->dsdt_ptr)) 801161475Sdelphij sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 802161475Sdelphij else 803161475Sdelphij sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr); 80460786Sps if (acpi_checksum(sdt, sdt->len)) 805170256Sdelphij errx(1, "DSDT is corrupt\n"); 806170256Sdelphij return (sdt); 807170256Sdelphij} 808161475Sdelphij