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