acpi.c revision 119912
165285Siwasaki/*- 265285Siwasaki * Copyright (c) 1998 Doug Rabson 365285Siwasaki * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 465285Siwasaki * All rights reserved. 565285Siwasaki * 665285Siwasaki * Redistribution and use in source and binary forms, with or without 765285Siwasaki * modification, are permitted provided that the following conditions 865285Siwasaki * are met: 965285Siwasaki * 1. Redistributions of source code must retain the above copyright 1065285Siwasaki * notice, this list of conditions and the following disclaimer. 1165285Siwasaki * 2. Redistributions in binary form must reproduce the above copyright 1265285Siwasaki * notice, this list of conditions and the following disclaimer in the 1365285Siwasaki * documentation and/or other materials provided with the distribution. 1465285Siwasaki * 1565285Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1665285Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1765285Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1865285Siwasaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1965285Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2065285Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2165285Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2265285Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2365285Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2465285Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2565285Siwasaki * SUCH DAMAGE. 2665285Siwasaki * 2765285Siwasaki * $FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 119912 2003-09-09 08:31:58Z njl $ 2865285Siwasaki */ 2965285Siwasaki 30119515Snjl#include <sys/types.h> 3165285Siwasaki#include <sys/param.h> 3265285Siwasaki#include <sys/stat.h> 33119515Snjl#include <sys/wait.h> 3465285Siwasaki#include <assert.h> 3565285Siwasaki#include <err.h> 3665285Siwasaki#include <fcntl.h> 3765285Siwasaki#include <stdio.h> 38119515Snjl#include <string.h> 3965285Siwasaki#include <unistd.h> 4065285Siwasaki 4165285Siwasaki#include "acpidump.h" 4265285Siwasaki 4385323Siwasaki#define BEGIN_COMMENT "/*\n" 4485323Siwasaki#define END_COMMENT " */\n" 4585323Siwasaki 46119515Snjlstatic void acpi_print_string(char *s, size_t length); 47119912Snjlstatic void acpi_print_gas(struct ACPIgas *gas); 48119912Snjlstatic void acpi_handle_fadt(struct FADTbody *fadt); 49119515Snjlstatic void acpi_print_cpu(u_char cpu_id); 50119515Snjlstatic void acpi_print_local_apic(u_char cpu_id, u_char apic_id, 51119515Snjl u_int32_t flags); 52119515Snjlstatic void acpi_print_io_apic(u_char apic_id, u_int32_t int_base, 53119515Snjl u_int64_t apic_addr); 54119515Snjlstatic void acpi_print_mps_flags(u_int16_t flags); 55119515Snjlstatic void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags); 56119515Snjlstatic void acpi_print_apic(struct MADT_APIC *mp); 57119515Snjlstatic void acpi_handle_apic(struct ACPIsdt *sdp); 58119515Snjlstatic void acpi_handle_hpet(struct ACPIsdt *sdp); 59119515Snjlstatic void acpi_print_sdt(struct ACPIsdt *sdp, int endcomment); 60119912Snjlstatic void acpi_print_fadt(struct FADTbody *fadt); 61119912Snjlstatic void acpi_print_facs(struct FACSbody *facs); 62119515Snjlstatic void acpi_print_dsdt(struct ACPIsdt *dsdp); 63119515Snjlstatic struct ACPIsdt * 64119515Snjl acpi_map_sdt(vm_offset_t pa); 65119515Snjlstatic void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 66119515Snjlstatic void acpi_handle_rsdt(struct ACPIsdt *rsdp); 6785323Siwasaki 6865285Siwasakistatic void 6965285Siwasakiacpi_print_string(char *s, size_t length) 7065285Siwasaki{ 7165285Siwasaki int c; 7265285Siwasaki 7365285Siwasaki /* Trim trailing spaces and NULLs */ 7465285Siwasaki while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 7565285Siwasaki length--; 7665285Siwasaki 7765285Siwasaki while (length--) { 7865285Siwasaki c = *s++; 7965285Siwasaki putchar(c); 8065285Siwasaki } 8165285Siwasaki} 8265285Siwasaki 8365285Siwasakistatic void 84119912Snjlacpi_print_gas(struct ACPIgas *gas) 8565285Siwasaki{ 86119912Snjl switch(gas->address_space_id) { 87119912Snjl case ACPI_GAS_MEMORY: 88119912Snjl printf("0x%08lx:%u[%u] (Memory)\n", (u_long)gas->address, 89119912Snjl gas->bit_offset, gas->bit_width); 90119912Snjl break; 91119912Snjl case ACPI_GAS_IO: 92119912Snjl printf("0x%08lx:%u[%u] (IO)\n", (u_long)gas->address, 93119912Snjl gas->bit_offset, gas->bit_width); 94119912Snjl break; 95119912Snjl case ACPI_GAS_PCI: 96119912Snjl printf("%x:%x+%#x (PCI)\n", (uint16_t)(gas->address >> 32), 97119912Snjl (uint16_t)((gas->address >> 16) & 0xffff), 98119912Snjl (uint16_t)gas->address); 99119912Snjl break; 100119912Snjl /* XXX How to handle these below? */ 101119912Snjl case ACPI_GAS_EMBEDDED: 102119912Snjl printf("0x%#x:%u[%u] (EC)\n", (uint16_t)gas->address, 103119912Snjl gas->bit_offset, gas->bit_width); 104119912Snjl break; 105119912Snjl case ACPI_GAS_SMBUS: 106119912Snjl printf("0x%#x:%u[%u] (SMBus)\n", (uint16_t)gas->address, 107119912Snjl gas->bit_offset, gas->bit_width); 108119912Snjl break; 109119912Snjl case ACPI_GAS_FIXED: 110119912Snjl default: 111119912Snjl printf("0x%08lx (?)\n", (u_long)gas->address); 112119912Snjl break; 113119912Snjl } 114119912Snjl} 11565285Siwasaki 116119912Snjlstatic void 117119912Snjlacpi_handle_fadt(struct FADTbody *fadt) 118119912Snjl{ 119119912Snjl struct ACPIsdt *dsdp; 120119912Snjl struct FACSbody *facs; 121119912Snjl 122119912Snjl acpi_print_fadt(fadt); 123119912Snjl 124119912Snjl facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr); 125119912Snjl if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64) 126119912Snjl errx(1, "FACS is corrupt"); 127119912Snjl acpi_print_facs(facs); 128119912Snjl 129119912Snjl dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 13065285Siwasaki if (acpi_checksum(dsdp, dsdp->len)) 131119515Snjl errx(1, "DSDT is corrupt"); 132119515Snjl acpi_print_dsdt(dsdp); 13365285Siwasaki} 13465285Siwasaki 13585323Siwasakistatic void 136108967Sjhbacpi_print_cpu(u_char cpu_id) 137108967Sjhb{ 138108967Sjhb 139108967Sjhb printf("\tACPI CPU="); 140108967Sjhb if (cpu_id == 0xff) 141108967Sjhb printf("ALL\n"); 142108967Sjhb else 143108967Sjhb printf("%d\n", (u_int)cpu_id); 144108967Sjhb} 145108967Sjhb 146108967Sjhbstatic void 147108967Sjhbacpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 148108967Sjhb{ 149108967Sjhb acpi_print_cpu(cpu_id); 150108967Sjhb printf("\tFlags={"); 151108967Sjhb if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 152108967Sjhb printf("ENABLED"); 153108967Sjhb else 154108967Sjhb printf("DISABLED"); 155108967Sjhb printf("}\n"); 156108967Sjhb printf("\tAPIC ID=%d\n", (u_int)apic_id); 157108967Sjhb} 158108967Sjhb 159108967Sjhbstatic void 160108967Sjhbacpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 161108967Sjhb{ 162108967Sjhb printf("\tAPIC ID=%d\n", (u_int)apic_id); 163108967Sjhb printf("\tINT BASE=%d\n", int_base); 164119515Snjl printf("\tADDR=0x%016jx\n", apic_addr); 165108967Sjhb} 166108967Sjhb 167108967Sjhbstatic void 168108967Sjhbacpi_print_mps_flags(u_int16_t flags) 169108967Sjhb{ 170108967Sjhb 171108967Sjhb printf("\tFlags={Polarity="); 172108967Sjhb switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 173108967Sjhb case MPS_INT_FLAG_POLARITY_CONFORM: 174108967Sjhb printf("conforming"); 175108967Sjhb break; 176108967Sjhb case MPS_INT_FLAG_POLARITY_HIGH: 177108967Sjhb printf("active-hi"); 178108967Sjhb break; 179108967Sjhb case MPS_INT_FLAG_POLARITY_LOW: 180108967Sjhb printf("active-lo"); 181108967Sjhb break; 182108967Sjhb default: 183108967Sjhb printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 184108967Sjhb break; 185108967Sjhb } 186108967Sjhb printf(", Trigger="); 187108967Sjhb switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 188108967Sjhb case MPS_INT_FLAG_TRIGGER_CONFORM: 189108967Sjhb printf("conforming"); 190108967Sjhb break; 191108967Sjhb case MPS_INT_FLAG_TRIGGER_EDGE: 192108967Sjhb printf("edge"); 193108967Sjhb break; 194108967Sjhb case MPS_INT_FLAG_TRIGGER_LEVEL: 195108967Sjhb printf("level"); 196108967Sjhb break; 197108967Sjhb default: 198108967Sjhb printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 199108967Sjhb } 200108967Sjhb printf("}\n"); 201108967Sjhb} 202108967Sjhb 203108967Sjhbstatic void 204108967Sjhbacpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 205108967Sjhb{ 206108967Sjhb 207108967Sjhb printf("\tINTR=%d\n", (u_int)intr); 208108967Sjhb acpi_print_mps_flags(mps_flags); 209108967Sjhb} 210108967Sjhb 211108967Sjhbconst char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 212108967Sjhb "Local NMI", "Local APIC Override", "IO SAPIC", 213108967Sjhb "Local SAPIC", "Platform Interrupt" }; 214108967Sjhbconst char *platform_int_types[] = { "PMI", "INIT", 215108967Sjhb "Corrected Platform Error" }; 216108967Sjhb 217108967Sjhbstatic void 218108967Sjhbacpi_print_apic(struct MADT_APIC *mp) 219108967Sjhb{ 220108967Sjhb 221108967Sjhb printf("\tType=%s\n", apic_types[mp->type]); 222108967Sjhb switch (mp->type) { 223108967Sjhb case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 224108967Sjhb acpi_print_local_apic(mp->body.local_apic.cpu_id, 225108967Sjhb mp->body.local_apic.apic_id, mp->body.local_apic.flags); 226108967Sjhb break; 227108967Sjhb case ACPI_MADT_APIC_TYPE_IO_APIC: 228108967Sjhb acpi_print_io_apic(mp->body.io_apic.apic_id, 229108967Sjhb mp->body.io_apic.int_base, 230108967Sjhb mp->body.io_apic.apic_addr); 231108967Sjhb break; 232108967Sjhb case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 233108967Sjhb printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 234108967Sjhb printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 235108967Sjhb acpi_print_intr(mp->body.int_override.intr, 236108967Sjhb mp->body.int_override.mps_flags); 237108967Sjhb break; 238108967Sjhb case ACPI_MADT_APIC_TYPE_NMI: 239108967Sjhb acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 240108967Sjhb break; 241108967Sjhb case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 242108967Sjhb acpi_print_cpu(mp->body.local_nmi.cpu_id); 243108967Sjhb printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 244108967Sjhb acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 245108967Sjhb break; 246108967Sjhb case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 247119515Snjl printf("\tLocal APIC ADDR=0x%016jx\n", 248119515Snjl mp->body.local_apic_override.apic_addr); 249108967Sjhb break; 250108967Sjhb case ACPI_MADT_APIC_TYPE_IO_SAPIC: 251108967Sjhb acpi_print_io_apic(mp->body.io_sapic.apic_id, 252108967Sjhb mp->body.io_sapic.int_base, 253108967Sjhb mp->body.io_sapic.apic_addr); 254108967Sjhb break; 255108967Sjhb case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 256108967Sjhb acpi_print_local_apic(mp->body.local_sapic.cpu_id, 257108967Sjhb mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 258108967Sjhb printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 259108967Sjhb break; 260108967Sjhb case ACPI_MADT_APIC_TYPE_INT_SRC: 261108967Sjhb printf("\tType=%s\n", 262108967Sjhb platform_int_types[mp->body.int_src.type]); 263108967Sjhb printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 264108967Sjhb printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 265108967Sjhb printf("\tSAPIC Vector=%d\n", 266108967Sjhb (u_int)mp->body.int_src.sapic_vector); 267108967Sjhb acpi_print_intr(mp->body.int_src.intr, 268108967Sjhb mp->body.int_src.mps_flags); 269108967Sjhb break; 270108967Sjhb default: 271108967Sjhb printf("\tUnknown type %d\n", (u_int)mp->type); 272119515Snjl break; 273108967Sjhb } 274108967Sjhb} 275108967Sjhb 276108967Sjhbstatic void 277108967Sjhbacpi_handle_apic(struct ACPIsdt *sdp) 278108967Sjhb{ 279108967Sjhb struct MADTbody *madtp; 280108967Sjhb struct MADT_APIC *madt_apicp; 281108967Sjhb 282119515Snjl acpi_print_sdt(sdp, /*endcomment*/0); 283108967Sjhb madtp = (struct MADTbody *) sdp->body; 284108967Sjhb printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 285108967Sjhb printf("\tFlags={"); 286108967Sjhb if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 287108967Sjhb printf("PC-AT"); 288108967Sjhb printf("}\n"); 289119515Snjl madt_apicp = (struct MADT_APIC *)madtp->body; 290108967Sjhb while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 291108967Sjhb printf("\n"); 292108967Sjhb acpi_print_apic(madt_apicp); 293108967Sjhb madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 294108967Sjhb madt_apicp->len); 295108967Sjhb } 296108967Sjhb printf(END_COMMENT); 297108967Sjhb} 298108967Sjhb 299108967Sjhbstatic void 300118334Speteracpi_handle_hpet(struct ACPIsdt *sdp) 301118334Speter{ 302118334Speter struct HPETbody *hpetp; 303118334Speter 304119515Snjl acpi_print_sdt(sdp, /*endcomment*/0); 305118334Speter hpetp = (struct HPETbody *) sdp->body; 306118334Speter printf("\tHPET Number=%d\n", hpetp->hpet_number); 307118334Speter printf("\tADDR=0x%08x\n", hpetp->base_addr); 308118334Speter printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 309118334Speter printf("\tComparitors=%d\n", hpetp->block_comparitors); 310118334Speter printf("\tCounter Size=%d\n", hpetp->block_counter_size); 311118334Speter printf("\tLegacy IRQ routing capable={"); 312118334Speter if (hpetp->block_legacy_capable) 313118334Speter printf("TRUE}\n"); 314118334Speter else 315118334Speter printf("FALSE}\n"); 316118334Speter printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 317118335Speter printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 318118334Speter printf(END_COMMENT); 319118334Speter} 320118334Speter 321118334Speterstatic void 322119515Snjlacpi_print_sdt(struct ACPIsdt *sdp, int endcomment) 32385323Siwasaki{ 324119515Snjl printf(BEGIN_COMMENT " "); 32565285Siwasaki acpi_print_string(sdp->signature, 4); 32685323Siwasaki printf(": Length=%d, Revision=%d, Checksum=%d,\n", 32765285Siwasaki sdp->len, sdp->rev, sdp->check); 32865285Siwasaki printf("\tOEMID="); 32965285Siwasaki acpi_print_string(sdp->oemid, 6); 33065285Siwasaki printf(", OEM Table ID="); 33165285Siwasaki acpi_print_string(sdp->oemtblid, 8); 33265285Siwasaki printf(", OEM Revision=0x%x,\n", sdp->oemrev); 33365285Siwasaki printf("\tCreator ID="); 33465285Siwasaki acpi_print_string(sdp->creator, 4); 33565285Siwasaki printf(", Creator Revision=0x%x\n", sdp->crerev); 336119515Snjl if (endcomment) 337119515Snjl printf(END_COMMENT); 33865285Siwasaki} 33965285Siwasaki 340119515Snjlstatic void 34165285Siwasakiacpi_print_rsdt(struct ACPIsdt *rsdp) 34265285Siwasaki{ 34365285Siwasaki int i, entries; 34465285Siwasaki 345119515Snjl acpi_print_sdt(rsdp, /*endcomment*/0); 34665285Siwasaki entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 34765285Siwasaki printf("\tEntries={ "); 34865285Siwasaki for (i = 0; i < entries; i++) { 34965285Siwasaki if (i > 0) 35065285Siwasaki printf(", "); 35165285Siwasaki printf("0x%08x", rsdp->body[i]); 35265285Siwasaki } 35365285Siwasaki printf(" }\n"); 35485323Siwasaki printf(END_COMMENT); 35565285Siwasaki} 35665285Siwasaki 357119912Snjlstatic const char *acpi_pm_profiles[] = { 358119912Snjl "Unspecified", "Desktop", "Mobile", "Workstation", 359119912Snjl "Enterprise Server", "SOHO Server", "Appliance PC" 360119912Snjl}; 361119912Snjl 362119515Snjlstatic void 363119912Snjlacpi_print_fadt(struct FADTbody *fadt) 36465285Siwasaki{ 365119912Snjl const char *pm; 366119912Snjl char sep; 36765285Siwasaki 36885323Siwasaki printf(BEGIN_COMMENT); 369119912Snjl printf(" FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr, 370119912Snjl fadt->dsdt_ptr); 371119912Snjl printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC"); 372119912Snjl if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 373119912Snjl pm = "Reserved"; 374119912Snjl else 375119912Snjl pm = acpi_pm_profiles[fadt->pm_profile]; 376119912Snjl printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile); 377119912Snjl printf("\tSCI_INT=%d\n", fadt->sci_int); 378119912Snjl printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd); 379119912Snjl printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable); 380119912Snjl printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable); 381119912Snjl printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq); 382119912Snjl printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt); 383119912Snjl if (fadt->pm1a_evt_blk != 0) 38465285Siwasaki printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 385119912Snjl fadt->pm1a_evt_blk, 386119912Snjl fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1); 387119912Snjl if (fadt->pm1b_evt_blk != 0) 38865285Siwasaki printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 389119912Snjl fadt->pm1b_evt_blk, 390119912Snjl fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1); 391119912Snjl if (fadt->pm1a_cnt_blk != 0) 39265285Siwasaki printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 393119912Snjl fadt->pm1a_cnt_blk, 394119912Snjl fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1); 395119912Snjl if (fadt->pm1b_cnt_blk != 0) 39665285Siwasaki printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 397119912Snjl fadt->pm1b_cnt_blk, 398119912Snjl fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1); 399119912Snjl if (fadt->pm2_cnt_blk != 0) 40065285Siwasaki printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 401119912Snjl fadt->pm2_cnt_blk, 402119912Snjl fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1); 403119912Snjl if (fadt->pm_tmr_blk != 0) 40465285Siwasaki printf("\tPM2_TMR_BLK=0x%x-0x%x\n", 405119912Snjl fadt->pm_tmr_blk, 406119912Snjl fadt->pm_tmr_blk + fadt->pm_tmr_len - 1); 407119912Snjl if (fadt->gpe0_blk != 0) 408119912Snjl printf("\tGPE0_BLK=0x%x-0x%x\n", 409119912Snjl fadt->gpe0_blk, 410119912Snjl fadt->gpe0_blk + fadt->gpe0_len - 1); 411119912Snjl if (fadt->gpe1_blk != 0) 412119912Snjl printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 413119912Snjl fadt->gpe1_blk, 414119912Snjl fadt->gpe1_blk + fadt->gpe1_len - 1, 415119912Snjl fadt->gpe1_base); 416119912Snjl if (fadt->cst_cnt != 0) 417119912Snjl printf("\tCST_CNT=0x%x\n", fadt->cst_cnt); 41865285Siwasaki printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 419119912Snjl fadt->p_lvl2_lat, fadt->p_lvl3_lat); 42065285Siwasaki printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 421119912Snjl fadt->flush_size, fadt->flush_stride); 42265285Siwasaki printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 423119912Snjl fadt->duty_off, fadt->duty_width); 42465285Siwasaki printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 425119912Snjl fadt->day_alrm, fadt->mon_alrm, fadt->century); 42665285Siwasaki 427119912Snjl#define PRINTFLAG(var, flag) do { \ 428119912Snjl if ((var) & FADT_FLAG_## flag) { \ 429119912Snjl printf("%c%s", sep, #flag); sep = ','; \ 430119912Snjl } \ 43165285Siwasaki} while (0) 43265285Siwasaki 433119912Snjl printf("\tIAPC_BOOT_ARCH="); 434119912Snjl sep = '{'; 435119912Snjl PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV); 436119912Snjl PRINTFLAG(fadt->iapc_boot_arch, 8042); 437119912Snjl printf("}\n"); 43865285Siwasaki 439119912Snjl printf("\tFlags="); 440119912Snjl sep = '{'; 441119912Snjl PRINTFLAG(fadt->flags, WBINVD); 442119912Snjl PRINTFLAG(fadt->flags, WBINVD_FLUSH); 443119912Snjl PRINTFLAG(fadt->flags, PROC_C1); 444119912Snjl PRINTFLAG(fadt->flags, P_LVL2_UP); 445119912Snjl PRINTFLAG(fadt->flags, PWR_BUTTON); 446119912Snjl PRINTFLAG(fadt->flags, SLP_BUTTON); 447119912Snjl PRINTFLAG(fadt->flags, FIX_RTC); 448119912Snjl PRINTFLAG(fadt->flags, RTC_S4); 449119912Snjl PRINTFLAG(fadt->flags, TMR_VAL_EXT); 450119912Snjl PRINTFLAG(fadt->flags, DCK_CAP); 451119912Snjl PRINTFLAG(fadt->flags, RESET_REG); 452119912Snjl PRINTFLAG(fadt->flags, SEALED_CASE); 453119912Snjl PRINTFLAG(fadt->flags, HEADLESS); 454119912Snjl PRINTFLAG(fadt->flags, CPU_SW_SLP); 455119912Snjl printf("}\n"); 456119912Snjl 45765285Siwasaki#undef PRINTFLAG 45865285Siwasaki 459119912Snjl if (fadt->flags & FADT_FLAG_RESET_REG) { 460119912Snjl printf("\tRESET_REG="); 461119912Snjl acpi_print_gas(&fadt->reset_reg); 462119912Snjl printf(", RESET_VALUE=%#x\n", fadt->reset_value); 463119912Snjl } 464119912Snjl 465119912Snjl printf(END_COMMENT); 466119912Snjl} 467119912Snjl 468119912Snjlstatic void 469119912Snjlacpi_print_facs(struct FACSbody *facs) 470119912Snjl{ 471119912Snjl printf(BEGIN_COMMENT); 472119912Snjl printf(" FACS:\tLength=%u, ", facs->len); 473119912Snjl printf("HwSig=0x%08x, ", facs->hw_sig); 474119912Snjl printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec); 475119912Snjl 476119912Snjl printf("\tGlobal_Lock={"); 477119912Snjl if (facs->global_lock != 0) { 478119912Snjl if (facs->global_lock & FACS_FLAG_LOCK_PENDING) 479119912Snjl printf("PENDING,"); 480119912Snjl if (facs->global_lock & FACS_FLAG_LOCK_OWNED) 481119912Snjl printf("OWNED"); 482119912Snjl } 48365285Siwasaki printf("}\n"); 484119912Snjl 485119912Snjl printf("\tFlags={"); 486119912Snjl if (facs->flags & FACS_FLAG_S4BIOS_F) 487119912Snjl printf("S4BIOS"); 488119912Snjl printf("}\n"); 489119912Snjl 490119912Snjl if (facs->x_firm_wake_vec != 0) { 491119912Snjl printf("\tX_Firm_Wake_Vec=%08lx\n", 492119912Snjl (u_long)facs->x_firm_wake_vec); 493119912Snjl } 494119912Snjl 49585323Siwasaki printf(END_COMMENT); 49665285Siwasaki} 49765285Siwasaki 498119515Snjlstatic void 49965285Siwasakiacpi_print_dsdt(struct ACPIsdt *dsdp) 50065285Siwasaki{ 501119515Snjl acpi_print_sdt(dsdp, /*endcomment*/1); 50265285Siwasaki} 50365285Siwasaki 50465285Siwasakiint 50565285Siwasakiacpi_checksum(void *p, size_t length) 50665285Siwasaki{ 50765285Siwasaki u_int8_t *bp; 50865285Siwasaki u_int8_t sum; 50965285Siwasaki 51065285Siwasaki bp = p; 51165285Siwasaki sum = 0; 51265285Siwasaki while (length--) 51365285Siwasaki sum += *bp++; 51465285Siwasaki 51565285Siwasaki return (sum); 51665285Siwasaki} 51765285Siwasaki 518119515Snjlstatic struct ACPIsdt * 51965285Siwasakiacpi_map_sdt(vm_offset_t pa) 52065285Siwasaki{ 52165285Siwasaki struct ACPIsdt *sp; 52265285Siwasaki 52365285Siwasaki sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 52465285Siwasaki sp = acpi_map_physical(pa, sp->len); 52565285Siwasaki return (sp); 52665285Siwasaki} 52765285Siwasaki 528119515Snjlstatic void 52965285Siwasakiacpi_print_rsd_ptr(struct ACPIrsdp *rp) 53065285Siwasaki{ 53165285Siwasaki 53285323Siwasaki printf(BEGIN_COMMENT); 533119515Snjl printf(" RSD PTR: Checksum=%d, OEMID=", rp->sum); 53465285Siwasaki acpi_print_string(rp->oem, 6); 535108082Smarcel printf(", RsdtAddress=0x%08x\n", rp->rsdt_addr); 53685323Siwasaki printf(END_COMMENT); 53765285Siwasaki} 53865285Siwasaki 539119515Snjlstatic void 54065285Siwasakiacpi_handle_rsdt(struct ACPIsdt *rsdp) 54165285Siwasaki{ 54265285Siwasaki int i; 54365285Siwasaki int entries; 54465285Siwasaki struct ACPIsdt *sdp; 54565285Siwasaki 54665285Siwasaki entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 54765285Siwasaki acpi_print_rsdt(rsdp); 54865285Siwasaki for (i = 0; i < entries; i++) { 549119515Snjl sdp = (struct ACPIsdt *)acpi_map_sdt(rsdp->body[i]); 55065285Siwasaki if (acpi_checksum(sdp, sdp->len)) 551119515Snjl errx(1, "RSDT entry %d is corrupt", i); 552119515Snjl if (!memcmp(sdp->signature, "FACP", 4)) 553119912Snjl acpi_handle_fadt((struct FADTbody *) sdp->body); 554119515Snjl else if (!memcmp(sdp->signature, "APIC", 4)) 555108967Sjhb acpi_handle_apic(sdp); 556119515Snjl else if (!memcmp(sdp->signature, "HPET", 4)) 557118334Speter acpi_handle_hpet(sdp); 558119515Snjl else 559119515Snjl acpi_print_sdt(sdp, /*endcomment*/1); 56065285Siwasaki } 56165285Siwasaki} 56285323Siwasaki 563119515Snjlstruct ACPIsdt * 564119515Snjlsdt_load_devmem() 56585323Siwasaki{ 566119515Snjl struct ACPIrsdp *rp; 567119515Snjl struct ACPIsdt *rsdp; 56885323Siwasaki 569119515Snjl rp = acpi_find_rsd_ptr(); 570119515Snjl if (!rp) 571119515Snjl errx(1, "Can't find ACPI information"); 572119515Snjl 573119515Snjl if (tflag) 574119515Snjl acpi_print_rsd_ptr(rp); 575119515Snjl rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 576119515Snjl if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 577119515Snjl acpi_checksum(rsdp, rsdp->len) != 0) 578119515Snjl errx(1, "RSDT is corrupted"); 579119515Snjl 580119515Snjl return (rsdp); 58185323Siwasaki} 58285323Siwasaki 583119515Snjlvoid 584119515Snjldsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 58585323Siwasaki{ 586119515Snjl int fd; 587119515Snjl mode_t mode; 58885323Siwasaki 589119515Snjl assert(outfile != NULL); 590119515Snjl mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 591119515Snjl fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 592119515Snjl if (fd == -1) { 593119515Snjl perror("dsdt_save_file"); 594119515Snjl return; 595119515Snjl } 596119515Snjl write(fd, dsdp, SIZEOF_SDT_HDR); 597119515Snjl write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 598119515Snjl close(fd); 59985323Siwasaki} 60085323Siwasaki 601119515Snjlvoid 602119515Snjlaml_disassemble(struct ACPIsdt *dsdp) 60385323Siwasaki{ 604119515Snjl char tmpstr[32], buf[256]; 605119515Snjl FILE *fp; 606119515Snjl int fd, len; 60785323Siwasaki 608119515Snjl strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 609119515Snjl fd = mkstemp(tmpstr); 610119515Snjl if (fd < 0) { 611119515Snjl perror("iasl tmp file"); 612119515Snjl return; 613119515Snjl } 614119515Snjl 615119515Snjl /* Dump DSDT to the temp file */ 616119515Snjl write(fd, dsdp, SIZEOF_SDT_HDR); 617119515Snjl write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 618119515Snjl close(fd); 619119515Snjl 620119515Snjl /* Run iasl -d on the temp file */ 621119515Snjl if (fork() == 0) { 622119515Snjl close(STDOUT_FILENO); 623119515Snjl if (vflag == 0) 624119515Snjl close(STDERR_FILENO); 625119515Snjl execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 626119515Snjl err(1, "exec"); 627119515Snjl } 628119515Snjl 629119515Snjl wait(NULL); 630119515Snjl unlink(tmpstr); 631119515Snjl 632119515Snjl /* Dump iasl's output to stdout */ 633119515Snjl fp = fopen("acpidump.dsl", "r"); 634119515Snjl unlink("acpidump.dsl"); 635119515Snjl if (fp == NULL) { 636119515Snjl perror("iasl tmp file (read)"); 637119515Snjl return; 638119515Snjl } 639119515Snjl while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 640119515Snjl fwrite(buf, 1, len, stdout); 641119515Snjl fclose(fp); 64285323Siwasaki} 64385323Siwasaki 644119515Snjlvoid 645119515Snjlsdt_print_all(struct ACPIsdt *rsdp) 64685323Siwasaki{ 647119515Snjl acpi_handle_rsdt(rsdp); 64885323Siwasaki} 64985323Siwasaki 650119515Snjl/* Fetch a table matching the given signature via the RSDT */ 651119515Snjlstruct ACPIsdt * 652119515Snjlsdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 65385323Siwasaki{ 654119515Snjl int i; 655119515Snjl int entries; 656119515Snjl struct ACPIsdt *sdt; 65785323Siwasaki 658119515Snjl entries = (rsdt->len - SIZEOF_SDT_HDR) / sizeof(uint32_t); 659119515Snjl for (i = 0; i < entries; i++) { 660119515Snjl sdt = (struct ACPIsdt *)acpi_map_sdt(rsdt->body[i]); 661119515Snjl if (acpi_checksum(sdt, sdt->len)) 662119515Snjl errx(1, "RSDT entry %d is corrupt", i); 663119515Snjl if (!memcmp(sdt->signature, sig, strlen(sig))) 664119515Snjl return (sdt); 665119515Snjl } 666119515Snjl 667119515Snjl return (NULL); 66885323Siwasaki} 66985323Siwasaki 670119515Snjlstruct ACPIsdt * 671119912Snjldsdt_from_fadt(struct FADTbody *fadt) 67285323Siwasaki{ 673119515Snjl struct ACPIsdt *sdt; 67485323Siwasaki 675119912Snjl sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 676119515Snjl if (acpi_checksum(sdt, sdt->len)) 677119515Snjl errx(1, "DSDT is corrupt\n"); 678119515Snjl return (sdt); 67985323Siwasaki} 680