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(ACPI_GENERIC_ADDRESS *gas); 51 static int acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt); 52 static void acpi_handle_fadt(ACPI_TABLE_HEADER *fadt); 53 static void acpi_print_cpu(u_char cpu_id); 54 static void acpi_print_cpu_uid(uint32_t uid, char *uid_string); 55 static void acpi_print_local_apic(uint32_t apic_id, uint32_t flags); 56 static void acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, 57 uint64_t apic_addr); 58 static void acpi_print_mps_flags(uint16_t flags); 59 static void acpi_print_intr(uint32_t intr, uint16_t mps_flags); 60 static void acpi_print_local_nmi(u_int lint, uint16_t mps_flags); 61 static void acpi_print_madt(ACPI_SUBTABLE_HEADER *mp); 62 static void acpi_handle_madt(ACPI_TABLE_HEADER *sdp); 63 static void acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp); 64 static void acpi_handle_hpet(ACPI_TABLE_HEADER *sdp); 65 static void acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp); 66 static void acpi_handle_slit(ACPI_TABLE_HEADER *sdp); 67 static void acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain, 68 uint32_t flags); 69 static void acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp); 70 static void acpi_print_srat(ACPI_SUBTABLE_HEADER *srat); 71 static void acpi_handle_srat(ACPI_TABLE_HEADER *sdp); 72 static void acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp); 73 static void acpi_print_sdt(ACPI_TABLE_HEADER *sdp); 74 static void acpi_print_fadt(ACPI_TABLE_HEADER *sdp); 75 static void acpi_print_facs(ACPI_TABLE_FACS *facs); 76 static void acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp); 77 static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa); 78 static void acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp); 79 static void acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp); 80 static void acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first, 81 void (*action)(ACPI_SUBTABLE_HEADER *)); 82 83 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */ 84 static int addr_size; 85 86 /* Strings used in the TCPA table */ 87 static const char *tcpa_event_type_strings[] = { 88 "PREBOOT Certificate", 89 "POST Code", 90 "Unused", 91 "No Action", 92 "Separator", 93 "Action", 94 "Event Tag", 95 "S-CRTM Contents", 96 "S-CRTM Version", 97 "CPU Microcode", 98 "Platform Config Flags", 99 "Table of Devices", 100 "Compact Hash", 101 "IPL", 102 "IPL Partition Data", 103 "Non-Host Code", 104 "Non-Host Config", 105 "Non-Host Info" 106 }; 107 108 static const char *TCPA_pcclient_strings[] = { 109 "<undefined>", 110 "SMBIOS", 111 "BIS Certificate", 112 "POST BIOS ROM Strings", 113 "ESCD", 114 "CMOS", 115 "NVRAM", 116 "Option ROM Execute", 117 "Option ROM Configurateion", 118 "<undefined>", 119 "Option ROM Microcode Update ", 120 "S-CRTM Version String", 121 "S-CRTM Contents", 122 "POST Contents", 123 "Table of Devices", 124 }; 125 126 #define PRINTFLAG_END() printflag_end() 127 128 static char pf_sep = '{'; 129 130 static void 131 printflag_end(void) 132 { 133 134 if (pf_sep != '{') { 135 printf("}"); 136 pf_sep = '{'; 137 } 138 printf("\n"); 139 } 140 141 static void 142 printflag(uint64_t var, uint64_t mask, const char *name) 143 { 144 145 if (var & mask) { 146 printf("%c%s", pf_sep, name); 147 pf_sep = ','; 148 } 149 } 150 151 static void 152 acpi_print_string(char *s, size_t length) 153 { 154 int c; 155 156 /* Trim trailing spaces and NULLs */ 157 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 158 length--; 159 160 while (length--) { 161 c = *s++; 162 putchar(c); 163 } 164 } 165 166 static void 167 acpi_print_gas(ACPI_GENERIC_ADDRESS *gas) 168 { 169 switch(gas->SpaceId) { 170 case ACPI_GAS_MEMORY: 171 if (gas->BitWidth <= 32) 172 printf("0x%08x:%u[%u] (Memory)", 173 (u_int)gas->Address, gas->BitOffset, 174 gas->BitWidth); 175 else 176 printf("0x%016jx:%u[%u] (Memory)", 177 (uintmax_t)gas->Address, gas->BitOffset, 178 gas->BitWidth); 179 break; 180 case ACPI_GAS_IO: 181 printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address, 182 gas->BitOffset, gas->BitWidth); 183 break; 184 case ACPI_GAS_PCI: 185 printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32), 186 (uint16_t)((gas->Address >> 16) & 0xffff), 187 (uint16_t)gas->Address); 188 break; 189 /* XXX How to handle these below? */ 190 case ACPI_GAS_EMBEDDED: 191 printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address, 192 gas->BitOffset, gas->BitWidth); 193 break; 194 case ACPI_GAS_SMBUS: 195 printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address, 196 gas->BitOffset, gas->BitWidth); 197 break; 198 case ACPI_GAS_CMOS: 199 case ACPI_GAS_PCIBAR: 200 case ACPI_GAS_DATATABLE: 201 case ACPI_GAS_FIXED: 202 default: 203 printf("0x%016jx (?)", (uintmax_t)gas->Address); 204 break; 205 } 206 } 207 208 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */ 209 static int 210 acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt) 211 { 212 int fadt_revision; 213 214 /* Set the FADT revision separately from the RSDP version. */ 215 if (addr_size == 8) { 216 fadt_revision = 2; 217 218 /* 219 * A few systems (e.g., IBM T23) have an RSDP that claims 220 * revision 2 but the 64 bit addresses are invalid. If 221 * revision 2 and the 32 bit address is non-zero but the 222 * 32 and 64 bit versions don't match, prefer the 32 bit 223 * version for all subsequent tables. 224 */ 225 if (fadt->Facs != 0 && 226 (fadt->XFacs & 0xffffffff) != fadt->Facs) 227 fadt_revision = 1; 228 } else 229 fadt_revision = 1; 230 return (fadt_revision); 231 } 232 233 static void 234 acpi_handle_fadt(ACPI_TABLE_HEADER *sdp) 235 { 236 ACPI_TABLE_HEADER *dsdp; 237 ACPI_TABLE_FACS *facs; 238 ACPI_TABLE_FADT *fadt; 239 int fadt_revision; 240 241 fadt = (ACPI_TABLE_FADT *)sdp; 242 acpi_print_fadt(sdp); 243 244 fadt_revision = acpi_get_fadt_revision(fadt); 245 if (fadt_revision == 1) 246 facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs); 247 else 248 facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs); 249 if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64) 250 errx(1, "FACS is corrupt"); 251 acpi_print_facs(facs); 252 253 if (fadt_revision == 1) 254 dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt); 255 else 256 dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt); 257 if (acpi_checksum(dsdp, dsdp->Length)) 258 errx(1, "DSDT is corrupt"); 259 acpi_print_dsdt(dsdp); 260 } 261 262 static void 263 acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first, 264 void (*action)(ACPI_SUBTABLE_HEADER *)) 265 { 266 ACPI_SUBTABLE_HEADER *subtable; 267 char *end; 268 269 subtable = first; 270 end = (char *)table + table->Length; 271 while ((char *)subtable < end) { 272 printf("\n"); 273 action(subtable); 274 subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable + 275 subtable->Length); 276 } 277 } 278 279 static void 280 acpi_print_cpu(u_char cpu_id) 281 { 282 283 printf("\tACPI CPU="); 284 if (cpu_id == 0xff) 285 printf("ALL\n"); 286 else 287 printf("%d\n", (u_int)cpu_id); 288 } 289 290 static void 291 acpi_print_cpu_uid(uint32_t uid, char *uid_string) 292 { 293 294 printf("\tUID=%d", uid); 295 if (uid_string != NULL) 296 printf(" (%s)", uid_string); 297 printf("\n"); 298 } 299 300 static void 301 acpi_print_local_apic(uint32_t apic_id, uint32_t flags) 302 { 303 304 printf("\tFlags={"); 305 if (flags & ACPI_MADT_ENABLED) 306 printf("ENABLED"); 307 else 308 printf("DISABLED"); 309 printf("}\n"); 310 printf("\tAPIC ID=%d\n", apic_id); 311 } 312 313 static void 314 acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr) 315 { 316 317 printf("\tAPIC ID=%d\n", apic_id); 318 printf("\tINT BASE=%d\n", int_base); 319 printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr); 320 } 321 322 static void 323 acpi_print_mps_flags(uint16_t flags) 324 { 325 326 printf("\tFlags={Polarity="); 327 switch (flags & ACPI_MADT_POLARITY_MASK) { 328 case ACPI_MADT_POLARITY_CONFORMS: 329 printf("conforming"); 330 break; 331 case ACPI_MADT_POLARITY_ACTIVE_HIGH: 332 printf("active-hi"); 333 break; 334 case ACPI_MADT_POLARITY_ACTIVE_LOW: 335 printf("active-lo"); 336 break; 337 default: 338 printf("0x%x", flags & ACPI_MADT_POLARITY_MASK); 339 break; 340 } 341 printf(", Trigger="); 342 switch (flags & ACPI_MADT_TRIGGER_MASK) { 343 case ACPI_MADT_TRIGGER_CONFORMS: 344 printf("conforming"); 345 break; 346 case ACPI_MADT_TRIGGER_EDGE: 347 printf("edge"); 348 break; 349 case ACPI_MADT_TRIGGER_LEVEL: 350 printf("level"); 351 break; 352 default: 353 printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2); 354 } 355 printf("}\n"); 356 } 357 358 static void 359 acpi_print_gicc_flags(uint32_t flags) 360 { 361 362 printf("\tFlags={Performance intr="); 363 if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE) 364 printf("edge"); 365 else 366 printf("level"); 367 printf(", VGIC intr="); 368 if (flags & ACPI_MADT_VGIC_IRQ_MODE) 369 printf("edge"); 370 else 371 printf("level"); 372 printf("}\n"); 373 } 374 375 static void 376 acpi_print_intr(uint32_t intr, uint16_t mps_flags) 377 { 378 379 printf("\tINTR=%d\n", intr); 380 acpi_print_mps_flags(mps_flags); 381 } 382 383 static void 384 acpi_print_local_nmi(u_int lint, uint16_t mps_flags) 385 { 386 387 printf("\tLINT Pin=%d\n", lint); 388 acpi_print_mps_flags(mps_flags); 389 } 390 391 static const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", 392 "NMI", "Local APIC NMI", 393 "Local APIC Override", "IO SAPIC", 394 "Local SAPIC", "Platform Interrupt", 395 "Local X2APIC", "Local X2APIC NMI", 396 "GIC CPU Interface Structure", 397 "GIC Distributor Structure", 398 "GICv2m MSI Frame", 399 "GIC Redistributor Structure", 400 "GIC ITS Structure" }; 401 static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT", 402 "Corrected Platform Error" }; 403 404 static void 405 acpi_print_madt(ACPI_SUBTABLE_HEADER *mp) 406 { 407 ACPI_MADT_LOCAL_APIC *lapic; 408 ACPI_MADT_IO_APIC *ioapic; 409 ACPI_MADT_INTERRUPT_OVERRIDE *over; 410 ACPI_MADT_NMI_SOURCE *nmi; 411 ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi; 412 ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over; 413 ACPI_MADT_IO_SAPIC *iosapic; 414 ACPI_MADT_LOCAL_SAPIC *lsapic; 415 ACPI_MADT_INTERRUPT_SOURCE *isrc; 416 ACPI_MADT_LOCAL_X2APIC *x2apic; 417 ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi; 418 ACPI_MADT_GENERIC_INTERRUPT *gicc; 419 ACPI_MADT_GENERIC_DISTRIBUTOR *gicd; 420 ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr; 421 ACPI_MADT_GENERIC_TRANSLATOR *gict; 422 423 if (mp->Type < nitems(apic_types)) 424 printf("\tType=%s\n", apic_types[mp->Type]); 425 else 426 printf("\tType=%d (unknown)\n", mp->Type); 427 switch (mp->Type) { 428 case ACPI_MADT_TYPE_LOCAL_APIC: 429 lapic = (ACPI_MADT_LOCAL_APIC *)mp; 430 acpi_print_cpu(lapic->ProcessorId); 431 acpi_print_local_apic(lapic->Id, lapic->LapicFlags); 432 break; 433 case ACPI_MADT_TYPE_IO_APIC: 434 ioapic = (ACPI_MADT_IO_APIC *)mp; 435 acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase, 436 ioapic->Address); 437 break; 438 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 439 over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp; 440 printf("\tBUS=%d\n", (u_int)over->Bus); 441 printf("\tIRQ=%d\n", (u_int)over->SourceIrq); 442 acpi_print_intr(over->GlobalIrq, over->IntiFlags); 443 break; 444 case ACPI_MADT_TYPE_NMI_SOURCE: 445 nmi = (ACPI_MADT_NMI_SOURCE *)mp; 446 acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags); 447 break; 448 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 449 lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp; 450 acpi_print_cpu(lapic_nmi->ProcessorId); 451 acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags); 452 break; 453 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: 454 lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp; 455 printf("\tLocal APIC ADDR=0x%016jx\n", 456 (uintmax_t)lapic_over->Address); 457 break; 458 case ACPI_MADT_TYPE_IO_SAPIC: 459 iosapic = (ACPI_MADT_IO_SAPIC *)mp; 460 acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase, 461 iosapic->Address); 462 break; 463 case ACPI_MADT_TYPE_LOCAL_SAPIC: 464 lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp; 465 acpi_print_cpu(lsapic->ProcessorId); 466 acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags); 467 printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid); 468 if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid)) 469 acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString); 470 break; 471 case ACPI_MADT_TYPE_INTERRUPT_SOURCE: 472 isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp; 473 if (isrc->Type < nitems(platform_int_types)) 474 printf("\tType=%s\n", platform_int_types[isrc->Type]); 475 else 476 printf("\tType=%d (unknown)\n", isrc->Type); 477 printf("\tAPIC ID=%d\n", (u_int)isrc->Id); 478 printf("\tAPIC EID=%d\n", (u_int)isrc->Eid); 479 printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector); 480 acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags); 481 break; 482 case ACPI_MADT_TYPE_LOCAL_X2APIC: 483 x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp; 484 acpi_print_cpu_uid(x2apic->Uid, NULL); 485 acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags); 486 break; 487 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 488 x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp; 489 acpi_print_cpu_uid(x2apic_nmi->Uid, NULL); 490 acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags); 491 break; 492 case ACPI_MADT_TYPE_GENERIC_INTERRUPT: 493 gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp; 494 acpi_print_cpu_uid(gicc->Uid, NULL); 495 printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber); 496 acpi_print_gicc_flags(gicc->Flags); 497 printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion); 498 printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt); 499 printf("\tParked ADDR=%016jx\n", 500 (uintmax_t)gicc->ParkedAddress); 501 printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress); 502 printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress); 503 printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress); 504 printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt); 505 printf("\tGICR ADDR=%016jx\n", 506 (uintmax_t)gicc->GicrBaseAddress); 507 printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr); 508 printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass); 509 break; 510 case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: 511 gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp; 512 printf("\tGIC ID=%d\n", (u_int)gicd->GicId); 513 printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress); 514 printf("\tVector Base=%d\n", gicd->GlobalIrqBase); 515 printf("\tGIC VERSION=%d\n", (u_int)gicd->Version); 516 break; 517 case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR: 518 gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp; 519 printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress); 520 printf("\tLength=%08x\n", gicr->Length); 521 break; 522 case ACPI_MADT_TYPE_GENERIC_TRANSLATOR: 523 gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp; 524 printf("\tGIC ITS ID=%d\n", gict->TranslationId); 525 printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress); 526 break; 527 } 528 } 529 530 static void 531 acpi_handle_madt(ACPI_TABLE_HEADER *sdp) 532 { 533 ACPI_TABLE_MADT *madt; 534 535 printf(BEGIN_COMMENT); 536 acpi_print_sdt(sdp); 537 madt = (ACPI_TABLE_MADT *)sdp; 538 printf("\tLocal APIC ADDR=0x%08x\n", madt->Address); 539 printf("\tFlags={"); 540 if (madt->Flags & ACPI_MADT_PCAT_COMPAT) 541 printf("PC-AT"); 542 printf("}\n"); 543 acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt); 544 printf(END_COMMENT); 545 } 546 547 static void 548 acpi_handle_hpet(ACPI_TABLE_HEADER *sdp) 549 { 550 ACPI_TABLE_HPET *hpet; 551 552 printf(BEGIN_COMMENT); 553 acpi_print_sdt(sdp); 554 hpet = (ACPI_TABLE_HPET *)sdp; 555 printf("\tHPET Number=%d\n", hpet->Sequence); 556 printf("\tADDR="); 557 acpi_print_gas(&hpet->Address); 558 printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID); 559 printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >> 560 8); 561 printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ? 562 1 : 0); 563 printf("\tLegacy IRQ routing capable={"); 564 if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE) 565 printf("TRUE}\n"); 566 else 567 printf("FALSE}\n"); 568 printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16); 569 printf("\tMinimal Tick=%d\n", hpet->MinimumTick); 570 printf("\tFlags=0x%02x\n", hpet->Flags); 571 printf(END_COMMENT); 572 } 573 574 static void 575 acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp) 576 { 577 ACPI_TABLE_ECDT *ecdt; 578 579 printf(BEGIN_COMMENT); 580 acpi_print_sdt(sdp); 581 ecdt = (ACPI_TABLE_ECDT *)sdp; 582 printf("\tEC_CONTROL="); 583 acpi_print_gas(&ecdt->Control); 584 printf("\n\tEC_DATA="); 585 acpi_print_gas(&ecdt->Data); 586 printf("\n\tUID=%#x, ", ecdt->Uid); 587 printf("GPE_BIT=%#x\n", ecdt->Gpe); 588 printf("\tEC_ID=%s\n", ecdt->Id); 589 printf(END_COMMENT); 590 } 591 592 static void 593 acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp) 594 { 595 ACPI_TABLE_MCFG *mcfg; 596 ACPI_MCFG_ALLOCATION *alloc; 597 u_int i, entries; 598 599 printf(BEGIN_COMMENT); 600 acpi_print_sdt(sdp); 601 mcfg = (ACPI_TABLE_MCFG *)sdp; 602 entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) / 603 sizeof(ACPI_MCFG_ALLOCATION); 604 alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1); 605 for (i = 0; i < entries; i++, alloc++) { 606 printf("\n"); 607 printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address); 608 printf("\tSegment Group=0x%04x\n", alloc->PciSegment); 609 printf("\tStart Bus=%d\n", alloc->StartBusNumber); 610 printf("\tEnd Bus=%d\n", alloc->EndBusNumber); 611 } 612 printf(END_COMMENT); 613 } 614 615 static void 616 acpi_handle_slit(ACPI_TABLE_HEADER *sdp) 617 { 618 ACPI_TABLE_SLIT *slit; 619 UINT64 i, j; 620 621 printf(BEGIN_COMMENT); 622 acpi_print_sdt(sdp); 623 slit = (ACPI_TABLE_SLIT *)sdp; 624 printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount); 625 printf("\n\t "); 626 for (i = 0; i < slit->LocalityCount; i++) 627 printf(" %3ju", (uintmax_t)i); 628 printf("\n\t +"); 629 for (i = 0; i < slit->LocalityCount; i++) 630 printf("----"); 631 printf("\n"); 632 for (i = 0; i < slit->LocalityCount; i++) { 633 printf("\t %3ju |", (uintmax_t)i); 634 for (j = 0; j < slit->LocalityCount; j++) 635 printf(" %3d", 636 slit->Entry[i * slit->LocalityCount + j]); 637 printf("\n"); 638 } 639 printf(END_COMMENT); 640 } 641 642 static void 643 acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain, 644 uint32_t flags) 645 { 646 647 printf("\tFlags={"); 648 if (flags & ACPI_SRAT_CPU_ENABLED) 649 printf("ENABLED"); 650 else 651 printf("DISABLED"); 652 printf("}\n"); 653 printf("\tAPIC ID=%d\n", apic_id); 654 printf("\tProximity Domain=%d\n", proximity_domain); 655 } 656 657 static char * 658 acpi_tcpa_evname(struct TCPAevent *event) 659 { 660 struct TCPApc_event *pc_event; 661 char *eventname = NULL; 662 663 pc_event = (struct TCPApc_event *)(event + 1); 664 665 switch(event->event_type) { 666 case PREBOOT: 667 case POST_CODE: 668 case UNUSED: 669 case NO_ACTION: 670 case SEPARATOR: 671 case SCRTM_CONTENTS: 672 case SCRTM_VERSION: 673 case CPU_MICROCODE: 674 case PLATFORM_CONFIG_FLAGS: 675 case TABLE_OF_DEVICES: 676 case COMPACT_HASH: 677 case IPL: 678 case IPL_PARTITION_DATA: 679 case NONHOST_CODE: 680 case NONHOST_CONFIG: 681 case NONHOST_INFO: 682 asprintf(&eventname, "%s", 683 tcpa_event_type_strings[event->event_type]); 684 break; 685 686 case ACTION: 687 eventname = calloc(event->event_size + 1, sizeof(char)); 688 memcpy(eventname, pc_event, event->event_size); 689 break; 690 691 case EVENT_TAG: 692 switch (pc_event->event_id) { 693 case SMBIOS: 694 case BIS_CERT: 695 case CMOS: 696 case NVRAM: 697 case OPTION_ROM_EXEC: 698 case OPTION_ROM_CONFIG: 699 case S_CRTM_VERSION: 700 case POST_BIOS_ROM: 701 case ESCD: 702 case OPTION_ROM_MICROCODE: 703 case S_CRTM_CONTENTS: 704 case POST_CONTENTS: 705 asprintf(&eventname, "%s", 706 TCPA_pcclient_strings[pc_event->event_id]); 707 break; 708 709 default: 710 asprintf(&eventname, "<unknown tag 0x%02x>", 711 pc_event->event_id); 712 break; 713 } 714 break; 715 716 default: 717 asprintf(&eventname, "<unknown 0x%02x>", event->event_type); 718 break; 719 } 720 721 return eventname; 722 } 723 724 static void 725 acpi_print_tcpa(struct TCPAevent *event) 726 { 727 int i; 728 char *eventname; 729 730 eventname = acpi_tcpa_evname(event); 731 732 printf("\t%d", event->pcr_index); 733 printf(" 0x"); 734 for (i = 0; i < 20; i++) 735 printf("%02x", event->pcr_value[i]); 736 printf(" [%s]\n", eventname ? eventname : "<unknown>"); 737 738 free(eventname); 739 } 740 741 static void 742 acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp) 743 { 744 struct TCPAbody *tcpa; 745 struct TCPAevent *event; 746 uintmax_t len, paddr; 747 unsigned char *vaddr = NULL; 748 unsigned char *vend = NULL; 749 750 printf(BEGIN_COMMENT); 751 acpi_print_sdt(sdp); 752 tcpa = (struct TCPAbody *) sdp; 753 754 switch (tcpa->platform_class) { 755 case ACPI_TCPA_BIOS_CLIENT: 756 len = tcpa->client.log_max_len; 757 paddr = tcpa->client.log_start_addr; 758 break; 759 760 case ACPI_TCPA_BIOS_SERVER: 761 len = tcpa->server.log_max_len; 762 paddr = tcpa->server.log_start_addr; 763 break; 764 765 default: 766 printf("XXX"); 767 printf(END_COMMENT); 768 return; 769 } 770 printf("\tClass %u Base Address 0x%jx Length %ju\n\n", 771 tcpa->platform_class, paddr, len); 772 773 if (len == 0) { 774 printf("\tEmpty TCPA table\n"); 775 printf(END_COMMENT); 776 return; 777 } 778 if(sdp->Revision == 1){ 779 printf("\tOLD TCPA spec log found. Dumping not supported.\n"); 780 printf(END_COMMENT); 781 return; 782 } 783 784 vaddr = (unsigned char *)acpi_map_physical(paddr, len); 785 vend = vaddr + len; 786 787 while (vaddr != NULL) { 788 if ((vaddr + sizeof(struct TCPAevent) >= vend)|| 789 (vaddr + sizeof(struct TCPAevent) < vaddr)) 790 break; 791 event = (struct TCPAevent *)(void *)vaddr; 792 if (vaddr + event->event_size >= vend) 793 break; 794 if (vaddr + event->event_size < vaddr) 795 break; 796 if (event->event_type == 0 && event->event_size == 0) 797 break; 798 #if 0 799 { 800 unsigned int i, j, k; 801 802 printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr); 803 for (j = 0, i = 0; i < 804 sizeof(struct TCPAevent) + event->event_size; i++) { 805 printf("%02x ", vaddr[i]); 806 if ((i+1) % 8 == 0) { 807 for (k = 0; k < 8; k++) 808 printf("%c", isprint(vaddr[j+k]) ? 809 vaddr[j+k] : '.'); 810 printf("\n\t\t%p ", &vaddr[i + 1]); 811 j = i + 1; 812 } 813 } 814 printf("\n"); } 815 #endif 816 acpi_print_tcpa(event); 817 818 vaddr += sizeof(struct TCPAevent) + event->event_size; 819 } 820 821 printf(END_COMMENT); 822 } 823 824 static const char * 825 devscope_type2str(int type) 826 { 827 static char typebuf[16]; 828 829 switch (type) { 830 case 1: 831 return ("PCI Endpoint Device"); 832 case 2: 833 return ("PCI Sub-Hierarchy"); 834 case 3: 835 return ("IOAPIC"); 836 case 4: 837 return ("HPET"); 838 default: 839 snprintf(typebuf, sizeof(typebuf), "%d", type); 840 return (typebuf); 841 } 842 } 843 844 static int 845 acpi_handle_dmar_devscope(void *addr, int remaining) 846 { 847 char sep; 848 int pathlen; 849 ACPI_DMAR_PCI_PATH *path, *pathend; 850 ACPI_DMAR_DEVICE_SCOPE *devscope = addr; 851 852 if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE)) 853 return (-1); 854 855 if (remaining < devscope->Length) 856 return (-1); 857 858 printf("\n"); 859 printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType)); 860 printf("\t\tLength=%d\n", devscope->Length); 861 printf("\t\tEnumerationId=%d\n", devscope->EnumerationId); 862 printf("\t\tStartBusNumber=%d\n", devscope->Bus); 863 864 path = (ACPI_DMAR_PCI_PATH *)(devscope + 1); 865 pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE); 866 pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH); 867 if (path < pathend) { 868 sep = '{'; 869 printf("\t\tPath="); 870 do { 871 printf("%c%d:%d", sep, path->Device, path->Function); 872 sep=','; 873 path++; 874 } while (path < pathend); 875 printf("}\n"); 876 } 877 878 return (devscope->Length); 879 } 880 881 static void 882 acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd) 883 { 884 char *cp; 885 int remaining, consumed; 886 887 printf("\n"); 888 printf("\tType=DRHD\n"); 889 printf("\tLength=%d\n", drhd->Header.Length); 890 891 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag) 892 893 printf("\tFlags="); 894 PRINTFLAG(drhd->Flags, INCLUDE_ALL); 895 PRINTFLAG_END(); 896 897 #undef PRINTFLAG 898 899 printf("\tSegment=%d\n", drhd->Segment); 900 printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address); 901 902 remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT); 903 if (remaining > 0) 904 printf("\tDevice Scope:"); 905 while (remaining > 0) { 906 cp = (char *)drhd + drhd->Header.Length - remaining; 907 consumed = acpi_handle_dmar_devscope(cp, remaining); 908 if (consumed <= 0) 909 break; 910 else 911 remaining -= consumed; 912 } 913 } 914 915 static void 916 acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr) 917 { 918 char *cp; 919 int remaining, consumed; 920 921 printf("\n"); 922 printf("\tType=RMRR\n"); 923 printf("\tLength=%d\n", rmrr->Header.Length); 924 printf("\tSegment=%d\n", rmrr->Segment); 925 printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress); 926 printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress); 927 928 remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY); 929 if (remaining > 0) 930 printf("\tDevice Scope:"); 931 while (remaining > 0) { 932 cp = (char *)rmrr + rmrr->Header.Length - remaining; 933 consumed = acpi_handle_dmar_devscope(cp, remaining); 934 if (consumed <= 0) 935 break; 936 else 937 remaining -= consumed; 938 } 939 } 940 941 static void 942 acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr) 943 { 944 char *cp; 945 int remaining, consumed; 946 947 printf("\n"); 948 printf("\tType=ATSR\n"); 949 printf("\tLength=%d\n", atsr->Header.Length); 950 951 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag) 952 953 printf("\tFlags="); 954 PRINTFLAG(atsr->Flags, ALL_PORTS); 955 PRINTFLAG_END(); 956 957 #undef PRINTFLAG 958 959 printf("\tSegment=%d\n", atsr->Segment); 960 961 remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR); 962 if (remaining > 0) 963 printf("\tDevice Scope:"); 964 while (remaining > 0) { 965 cp = (char *)atsr + atsr->Header.Length - remaining; 966 consumed = acpi_handle_dmar_devscope(cp, remaining); 967 if (consumed <= 0) 968 break; 969 else 970 remaining -= consumed; 971 } 972 } 973 974 static void 975 acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa) 976 { 977 978 printf("\n"); 979 printf("\tType=RHSA\n"); 980 printf("\tLength=%d\n", rhsa->Header.Length); 981 printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress); 982 printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain); 983 } 984 985 static int 986 acpi_handle_dmar_remapping_structure(void *addr, int remaining) 987 { 988 ACPI_DMAR_HEADER *hdr = addr; 989 990 if (remaining < (int)sizeof(ACPI_DMAR_HEADER)) 991 return (-1); 992 993 if (remaining < hdr->Length) 994 return (-1); 995 996 switch (hdr->Type) { 997 case ACPI_DMAR_TYPE_HARDWARE_UNIT: 998 acpi_handle_dmar_drhd(addr); 999 break; 1000 case ACPI_DMAR_TYPE_RESERVED_MEMORY: 1001 acpi_handle_dmar_rmrr(addr); 1002 break; 1003 case ACPI_DMAR_TYPE_ROOT_ATS: 1004 acpi_handle_dmar_atsr(addr); 1005 break; 1006 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY: 1007 acpi_handle_dmar_rhsa(addr); 1008 break; 1009 default: 1010 printf("\n"); 1011 printf("\tType=%d\n", hdr->Type); 1012 printf("\tLength=%d\n", hdr->Length); 1013 break; 1014 } 1015 return (hdr->Length); 1016 } 1017 1018 #ifndef ACPI_DMAR_X2APIC_OPT_OUT 1019 #define ACPI_DMAR_X2APIC_OPT_OUT (0x2) 1020 #endif 1021 1022 static void 1023 acpi_handle_dmar(ACPI_TABLE_HEADER *sdp) 1024 { 1025 char *cp; 1026 int remaining, consumed; 1027 ACPI_TABLE_DMAR *dmar; 1028 1029 printf(BEGIN_COMMENT); 1030 acpi_print_sdt(sdp); 1031 dmar = (ACPI_TABLE_DMAR *)sdp; 1032 printf("\tHost Address Width=%d\n", dmar->Width + 1); 1033 1034 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag) 1035 1036 printf("\tFlags="); 1037 PRINTFLAG(dmar->Flags, INTR_REMAP); 1038 PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT); 1039 PRINTFLAG_END(); 1040 1041 #undef PRINTFLAG 1042 1043 remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR); 1044 while (remaining > 0) { 1045 cp = (char *)sdp + sdp->Length - remaining; 1046 consumed = acpi_handle_dmar_remapping_structure(cp, remaining); 1047 if (consumed <= 0) 1048 break; 1049 else 1050 remaining -= consumed; 1051 } 1052 1053 printf(END_COMMENT); 1054 } 1055 1056 static void 1057 acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp) 1058 { 1059 1060 printf("\tFlags={"); 1061 if (mp->Flags & ACPI_SRAT_MEM_ENABLED) 1062 printf("ENABLED"); 1063 else 1064 printf("DISABLED"); 1065 if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) 1066 printf(",HOT_PLUGGABLE"); 1067 if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE) 1068 printf(",NON_VOLATILE"); 1069 printf("}\n"); 1070 printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress); 1071 printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length); 1072 printf("\tProximity Domain=%d\n", mp->ProximityDomain); 1073 } 1074 1075 static const char *srat_types[] = { "CPU", "Memory", "X2APIC", "GICC" }; 1076 1077 static void 1078 acpi_print_srat(ACPI_SUBTABLE_HEADER *srat) 1079 { 1080 ACPI_SRAT_CPU_AFFINITY *cpu; 1081 ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic; 1082 ACPI_SRAT_GICC_AFFINITY *gic; 1083 1084 if (srat->Type < nitems(srat_types)) 1085 printf("\tType=%s\n", srat_types[srat->Type]); 1086 else 1087 printf("\tType=%d (unknown)\n", srat->Type); 1088 switch (srat->Type) { 1089 case ACPI_SRAT_TYPE_CPU_AFFINITY: 1090 cpu = (ACPI_SRAT_CPU_AFFINITY *)srat; 1091 acpi_print_srat_cpu(cpu->ApicId, 1092 cpu->ProximityDomainHi[2] << 24 | 1093 cpu->ProximityDomainHi[1] << 16 | 1094 cpu->ProximityDomainHi[0] << 0 | 1095 cpu->ProximityDomainLo, cpu->Flags); 1096 break; 1097 case ACPI_SRAT_TYPE_MEMORY_AFFINITY: 1098 acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat); 1099 break; 1100 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: 1101 x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat; 1102 acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain, 1103 x2apic->Flags); 1104 break; 1105 case ACPI_SRAT_TYPE_GICC_AFFINITY: 1106 gic = (ACPI_SRAT_GICC_AFFINITY *)srat; 1107 acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain, 1108 gic->Flags); 1109 break; 1110 } 1111 } 1112 1113 static void 1114 acpi_handle_srat(ACPI_TABLE_HEADER *sdp) 1115 { 1116 ACPI_TABLE_SRAT *srat; 1117 1118 printf(BEGIN_COMMENT); 1119 acpi_print_sdt(sdp); 1120 srat = (ACPI_TABLE_SRAT *)sdp; 1121 printf("\tTable Revision=%d\n", srat->TableRevision); 1122 acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat); 1123 printf(END_COMMENT); 1124 } 1125 1126 static void 1127 acpi_print_sdt(ACPI_TABLE_HEADER *sdp) 1128 { 1129 printf(" "); 1130 acpi_print_string(sdp->Signature, ACPI_NAME_SIZE); 1131 printf(": Length=%d, Revision=%d, Checksum=%d,\n", 1132 sdp->Length, sdp->Revision, sdp->Checksum); 1133 printf("\tOEMID="); 1134 acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE); 1135 printf(", OEM Table ID="); 1136 acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE); 1137 printf(", OEM Revision=0x%x,\n", sdp->OemRevision); 1138 printf("\tCreator ID="); 1139 acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE); 1140 printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision); 1141 } 1142 1143 static void 1144 acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp) 1145 { 1146 ACPI_TABLE_RSDT *rsdt; 1147 ACPI_TABLE_XSDT *xsdt; 1148 int i, entries; 1149 1150 rsdt = (ACPI_TABLE_RSDT *)rsdp; 1151 xsdt = (ACPI_TABLE_XSDT *)rsdp; 1152 printf(BEGIN_COMMENT); 1153 acpi_print_sdt(rsdp); 1154 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size; 1155 printf("\tEntries={ "); 1156 for (i = 0; i < entries; i++) { 1157 if (i > 0) 1158 printf(", "); 1159 if (addr_size == 4) 1160 printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i])); 1161 else 1162 printf("0x%016jx", 1163 (uintmax_t)le64toh(xsdt->TableOffsetEntry[i])); 1164 } 1165 printf(" }\n"); 1166 printf(END_COMMENT); 1167 } 1168 1169 static const char *acpi_pm_profiles[] = { 1170 "Unspecified", "Desktop", "Mobile", "Workstation", 1171 "Enterprise Server", "SOHO Server", "Appliance PC" 1172 }; 1173 1174 static void 1175 acpi_print_fadt(ACPI_TABLE_HEADER *sdp) 1176 { 1177 ACPI_TABLE_FADT *fadt; 1178 const char *pm; 1179 1180 fadt = (ACPI_TABLE_FADT *)sdp; 1181 printf(BEGIN_COMMENT); 1182 acpi_print_sdt(sdp); 1183 printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs, 1184 fadt->Dsdt); 1185 printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC"); 1186 if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 1187 pm = "Reserved"; 1188 else 1189 pm = acpi_pm_profiles[fadt->PreferredProfile]; 1190 printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile); 1191 printf("\tSCI_INT=%d\n", fadt->SciInterrupt); 1192 printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand); 1193 printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable); 1194 printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable); 1195 printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest); 1196 printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl); 1197 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 1198 fadt->Pm1aEventBlock, 1199 fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1); 1200 if (fadt->Pm1bEventBlock != 0) 1201 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 1202 fadt->Pm1bEventBlock, 1203 fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1); 1204 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 1205 fadt->Pm1aControlBlock, 1206 fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1); 1207 if (fadt->Pm1bControlBlock != 0) 1208 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 1209 fadt->Pm1bControlBlock, 1210 fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1); 1211 if (fadt->Pm2ControlBlock != 0) 1212 printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 1213 fadt->Pm2ControlBlock, 1214 fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1); 1215 printf("\tPM_TMR_BLK=0x%x-0x%x\n", 1216 fadt->PmTimerBlock, 1217 fadt->PmTimerBlock + fadt->PmTimerLength - 1); 1218 if (fadt->Gpe0Block != 0) 1219 printf("\tGPE0_BLK=0x%x-0x%x\n", 1220 fadt->Gpe0Block, 1221 fadt->Gpe0Block + fadt->Gpe0BlockLength - 1); 1222 if (fadt->Gpe1Block != 0) 1223 printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 1224 fadt->Gpe1Block, 1225 fadt->Gpe1Block + fadt->Gpe1BlockLength - 1, 1226 fadt->Gpe1Base); 1227 if (fadt->CstControl != 0) 1228 printf("\tCST_CNT=0x%x\n", fadt->CstControl); 1229 printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n", 1230 fadt->C2Latency, fadt->C3Latency); 1231 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 1232 fadt->FlushSize, fadt->FlushStride); 1233 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 1234 fadt->DutyOffset, fadt->DutyWidth); 1235 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 1236 fadt->DayAlarm, fadt->MonthAlarm, fadt->Century); 1237 1238 #define PRINTFLAG(var, flag) printflag((var), ACPI_FADT_## flag, #flag) 1239 1240 printf("\tIAPC_BOOT_ARCH="); 1241 PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES); 1242 PRINTFLAG(fadt->BootFlags, 8042); 1243 PRINTFLAG(fadt->BootFlags, NO_VGA); 1244 PRINTFLAG(fadt->BootFlags, NO_MSI); 1245 PRINTFLAG(fadt->BootFlags, NO_ASPM); 1246 PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC); 1247 PRINTFLAG_END(); 1248 1249 printf("\tFlags="); 1250 PRINTFLAG(fadt->Flags, WBINVD); 1251 PRINTFLAG(fadt->Flags, WBINVD_FLUSH); 1252 PRINTFLAG(fadt->Flags, C1_SUPPORTED); 1253 PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED); 1254 PRINTFLAG(fadt->Flags, POWER_BUTTON); 1255 PRINTFLAG(fadt->Flags, SLEEP_BUTTON); 1256 PRINTFLAG(fadt->Flags, FIXED_RTC); 1257 PRINTFLAG(fadt->Flags, S4_RTC_WAKE); 1258 PRINTFLAG(fadt->Flags, 32BIT_TIMER); 1259 PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED); 1260 PRINTFLAG(fadt->Flags, RESET_REGISTER); 1261 PRINTFLAG(fadt->Flags, SEALED_CASE); 1262 PRINTFLAG(fadt->Flags, HEADLESS); 1263 PRINTFLAG(fadt->Flags, SLEEP_TYPE); 1264 PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE); 1265 PRINTFLAG(fadt->Flags, PLATFORM_CLOCK); 1266 PRINTFLAG(fadt->Flags, S4_RTC_VALID); 1267 PRINTFLAG(fadt->Flags, REMOTE_POWER_ON); 1268 PRINTFLAG(fadt->Flags, APIC_CLUSTER); 1269 PRINTFLAG(fadt->Flags, APIC_PHYSICAL); 1270 PRINTFLAG(fadt->Flags, HW_REDUCED); 1271 PRINTFLAG(fadt->Flags, LOW_POWER_S0); 1272 PRINTFLAG_END(); 1273 1274 #undef PRINTFLAG 1275 1276 if (fadt->Flags & ACPI_FADT_RESET_REGISTER) { 1277 printf("\tRESET_REG="); 1278 acpi_print_gas(&fadt->ResetRegister); 1279 printf(", RESET_VALUE=%#x\n", fadt->ResetValue); 1280 } 1281 if (acpi_get_fadt_revision(fadt) > 1) { 1282 printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs); 1283 printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt); 1284 printf("\tX_PM1a_EVT_BLK="); 1285 acpi_print_gas(&fadt->XPm1aEventBlock); 1286 if (fadt->XPm1bEventBlock.Address != 0) { 1287 printf("\n\tX_PM1b_EVT_BLK="); 1288 acpi_print_gas(&fadt->XPm1bEventBlock); 1289 } 1290 printf("\n\tX_PM1a_CNT_BLK="); 1291 acpi_print_gas(&fadt->XPm1aControlBlock); 1292 if (fadt->XPm1bControlBlock.Address != 0) { 1293 printf("\n\tX_PM1b_CNT_BLK="); 1294 acpi_print_gas(&fadt->XPm1bControlBlock); 1295 } 1296 if (fadt->XPm2ControlBlock.Address != 0) { 1297 printf("\n\tX_PM2_CNT_BLK="); 1298 acpi_print_gas(&fadt->XPm2ControlBlock); 1299 } 1300 printf("\n\tX_PM_TMR_BLK="); 1301 acpi_print_gas(&fadt->XPmTimerBlock); 1302 if (fadt->XGpe0Block.Address != 0) { 1303 printf("\n\tX_GPE0_BLK="); 1304 acpi_print_gas(&fadt->XGpe0Block); 1305 } 1306 if (fadt->XGpe1Block.Address != 0) { 1307 printf("\n\tX_GPE1_BLK="); 1308 acpi_print_gas(&fadt->XGpe1Block); 1309 } 1310 printf("\n"); 1311 } 1312 1313 printf(END_COMMENT); 1314 } 1315 1316 static void 1317 acpi_print_facs(ACPI_TABLE_FACS *facs) 1318 { 1319 printf(BEGIN_COMMENT); 1320 printf(" FACS:\tLength=%u, ", facs->Length); 1321 printf("HwSig=0x%08x, ", facs->HardwareSignature); 1322 printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector); 1323 1324 printf("\tGlobal_Lock="); 1325 if (facs->GlobalLock != 0) { 1326 if (facs->GlobalLock & ACPI_GLOCK_PENDING) 1327 printf("PENDING,"); 1328 if (facs->GlobalLock & ACPI_GLOCK_OWNED) 1329 printf("OWNED"); 1330 } 1331 printf("\n"); 1332 1333 printf("\tFlags="); 1334 if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT) 1335 printf("S4BIOS"); 1336 printf("\n"); 1337 1338 if (facs->XFirmwareWakingVector != 0) 1339 printf("\tX_Firm_Wake_Vec=%016jx\n", 1340 (uintmax_t)facs->XFirmwareWakingVector); 1341 printf("\tVersion=%u\n", facs->Version); 1342 1343 printf(END_COMMENT); 1344 } 1345 1346 static void 1347 acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp) 1348 { 1349 printf(BEGIN_COMMENT); 1350 acpi_print_sdt(dsdp); 1351 printf(END_COMMENT); 1352 } 1353 1354 int 1355 acpi_checksum(void *p, size_t length) 1356 { 1357 uint8_t *bp; 1358 uint8_t sum; 1359 1360 bp = p; 1361 sum = 0; 1362 while (length--) 1363 sum += *bp++; 1364 1365 return (sum); 1366 } 1367 1368 static ACPI_TABLE_HEADER * 1369 acpi_map_sdt(vm_offset_t pa) 1370 { 1371 ACPI_TABLE_HEADER *sp; 1372 1373 sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER)); 1374 sp = acpi_map_physical(pa, sp->Length); 1375 return (sp); 1376 } 1377 1378 static void 1379 acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp) 1380 { 1381 printf(BEGIN_COMMENT); 1382 printf(" RSD PTR: OEM="); 1383 acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE); 1384 printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x", 1385 rp->Revision); 1386 if (rp->Revision < 2) { 1387 printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress, 1388 rp->Checksum); 1389 } else { 1390 printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n", 1391 (uintmax_t)rp->XsdtPhysicalAddress, rp->Length, 1392 rp->ExtendedChecksum); 1393 } 1394 printf(END_COMMENT); 1395 } 1396 1397 static void 1398 acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp) 1399 { 1400 ACPI_TABLE_HEADER *sdp; 1401 ACPI_TABLE_RSDT *rsdt; 1402 ACPI_TABLE_XSDT *xsdt; 1403 vm_offset_t addr; 1404 int entries, i; 1405 1406 acpi_print_rsdt(rsdp); 1407 rsdt = (ACPI_TABLE_RSDT *)rsdp; 1408 xsdt = (ACPI_TABLE_XSDT *)rsdp; 1409 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size; 1410 for (i = 0; i < entries; i++) { 1411 if (addr_size == 4) 1412 addr = le32toh(rsdt->TableOffsetEntry[i]); 1413 else 1414 addr = le64toh(xsdt->TableOffsetEntry[i]); 1415 if (addr == 0) 1416 continue; 1417 sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr); 1418 if (acpi_checksum(sdp, sdp->Length)) { 1419 warnx("RSDT entry %d (sig %.4s) is corrupt", i, 1420 sdp->Signature); 1421 continue; 1422 } 1423 if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4)) 1424 acpi_handle_fadt(sdp); 1425 else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4)) 1426 acpi_handle_madt(sdp); 1427 else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4)) 1428 acpi_handle_hpet(sdp); 1429 else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4)) 1430 acpi_handle_ecdt(sdp); 1431 else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4)) 1432 acpi_handle_mcfg(sdp); 1433 else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4)) 1434 acpi_handle_slit(sdp); 1435 else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4)) 1436 acpi_handle_srat(sdp); 1437 else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4)) 1438 acpi_handle_tcpa(sdp); 1439 else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4)) 1440 acpi_handle_dmar(sdp); 1441 else { 1442 printf(BEGIN_COMMENT); 1443 acpi_print_sdt(sdp); 1444 printf(END_COMMENT); 1445 } 1446 } 1447 } 1448 1449 ACPI_TABLE_HEADER * 1450 sdt_load_devmem(void) 1451 { 1452 ACPI_TABLE_RSDP *rp; 1453 ACPI_TABLE_HEADER *rsdp; 1454 1455 rp = acpi_find_rsd_ptr(); 1456 if (!rp) 1457 errx(1, "Can't find ACPI information"); 1458 1459 if (tflag) 1460 acpi_print_rsd_ptr(rp); 1461 if (rp->Revision < 2) { 1462 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress); 1463 if (memcmp(rsdp->Signature, "RSDT", 4) != 0 || 1464 acpi_checksum(rsdp, rsdp->Length) != 0) 1465 errx(1, "RSDT is corrupted"); 1466 addr_size = sizeof(uint32_t); 1467 } else { 1468 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress); 1469 if (memcmp(rsdp->Signature, "XSDT", 4) != 0 || 1470 acpi_checksum(rsdp, rsdp->Length) != 0) 1471 errx(1, "XSDT is corrupted"); 1472 addr_size = sizeof(uint64_t); 1473 } 1474 return (rsdp); 1475 } 1476 1477 /* Write the DSDT to a file, concatenating any SSDTs (if present). */ 1478 static int 1479 write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt) 1480 { 1481 ACPI_TABLE_HEADER sdt; 1482 ACPI_TABLE_HEADER *ssdt; 1483 uint8_t sum; 1484 1485 /* Create a new checksum to account for the DSDT and any SSDTs. */ 1486 sdt = *dsdt; 1487 if (rsdt != NULL) { 1488 sdt.Checksum = 0; 1489 sum = acpi_checksum(dsdt + 1, dsdt->Length - 1490 sizeof(ACPI_TABLE_HEADER)); 1491 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL); 1492 while (ssdt != NULL) { 1493 sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER); 1494 sum += acpi_checksum(ssdt + 1, 1495 ssdt->Length - sizeof(ACPI_TABLE_HEADER)); 1496 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt); 1497 } 1498 sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER)); 1499 sdt.Checksum -= sum; 1500 } 1501 1502 /* Write out the DSDT header and body. */ 1503 write(fd, &sdt, sizeof(ACPI_TABLE_HEADER)); 1504 write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER)); 1505 1506 /* Write out any SSDTs (if present.) */ 1507 if (rsdt != NULL) { 1508 ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL); 1509 while (ssdt != NULL) { 1510 write(fd, ssdt + 1, ssdt->Length - 1511 sizeof(ACPI_TABLE_HEADER)); 1512 ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt); 1513 } 1514 } 1515 return (0); 1516 } 1517 1518 void 1519 dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp) 1520 { 1521 int fd; 1522 mode_t mode; 1523 1524 assert(outfile != NULL); 1525 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 1526 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 1527 if (fd == -1) { 1528 perror("dsdt_save_file"); 1529 return; 1530 } 1531 write_dsdt(fd, rsdt, dsdp); 1532 close(fd); 1533 } 1534 1535 void 1536 aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp) 1537 { 1538 char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX]; 1539 const char *iname = "/acpdump.din"; 1540 const char *oname = "/acpdump.dsl"; 1541 const char *tmpdir; 1542 FILE *fp; 1543 size_t len; 1544 int fd, status; 1545 pid_t pid; 1546 1547 tmpdir = getenv("TMPDIR"); 1548 if (tmpdir == NULL) 1549 tmpdir = _PATH_TMP; 1550 if (realpath(tmpdir, buf) == NULL) { 1551 perror("realpath tmp dir"); 1552 return; 1553 } 1554 len = sizeof(wrkdir) - strlen(iname); 1555 if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) { 1556 fprintf(stderr, "$TMPDIR too long\n"); 1557 return; 1558 } 1559 if (mkdtemp(wrkdir) == NULL) { 1560 perror("mkdtemp tmp working dir"); 1561 return; 1562 } 1563 len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname); 1564 assert(len <= sizeof(tmpstr) - 1); 1565 fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); 1566 if (fd < 0) { 1567 perror("iasl tmp file"); 1568 return; 1569 } 1570 write_dsdt(fd, rsdt, dsdp); 1571 close(fd); 1572 1573 /* Run iasl -d on the temp file */ 1574 if ((pid = fork()) == 0) { 1575 close(STDOUT_FILENO); 1576 if (vflag == 0) 1577 close(STDERR_FILENO); 1578 execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL); 1579 err(1, "exec"); 1580 } 1581 if (pid > 0) 1582 wait(&status); 1583 if (unlink(tmpstr) < 0) { 1584 perror("unlink"); 1585 goto out; 1586 } 1587 if (pid < 0) { 1588 perror("fork"); 1589 goto out; 1590 } 1591 if (status != 0) { 1592 fprintf(stderr, "iast exit status = %d\n", status); 1593 } 1594 1595 /* Dump iasl's output to stdout */ 1596 len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname); 1597 assert(len <= sizeof(tmpstr) - 1); 1598 fp = fopen(tmpstr, "r"); 1599 if (unlink(tmpstr) < 0) { 1600 perror("unlink"); 1601 goto out; 1602 } 1603 if (fp == NULL) { 1604 perror("iasl tmp file (read)"); 1605 goto out; 1606 } 1607 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 1608 fwrite(buf, 1, len, stdout); 1609 fclose(fp); 1610 1611 out: 1612 if (rmdir(wrkdir) < 0) 1613 perror("rmdir"); 1614 } 1615 1616 void 1617 sdt_print_all(ACPI_TABLE_HEADER *rsdp) 1618 { 1619 acpi_handle_rsdt(rsdp); 1620 } 1621 1622 /* Fetch a table matching the given signature via the RSDT. */ 1623 ACPI_TABLE_HEADER * 1624 sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last) 1625 { 1626 ACPI_TABLE_HEADER *sdt; 1627 ACPI_TABLE_RSDT *rsdt; 1628 ACPI_TABLE_XSDT *xsdt; 1629 vm_offset_t addr; 1630 int entries, i; 1631 1632 rsdt = (ACPI_TABLE_RSDT *)rsdp; 1633 xsdt = (ACPI_TABLE_XSDT *)rsdp; 1634 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size; 1635 for (i = 0; i < entries; i++) { 1636 if (addr_size == 4) 1637 addr = le32toh(rsdt->TableOffsetEntry[i]); 1638 else 1639 addr = le64toh(xsdt->TableOffsetEntry[i]); 1640 if (addr == 0) 1641 continue; 1642 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr); 1643 if (last != NULL) { 1644 if (sdt == last) 1645 last = NULL; 1646 continue; 1647 } 1648 if (memcmp(sdt->Signature, sig, strlen(sig))) 1649 continue; 1650 if (acpi_checksum(sdt, sdt->Length)) 1651 errx(1, "RSDT entry %d is corrupt", i); 1652 return (sdt); 1653 } 1654 1655 return (NULL); 1656 } 1657 1658 ACPI_TABLE_HEADER * 1659 dsdt_from_fadt(ACPI_TABLE_FADT *fadt) 1660 { 1661 ACPI_TABLE_HEADER *sdt; 1662 1663 /* Use the DSDT address if it is version 1, otherwise use XDSDT. */ 1664 if (acpi_get_fadt_revision(fadt) == 1) 1665 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt); 1666 else 1667 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt); 1668 if (acpi_checksum(sdt, sdt->Length)) 1669 errx(1, "DSDT is corrupt\n"); 1670 return (sdt); 1671 } 1672