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