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