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