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