1 /*- 2 * Copyright (c) 1998 Doug Rabson 3 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/endian.h> 32 #include <sys/stat.h> 33 #include <sys/wait.h> 34 #include <assert.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <stdio.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include "acpidump.h" 42 43 #define BEGIN_COMMENT "/*\n" 44 #define END_COMMENT " */\n" 45 46 static void acpi_print_string(char *s, size_t length); 47 static void acpi_print_gas(struct ACPIgas *gas); 48 static void acpi_handle_fadt(struct FADTbody *fadt); 49 static void acpi_print_cpu(u_char cpu_id); 50 static void acpi_print_local_apic(u_char cpu_id, u_char apic_id, 51 u_int32_t flags); 52 static void acpi_print_io_apic(u_char apic_id, u_int32_t int_base, 53 u_int64_t apic_addr); 54 static void acpi_print_mps_flags(u_int16_t flags); 55 static void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags); 56 static void acpi_print_apic(struct MADT_APIC *mp); 57 static void acpi_handle_apic(struct ACPIsdt *sdp); 58 static void acpi_handle_hpet(struct ACPIsdt *sdp); 59 static void acpi_print_sdt(struct ACPIsdt *sdp); 60 static void acpi_print_fadt(struct FADTbody *fadt); 61 static void acpi_print_facs(struct FACSbody *facs); 62 static void acpi_print_dsdt(struct ACPIsdt *dsdp); 63 static struct ACPIsdt *acpi_map_sdt(vm_offset_t pa); 64 static void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 65 static void acpi_handle_rsdt(struct ACPIsdt *rsdp); 66 67 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */ 68 static int addr_size; 69 70 static void 71 acpi_print_string(char *s, size_t length) 72 { 73 int c; 74 75 /* Trim trailing spaces and NULLs */ 76 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 77 length--; 78 79 while (length--) { 80 c = *s++; 81 putchar(c); 82 } 83 } 84 85 static void 86 acpi_print_gas(struct ACPIgas *gas) 87 { 88 switch(gas->address_space_id) { 89 case ACPI_GAS_MEMORY: 90 printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->address, 91 gas->bit_offset, gas->bit_width); 92 break; 93 case ACPI_GAS_IO: 94 printf("0x%02lx:%u[%u] (IO)", (u_long)gas->address, 95 gas->bit_offset, gas->bit_width); 96 break; 97 case ACPI_GAS_PCI: 98 printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->address >> 32), 99 (uint16_t)((gas->address >> 16) & 0xffff), 100 (uint16_t)gas->address); 101 break; 102 /* XXX How to handle these below? */ 103 case ACPI_GAS_EMBEDDED: 104 printf("0x%x:%u[%u] (EC)", (uint16_t)gas->address, 105 gas->bit_offset, gas->bit_width); 106 break; 107 case ACPI_GAS_SMBUS: 108 printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->address, 109 gas->bit_offset, gas->bit_width); 110 break; 111 case ACPI_GAS_FIXED: 112 default: 113 printf("0x%08lx (?)", (u_long)gas->address); 114 break; 115 } 116 } 117 118 static void 119 acpi_handle_fadt(struct FADTbody *fadt) 120 { 121 struct ACPIsdt *dsdp; 122 struct FACSbody *facs; 123 124 acpi_print_fadt(fadt); 125 126 /* 127 * My T23 is revision 2 but the 64 bit addresses are invalid. 128 * If revision 2 and the 32 bit address is non-zero but the 32 129 * and 64 bit versions don't match, prefer the 32 bit version. 130 */ 131 if (addr_size == 4 || 132 (addr_size == 8 && fadt->facs_ptr != 0 && 133 (fadt->x_facs_ptr & 0xffffffff) != fadt->facs_ptr)) 134 facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr); 135 else 136 facs = (struct FACSbody *)acpi_map_sdt(fadt->x_facs_ptr); 137 if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64) 138 errx(1, "FACS is corrupt"); 139 acpi_print_facs(facs); 140 141 if (addr_size == 4 || 142 (addr_size == 8 && fadt->dsdt_ptr != 0 && 143 (fadt->x_dsdt_ptr & 0xffffffff) != fadt->dsdt_ptr)) 144 dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 145 else 146 dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr); 147 if (acpi_checksum(dsdp, dsdp->len)) 148 errx(1, "DSDT is corrupt"); 149 acpi_print_dsdt(dsdp); 150 } 151 152 static void 153 acpi_print_cpu(u_char cpu_id) 154 { 155 156 printf("\tACPI CPU="); 157 if (cpu_id == 0xff) 158 printf("ALL\n"); 159 else 160 printf("%d\n", (u_int)cpu_id); 161 } 162 163 static void 164 acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 165 { 166 acpi_print_cpu(cpu_id); 167 printf("\tFlags={"); 168 if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 169 printf("ENABLED"); 170 else 171 printf("DISABLED"); 172 printf("}\n"); 173 printf("\tAPIC ID=%d\n", (u_int)apic_id); 174 } 175 176 static void 177 acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 178 { 179 printf("\tAPIC ID=%d\n", (u_int)apic_id); 180 printf("\tINT BASE=%d\n", int_base); 181 printf("\tADDR=0x%016jx\n", apic_addr); 182 } 183 184 static void 185 acpi_print_mps_flags(u_int16_t flags) 186 { 187 188 printf("\tFlags={Polarity="); 189 switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 190 case MPS_INT_FLAG_POLARITY_CONFORM: 191 printf("conforming"); 192 break; 193 case MPS_INT_FLAG_POLARITY_HIGH: 194 printf("active-hi"); 195 break; 196 case MPS_INT_FLAG_POLARITY_LOW: 197 printf("active-lo"); 198 break; 199 default: 200 printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 201 break; 202 } 203 printf(", Trigger="); 204 switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 205 case MPS_INT_FLAG_TRIGGER_CONFORM: 206 printf("conforming"); 207 break; 208 case MPS_INT_FLAG_TRIGGER_EDGE: 209 printf("edge"); 210 break; 211 case MPS_INT_FLAG_TRIGGER_LEVEL: 212 printf("level"); 213 break; 214 default: 215 printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 216 } 217 printf("}\n"); 218 } 219 220 static void 221 acpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 222 { 223 224 printf("\tINTR=%d\n", (u_int)intr); 225 acpi_print_mps_flags(mps_flags); 226 } 227 228 const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 229 "Local NMI", "Local APIC Override", "IO SAPIC", 230 "Local SAPIC", "Platform Interrupt" }; 231 const char *platform_int_types[] = { "PMI", "INIT", 232 "Corrected Platform Error" }; 233 234 static void 235 acpi_print_apic(struct MADT_APIC *mp) 236 { 237 238 printf("\tType=%s\n", apic_types[mp->type]); 239 switch (mp->type) { 240 case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 241 acpi_print_local_apic(mp->body.local_apic.cpu_id, 242 mp->body.local_apic.apic_id, mp->body.local_apic.flags); 243 break; 244 case ACPI_MADT_APIC_TYPE_IO_APIC: 245 acpi_print_io_apic(mp->body.io_apic.apic_id, 246 mp->body.io_apic.int_base, 247 mp->body.io_apic.apic_addr); 248 break; 249 case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 250 printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 251 printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 252 acpi_print_intr(mp->body.int_override.intr, 253 mp->body.int_override.mps_flags); 254 break; 255 case ACPI_MADT_APIC_TYPE_NMI: 256 acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 257 break; 258 case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 259 acpi_print_cpu(mp->body.local_nmi.cpu_id); 260 printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 261 acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 262 break; 263 case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 264 printf("\tLocal APIC ADDR=0x%016jx\n", 265 mp->body.local_apic_override.apic_addr); 266 break; 267 case ACPI_MADT_APIC_TYPE_IO_SAPIC: 268 acpi_print_io_apic(mp->body.io_sapic.apic_id, 269 mp->body.io_sapic.int_base, 270 mp->body.io_sapic.apic_addr); 271 break; 272 case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 273 acpi_print_local_apic(mp->body.local_sapic.cpu_id, 274 mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 275 printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 276 break; 277 case ACPI_MADT_APIC_TYPE_INT_SRC: 278 printf("\tType=%s\n", 279 platform_int_types[mp->body.int_src.type]); 280 printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 281 printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 282 printf("\tSAPIC Vector=%d\n", 283 (u_int)mp->body.int_src.sapic_vector); 284 acpi_print_intr(mp->body.int_src.intr, 285 mp->body.int_src.mps_flags); 286 break; 287 default: 288 printf("\tUnknown type %d\n", (u_int)mp->type); 289 break; 290 } 291 } 292 293 static void 294 acpi_handle_apic(struct ACPIsdt *sdp) 295 { 296 struct MADTbody *madtp; 297 struct MADT_APIC *madt_apicp; 298 299 printf(BEGIN_COMMENT); 300 acpi_print_sdt(sdp); 301 madtp = (struct MADTbody *) sdp->body; 302 printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 303 printf("\tFlags={"); 304 if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 305 printf("PC-AT"); 306 printf("}\n"); 307 madt_apicp = (struct MADT_APIC *)madtp->body; 308 while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 309 printf("\n"); 310 acpi_print_apic(madt_apicp); 311 madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 312 madt_apicp->len); 313 } 314 printf(END_COMMENT); 315 } 316 317 static void 318 acpi_handle_hpet(struct ACPIsdt *sdp) 319 { 320 struct HPETbody *hpetp; 321 322 printf(BEGIN_COMMENT); 323 acpi_print_sdt(sdp); 324 hpetp = (struct HPETbody *) sdp->body; 325 printf("\tHPET Number=%d\n", hpetp->hpet_number); 326 printf("\tADDR=0x%08x\n", hpetp->base_addr); 327 printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 328 printf("\tComparitors=%d\n", hpetp->block_comparitors); 329 printf("\tCounter Size=%d\n", hpetp->block_counter_size); 330 printf("\tLegacy IRQ routing capable={"); 331 if (hpetp->block_legacy_capable) 332 printf("TRUE}\n"); 333 else 334 printf("FALSE}\n"); 335 printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 336 printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 337 printf(END_COMMENT); 338 } 339 340 static void 341 acpi_handle_ecdt(struct ACPIsdt *sdp) 342 { 343 struct ECDTbody *ecdt; 344 345 printf(BEGIN_COMMENT); 346 acpi_print_sdt(sdp); 347 ecdt = (struct ECDTbody *) sdp->body; 348 printf("\tEC_CONTROL="); 349 acpi_print_gas(&ecdt->ec_control); 350 printf("\n\tEC_DATA="); 351 acpi_print_gas(&ecdt->ec_data); 352 printf("\n\tUID=%#x, ", ecdt->uid); 353 printf("GPE_BIT=%#x\n", ecdt->gpe_bit); 354 printf("\tEC_ID=%s\n", ecdt->ec_id); 355 printf(END_COMMENT); 356 } 357 358 static void 359 acpi_print_sdt(struct ACPIsdt *sdp) 360 { 361 printf(" "); 362 acpi_print_string(sdp->signature, 4); 363 printf(": Length=%d, Revision=%d, Checksum=%d,\n", 364 sdp->len, sdp->rev, sdp->check); 365 printf("\tOEMID="); 366 acpi_print_string(sdp->oemid, 6); 367 printf(", OEM Table ID="); 368 acpi_print_string(sdp->oemtblid, 8); 369 printf(", OEM Revision=0x%x,\n", sdp->oemrev); 370 printf("\tCreator ID="); 371 acpi_print_string(sdp->creator, 4); 372 printf(", Creator Revision=0x%x\n", sdp->crerev); 373 } 374 375 static void 376 acpi_print_rsdt(struct ACPIsdt *rsdp) 377 { 378 int i, entries; 379 u_long addr; 380 381 printf(BEGIN_COMMENT); 382 acpi_print_sdt(rsdp); 383 entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 384 printf("\tEntries={ "); 385 for (i = 0; i < entries; i++) { 386 if (i > 0) 387 printf(", "); 388 switch (addr_size) { 389 case 4: 390 addr = le32dec((char*)rsdp->body + i * addr_size); 391 break; 392 case 8: 393 addr = le64dec((char*)rsdp->body + i * addr_size); 394 break; 395 default: 396 addr = 0; 397 } 398 assert(addr != 0); 399 printf("0x%08lx", addr); 400 } 401 printf(" }\n"); 402 printf(END_COMMENT); 403 } 404 405 static const char *acpi_pm_profiles[] = { 406 "Unspecified", "Desktop", "Mobile", "Workstation", 407 "Enterprise Server", "SOHO Server", "Appliance PC" 408 }; 409 410 static void 411 acpi_print_fadt(struct FADTbody *fadt) 412 { 413 const char *pm; 414 char sep; 415 416 printf(BEGIN_COMMENT); 417 printf(" FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr, 418 fadt->dsdt_ptr); 419 printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC"); 420 if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 421 pm = "Reserved"; 422 else 423 pm = acpi_pm_profiles[fadt->pm_profile]; 424 printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile); 425 printf("\tSCI_INT=%d\n", fadt->sci_int); 426 printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd); 427 printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable); 428 printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable); 429 printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq); 430 printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt); 431 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 432 fadt->pm1a_evt_blk, 433 fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1); 434 if (fadt->pm1b_evt_blk != 0) 435 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 436 fadt->pm1b_evt_blk, 437 fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1); 438 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 439 fadt->pm1a_cnt_blk, 440 fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1); 441 if (fadt->pm1b_cnt_blk != 0) 442 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 443 fadt->pm1b_cnt_blk, 444 fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1); 445 if (fadt->pm2_cnt_blk != 0) 446 printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 447 fadt->pm2_cnt_blk, 448 fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1); 449 printf("\tPM_TMR_BLK=0x%x-0x%x\n", 450 fadt->pm_tmr_blk, 451 fadt->pm_tmr_blk + fadt->pm_tmr_len - 1); 452 if (fadt->gpe0_blk != 0) 453 printf("\tGPE0_BLK=0x%x-0x%x\n", 454 fadt->gpe0_blk, 455 fadt->gpe0_blk + fadt->gpe0_len - 1); 456 if (fadt->gpe1_blk != 0) 457 printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 458 fadt->gpe1_blk, 459 fadt->gpe1_blk + fadt->gpe1_len - 1, 460 fadt->gpe1_base); 461 if (fadt->cst_cnt != 0) 462 printf("\tCST_CNT=0x%x\n", fadt->cst_cnt); 463 printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n", 464 fadt->p_lvl2_lat, fadt->p_lvl3_lat); 465 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 466 fadt->flush_size, fadt->flush_stride); 467 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 468 fadt->duty_off, fadt->duty_width); 469 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 470 fadt->day_alrm, fadt->mon_alrm, fadt->century); 471 472 #define PRINTFLAG(var, flag) do { \ 473 if ((var) & FADT_FLAG_## flag) { \ 474 printf("%c%s", sep, #flag); sep = ','; \ 475 } \ 476 } while (0) 477 478 printf("\tIAPC_BOOT_ARCH="); 479 sep = '{'; 480 PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV); 481 PRINTFLAG(fadt->iapc_boot_arch, 8042); 482 printf("}\n"); 483 484 printf("\tFlags="); 485 sep = '{'; 486 PRINTFLAG(fadt->flags, WBINVD); 487 PRINTFLAG(fadt->flags, WBINVD_FLUSH); 488 PRINTFLAG(fadt->flags, PROC_C1); 489 PRINTFLAG(fadt->flags, P_LVL2_UP); 490 PRINTFLAG(fadt->flags, PWR_BUTTON); 491 PRINTFLAG(fadt->flags, SLP_BUTTON); 492 PRINTFLAG(fadt->flags, FIX_RTC); 493 PRINTFLAG(fadt->flags, RTC_S4); 494 PRINTFLAG(fadt->flags, TMR_VAL_EXT); 495 PRINTFLAG(fadt->flags, DCK_CAP); 496 PRINTFLAG(fadt->flags, RESET_REG); 497 PRINTFLAG(fadt->flags, SEALED_CASE); 498 PRINTFLAG(fadt->flags, HEADLESS); 499 PRINTFLAG(fadt->flags, CPU_SW_SLP); 500 printf("}\n"); 501 502 #undef PRINTFLAG 503 504 if (fadt->flags & FADT_FLAG_RESET_REG) { 505 printf("\tRESET_REG="); 506 acpi_print_gas(&fadt->reset_reg); 507 printf(", RESET_VALUE=%#x\n", fadt->reset_value); 508 } 509 if (addr_size == 8) { 510 printf("\tX_FACS=0x%08lx, ", (u_long)fadt->x_facs_ptr); 511 printf("X_DSDT=0x%08lx\n", (u_long)fadt->x_dsdt_ptr); 512 printf("\tX_PM1a_EVT_BLK="); 513 acpi_print_gas(&fadt->x_pm1a_evt_blk); 514 if (fadt->x_pm1b_evt_blk.address != 0) { 515 printf("\n\tX_PM1b_EVT_BLK="); 516 acpi_print_gas(&fadt->x_pm1b_evt_blk); 517 } 518 printf("\n\tX_PM1a_CNT_BLK="); 519 acpi_print_gas(&fadt->x_pm1a_cnt_blk); 520 if (fadt->x_pm1b_cnt_blk.address != 0) { 521 printf("\n\tX_PM1b_CNT_BLK="); 522 acpi_print_gas(&fadt->x_pm1b_cnt_blk); 523 } 524 if (fadt->x_pm1b_cnt_blk.address != 0) { 525 printf("\n\tX_PM2_CNT_BLK="); 526 acpi_print_gas(&fadt->x_pm2_cnt_blk); 527 } 528 printf("\n\tX_PM_TMR_BLK="); 529 acpi_print_gas(&fadt->x_pm_tmr_blk); 530 if (fadt->x_gpe0_blk.address != 0) { 531 printf("\n\tX_GPE0_BLK="); 532 acpi_print_gas(&fadt->x_gpe0_blk); 533 } 534 if (fadt->x_gpe1_blk.address != 0) { 535 printf("\n\tX_GPE1_BLK="); 536 acpi_print_gas(&fadt->x_gpe1_blk); 537 } 538 printf("\n"); 539 } 540 541 printf(END_COMMENT); 542 } 543 544 static void 545 acpi_print_facs(struct FACSbody *facs) 546 { 547 printf(BEGIN_COMMENT); 548 printf(" FACS:\tLength=%u, ", facs->len); 549 printf("HwSig=0x%08x, ", facs->hw_sig); 550 printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec); 551 552 printf("\tGlobal_Lock="); 553 if (facs->global_lock != 0) { 554 if (facs->global_lock & FACS_FLAG_LOCK_PENDING) 555 printf("PENDING,"); 556 if (facs->global_lock & FACS_FLAG_LOCK_OWNED) 557 printf("OWNED"); 558 } 559 printf("\n"); 560 561 printf("\tFlags="); 562 if (facs->flags & FACS_FLAG_S4BIOS_F) 563 printf("S4BIOS"); 564 printf("\n"); 565 566 if (facs->x_firm_wake_vec != 0) { 567 printf("\tX_Firm_Wake_Vec=%08lx\n", 568 (u_long)facs->x_firm_wake_vec); 569 } 570 printf("\tVersion=%u\n", facs->version); 571 572 printf(END_COMMENT); 573 } 574 575 static void 576 acpi_print_dsdt(struct ACPIsdt *dsdp) 577 { 578 printf(BEGIN_COMMENT); 579 acpi_print_sdt(dsdp); 580 printf(END_COMMENT); 581 } 582 583 int 584 acpi_checksum(void *p, size_t length) 585 { 586 u_int8_t *bp; 587 u_int8_t sum; 588 589 bp = p; 590 sum = 0; 591 while (length--) 592 sum += *bp++; 593 594 return (sum); 595 } 596 597 static struct ACPIsdt * 598 acpi_map_sdt(vm_offset_t pa) 599 { 600 struct ACPIsdt *sp; 601 602 sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 603 sp = acpi_map_physical(pa, sp->len); 604 return (sp); 605 } 606 607 static void 608 acpi_print_rsd_ptr(struct ACPIrsdp *rp) 609 { 610 printf(BEGIN_COMMENT); 611 printf(" RSD PTR: OEM="); 612 acpi_print_string(rp->oem, 6); 613 printf(", ACPI_Rev=%s (%d)\n", rp->revision < 2 ? "1.0x" : "2.0x", 614 rp->revision); 615 if (rp->revision < 2) { 616 printf("\tRSDT=0x%08x, cksum=%u\n", rp->rsdt_addr, rp->sum); 617 } else { 618 printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n", 619 (u_long)rp->xsdt_addr, rp->length, rp->xsum); 620 } 621 printf(END_COMMENT); 622 } 623 624 static void 625 acpi_handle_rsdt(struct ACPIsdt *rsdp) 626 { 627 struct ACPIsdt *sdp; 628 vm_offset_t addr; 629 int entries, i; 630 631 acpi_print_rsdt(rsdp); 632 entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 633 for (i = 0; i < entries; i++) { 634 switch (addr_size) { 635 case 4: 636 addr = le32dec((char*)rsdp->body + i * addr_size); 637 break; 638 case 8: 639 addr = le64dec((char*)rsdp->body + i * addr_size); 640 break; 641 default: 642 assert((addr = 0)); 643 } 644 645 sdp = (struct ACPIsdt *)acpi_map_sdt(addr); 646 if (acpi_checksum(sdp, sdp->len)) 647 errx(1, "RSDT entry %d is corrupt", i); 648 if (!memcmp(sdp->signature, "FACP", 4)) 649 acpi_handle_fadt((struct FADTbody *) sdp->body); 650 else if (!memcmp(sdp->signature, "APIC", 4)) 651 acpi_handle_apic(sdp); 652 else if (!memcmp(sdp->signature, "HPET", 4)) 653 acpi_handle_hpet(sdp); 654 else if (!memcmp(sdp->signature, "ECDT", 4)) 655 acpi_handle_ecdt(sdp); 656 else { 657 printf(BEGIN_COMMENT); 658 acpi_print_sdt(sdp); 659 printf(END_COMMENT); 660 } 661 } 662 } 663 664 struct ACPIsdt * 665 sdt_load_devmem() 666 { 667 struct ACPIrsdp *rp; 668 struct ACPIsdt *rsdp; 669 670 rp = acpi_find_rsd_ptr(); 671 if (!rp) 672 errx(1, "Can't find ACPI information"); 673 674 if (tflag) 675 acpi_print_rsd_ptr(rp); 676 if (rp->revision < 2) { 677 rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 678 if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 679 acpi_checksum(rsdp, rsdp->len) != 0) 680 errx(1, "RSDT is corrupted"); 681 addr_size = sizeof(uint32_t); 682 } else { 683 rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr); 684 if (memcmp(rsdp->signature, "XSDT", 4) != 0 || 685 acpi_checksum(rsdp, rsdp->len) != 0) 686 errx(1, "XSDT is corrupted"); 687 addr_size = sizeof(uint64_t); 688 } 689 return (rsdp); 690 } 691 692 void 693 dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 694 { 695 int fd; 696 mode_t mode; 697 698 assert(outfile != NULL); 699 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 700 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 701 if (fd == -1) { 702 perror("dsdt_save_file"); 703 return; 704 } 705 write(fd, dsdp, SIZEOF_SDT_HDR); 706 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 707 close(fd); 708 } 709 710 void 711 aml_disassemble(struct ACPIsdt *dsdp) 712 { 713 char tmpstr[32], buf[256]; 714 FILE *fp; 715 int fd, len; 716 717 strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 718 fd = mkstemp(tmpstr); 719 if (fd < 0) { 720 perror("iasl tmp file"); 721 return; 722 } 723 724 /* Dump DSDT to the temp file */ 725 write(fd, dsdp, SIZEOF_SDT_HDR); 726 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 727 close(fd); 728 729 /* Run iasl -d on the temp file */ 730 if (fork() == 0) { 731 close(STDOUT_FILENO); 732 if (vflag == 0) 733 close(STDERR_FILENO); 734 execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 735 err(1, "exec"); 736 } 737 738 wait(NULL); 739 unlink(tmpstr); 740 741 /* Dump iasl's output to stdout */ 742 fp = fopen("acpidump.dsl", "r"); 743 unlink("acpidump.dsl"); 744 if (fp == NULL) { 745 perror("iasl tmp file (read)"); 746 return; 747 } 748 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 749 fwrite(buf, 1, len, stdout); 750 fclose(fp); 751 } 752 753 void 754 sdt_print_all(struct ACPIsdt *rsdp) 755 { 756 acpi_handle_rsdt(rsdp); 757 } 758 759 /* Fetch a table matching the given signature via the RSDT */ 760 struct ACPIsdt * 761 sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 762 { 763 struct ACPIsdt *sdt; 764 vm_offset_t addr; 765 int entries, i; 766 767 entries = (rsdt->len - SIZEOF_SDT_HDR) / addr_size; 768 for (i = 0; i < entries; i++) { 769 switch (addr_size) { 770 case 4: 771 addr = le32dec((char*)rsdt->body + i * addr_size); 772 break; 773 case 8: 774 addr = le64dec((char*)rsdt->body + i * addr_size); 775 break; 776 default: 777 assert((addr = 0)); 778 } 779 sdt = (struct ACPIsdt *)acpi_map_sdt(addr); 780 if (memcmp(sdt->signature, sig, strlen(sig))) 781 continue; 782 if (acpi_checksum(sdt, sdt->len)) 783 errx(1, "RSDT entry %d is corrupt", i); 784 return (sdt); 785 } 786 787 return (NULL); 788 } 789 790 struct ACPIsdt * 791 dsdt_from_fadt(struct FADTbody *fadt) 792 { 793 struct ACPIsdt *sdt; 794 795 /* Use the DSDT address if it is valid and version 1, else X_DSDT */ 796 if (addr_size == 4 || 797 (addr_size == 8 && fadt->dsdt_ptr != 0 && 798 (fadt->x_dsdt_ptr & 0xffffffff) != fadt->dsdt_ptr)) 799 sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 800 else 801 sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr); 802 if (acpi_checksum(sdt, sdt->len)) 803 errx(1, "DSDT is corrupt\n"); 804 return (sdt); 805 } 806