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 * $Id: acpi.c,v 1.4 2000/08/09 14:47:52 iwasaki Exp $ 28e1e9a4bfSMitsuru IWASAKI * $FreeBSD$ 29e1e9a4bfSMitsuru IWASAKI */ 30e1e9a4bfSMitsuru IWASAKI 31e1e9a4bfSMitsuru IWASAKI #include <sys/param.h> 32e1e9a4bfSMitsuru IWASAKI #include <sys/stat.h> 33e1e9a4bfSMitsuru IWASAKI #include <sys/acpi.h> 34e1e9a4bfSMitsuru IWASAKI 35e1e9a4bfSMitsuru IWASAKI #include <assert.h> 36e1e9a4bfSMitsuru IWASAKI #include <err.h> 37e1e9a4bfSMitsuru IWASAKI #include <fcntl.h> 38e1e9a4bfSMitsuru IWASAKI #include <stdio.h> 39e1e9a4bfSMitsuru IWASAKI #include <unistd.h> 40e1e9a4bfSMitsuru IWASAKI 41e1e9a4bfSMitsuru IWASAKI #include "acpidump.h" 42e1e9a4bfSMitsuru IWASAKI 43e1e9a4bfSMitsuru IWASAKI static void 44e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length) 45e1e9a4bfSMitsuru IWASAKI { 46e1e9a4bfSMitsuru IWASAKI int c; 47e1e9a4bfSMitsuru IWASAKI 48e1e9a4bfSMitsuru IWASAKI /* Trim trailing spaces and NULLs */ 49e1e9a4bfSMitsuru IWASAKI while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 50e1e9a4bfSMitsuru IWASAKI length--; 51e1e9a4bfSMitsuru IWASAKI 52e1e9a4bfSMitsuru IWASAKI while (length--) { 53e1e9a4bfSMitsuru IWASAKI c = *s++; 54e1e9a4bfSMitsuru IWASAKI putchar(c); 55e1e9a4bfSMitsuru IWASAKI } 56e1e9a4bfSMitsuru IWASAKI } 57e1e9a4bfSMitsuru IWASAKI 58e1e9a4bfSMitsuru IWASAKI static void 59e1e9a4bfSMitsuru IWASAKI acpi_handle_dsdt(struct ACPIsdt *dsdp) 60e1e9a4bfSMitsuru IWASAKI { 61e1e9a4bfSMitsuru IWASAKI u_int8_t *dp; 62e1e9a4bfSMitsuru IWASAKI u_int8_t *end; 63e1e9a4bfSMitsuru IWASAKI 64e1e9a4bfSMitsuru IWASAKI acpi_print_dsdt(dsdp); 65e1e9a4bfSMitsuru IWASAKI dp = (u_int8_t *)dsdp->body; 66e1e9a4bfSMitsuru IWASAKI end = (u_int8_t *)dsdp + dsdp->len; 67e1e9a4bfSMitsuru IWASAKI asl_dump_objectlist(&dp, end, 0); 68e1e9a4bfSMitsuru IWASAKI assert(dp == end); 69e1e9a4bfSMitsuru IWASAKI } 70e1e9a4bfSMitsuru IWASAKI 71e1e9a4bfSMitsuru IWASAKI static void 72e1e9a4bfSMitsuru IWASAKI acpi_handle_facp(struct FACPbody *facp) 73e1e9a4bfSMitsuru IWASAKI { 74e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *dsdp; 75e1e9a4bfSMitsuru IWASAKI 76e1e9a4bfSMitsuru IWASAKI acpi_print_facp(facp); 77e1e9a4bfSMitsuru IWASAKI dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr); 78e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(dsdp, dsdp->len)) 79e1e9a4bfSMitsuru IWASAKI errx(1, "DSDT is corrupt\n"); 80e1e9a4bfSMitsuru IWASAKI acpi_handle_dsdt(dsdp); 81e1e9a4bfSMitsuru IWASAKI aml_dump(dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 82e1e9a4bfSMitsuru IWASAKI } 83e1e9a4bfSMitsuru IWASAKI 84e1e9a4bfSMitsuru IWASAKI /* 85e1e9a4bfSMitsuru IWASAKI * Public interfaces 86e1e9a4bfSMitsuru IWASAKI */ 87e1e9a4bfSMitsuru IWASAKI 88e1e9a4bfSMitsuru IWASAKI void 89e1e9a4bfSMitsuru IWASAKI acpi_print_sdt(struct ACPIsdt *sdp) 90e1e9a4bfSMitsuru IWASAKI { 91e1e9a4bfSMitsuru IWASAKI 92e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->signature, 4); 93e1e9a4bfSMitsuru IWASAKI printf(": Lenth=%d, Revision=%d, Checksum=%d,\n", 94e1e9a4bfSMitsuru IWASAKI sdp->len, sdp->rev, sdp->check); 95e1e9a4bfSMitsuru IWASAKI printf("\tOEMID="); 96e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemid, 6); 97e1e9a4bfSMitsuru IWASAKI printf(", OEM Table ID="); 98e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->oemtblid, 8); 99e1e9a4bfSMitsuru IWASAKI printf(", OEM Revision=0x%x,\n", sdp->oemrev); 100e1e9a4bfSMitsuru IWASAKI printf("\tCreator ID="); 101e1e9a4bfSMitsuru IWASAKI acpi_print_string(sdp->creator, 4); 102e1e9a4bfSMitsuru IWASAKI printf(", Creator Revision=0x%x\n", sdp->crerev); 103e1e9a4bfSMitsuru IWASAKI } 104e1e9a4bfSMitsuru IWASAKI 105e1e9a4bfSMitsuru IWASAKI void 106e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(struct ACPIsdt *rsdp) 107e1e9a4bfSMitsuru IWASAKI { 108e1e9a4bfSMitsuru IWASAKI int i, entries; 109e1e9a4bfSMitsuru IWASAKI 110e1e9a4bfSMitsuru IWASAKI acpi_print_sdt(rsdp); 111e1e9a4bfSMitsuru IWASAKI entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 112e1e9a4bfSMitsuru IWASAKI printf("\tEntries={ "); 113e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 114e1e9a4bfSMitsuru IWASAKI if (i > 0) 115e1e9a4bfSMitsuru IWASAKI printf(", "); 116e1e9a4bfSMitsuru IWASAKI printf("0x%08x", rsdp->body[i]); 117e1e9a4bfSMitsuru IWASAKI } 118e1e9a4bfSMitsuru IWASAKI printf(" }\n"); 119e1e9a4bfSMitsuru IWASAKI } 120e1e9a4bfSMitsuru IWASAKI 121e1e9a4bfSMitsuru IWASAKI void 122e1e9a4bfSMitsuru IWASAKI acpi_print_facp(struct FACPbody *facp) 123e1e9a4bfSMitsuru IWASAKI { 124e1e9a4bfSMitsuru IWASAKI char sep; 125e1e9a4bfSMitsuru IWASAKI 126e1e9a4bfSMitsuru IWASAKI printf("\tDSDT=0x%x\n", facp->dsdt_ptr); 127e1e9a4bfSMitsuru IWASAKI printf("\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC"); 128e1e9a4bfSMitsuru IWASAKI printf("\tSCI_INT=%d\n", facp->sci_int); 129e1e9a4bfSMitsuru IWASAKI printf("\tSMI_CMD=0x%x, ", facp->smi_cmd); 130e1e9a4bfSMitsuru IWASAKI printf("ACPI_ENABLE=0x%x, ", facp->acpi_enable); 131e1e9a4bfSMitsuru IWASAKI printf("ACPI_DISABLE=0x%x, ", facp->acpi_disable); 132e1e9a4bfSMitsuru IWASAKI printf("S4BIOS_REQ=0x%x\n", facp->s4biosreq); 133e1e9a4bfSMitsuru IWASAKI if (facp->pm1a_evt_blk) 134e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 135e1e9a4bfSMitsuru IWASAKI facp->pm1a_evt_blk, 136e1e9a4bfSMitsuru IWASAKI facp->pm1a_evt_blk + facp->pm1_evt_len - 1); 137e1e9a4bfSMitsuru IWASAKI if (facp->pm1b_evt_blk) 138e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 139e1e9a4bfSMitsuru IWASAKI facp->pm1b_evt_blk, 140e1e9a4bfSMitsuru IWASAKI facp->pm1b_evt_blk + facp->pm1_evt_len - 1); 141e1e9a4bfSMitsuru IWASAKI if (facp->pm1a_cnt_blk) 142e1e9a4bfSMitsuru IWASAKI printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 143e1e9a4bfSMitsuru IWASAKI facp->pm1a_cnt_blk, 144e1e9a4bfSMitsuru IWASAKI facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1); 145e1e9a4bfSMitsuru IWASAKI if (facp->pm1b_cnt_blk) 146e1e9a4bfSMitsuru IWASAKI printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 147e1e9a4bfSMitsuru IWASAKI facp->pm1b_cnt_blk, 148e1e9a4bfSMitsuru IWASAKI facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1); 149e1e9a4bfSMitsuru IWASAKI if (facp->pm2_cnt_blk) 150e1e9a4bfSMitsuru IWASAKI printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 151e1e9a4bfSMitsuru IWASAKI facp->pm2_cnt_blk, 152e1e9a4bfSMitsuru IWASAKI facp->pm2_cnt_blk + facp->pm2_cnt_len - 1); 153e1e9a4bfSMitsuru IWASAKI if (facp->pm_tmr_blk) 154e1e9a4bfSMitsuru IWASAKI printf("\tPM2_TMR_BLK=0x%x-0x%x\n", 155e1e9a4bfSMitsuru IWASAKI facp->pm_tmr_blk, 156e1e9a4bfSMitsuru IWASAKI facp->pm_tmr_blk + facp->pm_tmr_len - 1); 157e1e9a4bfSMitsuru IWASAKI if (facp->gpe0_blk) 158e1e9a4bfSMitsuru IWASAKI printf("\tPM2_GPE0_BLK=0x%x-0x%x\n", 159e1e9a4bfSMitsuru IWASAKI facp->gpe0_blk, 160e1e9a4bfSMitsuru IWASAKI facp->gpe0_blk + facp->gpe0_len - 1); 161e1e9a4bfSMitsuru IWASAKI if (facp->gpe1_blk) 162e1e9a4bfSMitsuru IWASAKI printf("\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 163e1e9a4bfSMitsuru IWASAKI facp->gpe1_blk, 164e1e9a4bfSMitsuru IWASAKI facp->gpe1_blk + facp->gpe1_len - 1, 165e1e9a4bfSMitsuru IWASAKI facp->gpe1_base); 166e1e9a4bfSMitsuru IWASAKI printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n", 167e1e9a4bfSMitsuru IWASAKI facp->p_lvl2_lat, facp->p_lvl3_lat); 168e1e9a4bfSMitsuru IWASAKI printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 169e1e9a4bfSMitsuru IWASAKI facp->flush_size, facp->flush_stride); 170e1e9a4bfSMitsuru IWASAKI printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 171e1e9a4bfSMitsuru IWASAKI facp->duty_off, facp->duty_width); 172e1e9a4bfSMitsuru IWASAKI printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 173e1e9a4bfSMitsuru IWASAKI facp->day_alrm, facp->mon_alrm, facp->century); 174e1e9a4bfSMitsuru IWASAKI printf("\tFlags="); 175e1e9a4bfSMitsuru IWASAKI sep = '{'; 176e1e9a4bfSMitsuru IWASAKI 177e1e9a4bfSMitsuru IWASAKI #define PRINTFLAG(xx) do { \ 178e1e9a4bfSMitsuru IWASAKI if (facp->flags & ACPI_FACP_FLAG_## xx) { \ 179e1e9a4bfSMitsuru IWASAKI printf("%c%s", sep, #xx); sep = ','; \ 180e1e9a4bfSMitsuru IWASAKI } \ 181e1e9a4bfSMitsuru IWASAKI } while (0) 182e1e9a4bfSMitsuru IWASAKI 183e1e9a4bfSMitsuru IWASAKI PRINTFLAG(WBINVD); 184e1e9a4bfSMitsuru IWASAKI PRINTFLAG(WBINVD_FLUSH); 185e1e9a4bfSMitsuru IWASAKI PRINTFLAG(PROC_C1); 186e1e9a4bfSMitsuru IWASAKI PRINTFLAG(P_LVL2_UP); 187e1e9a4bfSMitsuru IWASAKI PRINTFLAG(PWR_BUTTON); 188e1e9a4bfSMitsuru IWASAKI PRINTFLAG(SLP_BUTTON); 189e1e9a4bfSMitsuru IWASAKI PRINTFLAG(FIX_RTC); 190e1e9a4bfSMitsuru IWASAKI PRINTFLAG(RTC_S4); 191e1e9a4bfSMitsuru IWASAKI PRINTFLAG(TMR_VAL_EXT); 192e1e9a4bfSMitsuru IWASAKI PRINTFLAG(DCK_CAP); 193e1e9a4bfSMitsuru IWASAKI 194e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG 195e1e9a4bfSMitsuru IWASAKI 196e1e9a4bfSMitsuru IWASAKI printf("}\n"); 197e1e9a4bfSMitsuru IWASAKI } 198e1e9a4bfSMitsuru IWASAKI 199e1e9a4bfSMitsuru IWASAKI void 200e1e9a4bfSMitsuru IWASAKI acpi_print_dsdt(struct ACPIsdt *dsdp) 201e1e9a4bfSMitsuru IWASAKI { 202e1e9a4bfSMitsuru IWASAKI 203e1e9a4bfSMitsuru IWASAKI acpi_print_sdt(dsdp); 204e1e9a4bfSMitsuru IWASAKI } 205e1e9a4bfSMitsuru IWASAKI 206e1e9a4bfSMitsuru IWASAKI int 207e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length) 208e1e9a4bfSMitsuru IWASAKI { 209e1e9a4bfSMitsuru IWASAKI u_int8_t *bp; 210e1e9a4bfSMitsuru IWASAKI u_int8_t sum; 211e1e9a4bfSMitsuru IWASAKI 212e1e9a4bfSMitsuru IWASAKI bp = p; 213e1e9a4bfSMitsuru IWASAKI sum = 0; 214e1e9a4bfSMitsuru IWASAKI while (length--) 215e1e9a4bfSMitsuru IWASAKI sum += *bp++; 216e1e9a4bfSMitsuru IWASAKI 217e1e9a4bfSMitsuru IWASAKI return (sum); 218e1e9a4bfSMitsuru IWASAKI } 219e1e9a4bfSMitsuru IWASAKI 220e1e9a4bfSMitsuru IWASAKI struct ACPIsdt * 221e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa) 222e1e9a4bfSMitsuru IWASAKI { 223e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sp; 224e1e9a4bfSMitsuru IWASAKI 225e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 226e1e9a4bfSMitsuru IWASAKI sp = acpi_map_physical(pa, sp->len); 227e1e9a4bfSMitsuru IWASAKI return (sp); 228e1e9a4bfSMitsuru IWASAKI } 229e1e9a4bfSMitsuru IWASAKI 230e1e9a4bfSMitsuru IWASAKI void 231e1e9a4bfSMitsuru IWASAKI acpi_print_rsd_ptr(struct ACPIrsdp *rp) 232e1e9a4bfSMitsuru IWASAKI { 233e1e9a4bfSMitsuru IWASAKI 234e1e9a4bfSMitsuru IWASAKI printf("RSD PTR: Checksum=%d, OEMID=", rp->sum); 235e1e9a4bfSMitsuru IWASAKI acpi_print_string(rp->oem, 6); 236e1e9a4bfSMitsuru IWASAKI printf(", RsdtAddress=0x%08x\n", rp->addr); 237e1e9a4bfSMitsuru IWASAKI } 238e1e9a4bfSMitsuru IWASAKI 239e1e9a4bfSMitsuru IWASAKI void 240e1e9a4bfSMitsuru IWASAKI acpi_handle_rsdt(struct ACPIsdt *rsdp) 241e1e9a4bfSMitsuru IWASAKI { 242e1e9a4bfSMitsuru IWASAKI int i; 243e1e9a4bfSMitsuru IWASAKI int entries; 244e1e9a4bfSMitsuru IWASAKI struct ACPIsdt *sdp; 245e1e9a4bfSMitsuru IWASAKI 246e1e9a4bfSMitsuru IWASAKI entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t); 247e1e9a4bfSMitsuru IWASAKI acpi_print_rsdt(rsdp); 248e1e9a4bfSMitsuru IWASAKI for (i = 0; i < entries; i++) { 249e1e9a4bfSMitsuru IWASAKI sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]); 250e1e9a4bfSMitsuru IWASAKI if (acpi_checksum(sdp, sdp->len)) 251e1e9a4bfSMitsuru IWASAKI errx(1, "RSDT entry %d is corrupt\n", i); 252e1e9a4bfSMitsuru IWASAKI if (!memcmp(sdp->signature, "FACP", 4)) { 253e1e9a4bfSMitsuru IWASAKI acpi_handle_facp((struct FACPbody *) sdp->body); 254e1e9a4bfSMitsuru IWASAKI } else { 255e1e9a4bfSMitsuru IWASAKI acpi_print_sdt(sdp); 256e1e9a4bfSMitsuru IWASAKI } 257e1e9a4bfSMitsuru IWASAKI } 258e1e9a4bfSMitsuru IWASAKI } 259