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_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain, 67 uint32_t flags); 68 static void acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp); 69 static void acpi_print_srat(ACPI_SUBTABLE_HEADER *srat); 70 static void acpi_handle_srat(ACPI_TABLE_HEADER *sdp); 71 static void acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp); 72 static void acpi_print_sdt(ACPI_TABLE_HEADER *sdp); 73 static void acpi_print_fadt(ACPI_TABLE_HEADER *sdp); 74 static void acpi_print_facs(ACPI_TABLE_FACS *facs); 75 static void acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp); 76 static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa); 77 static void acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp); 78 static void acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp); 79 static void acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first, 80 void (*action)(ACPI_SUBTABLE_HEADER *)); 81 82 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */ 83 static int addr_size; 84 85 /* Strings used in the TCPA table */ 86 static const char *tcpa_event_type_strings[] = { 87 "PREBOOT Certificate", 88 "POST Code", 89 "Unused", 90 "No Action", 91 "Separator", 92 "Action", 93 "Event Tag", 94 "S-CRTM Contents", 95 "S-CRTM Version", 96 "CPU Microcode", 97 "Platform Config Flags", 98 "Table of Devices", 99 "Compact Hash", 100 "IPL", 101 "IPL Partition Data", 102 "Non-Host Code", 103 "Non-Host Config", 104 "Non-Host Info" 105 }; 106 107 static const char *TCPA_pcclient_strings[] = { 108 "<undefined>", 109 "SMBIOS", 110 "BIS Certificate", 111 "POST BIOS ROM Strings", 112 "ESCD", 113 "CMOS", 114 "NVRAM", 115 "Option ROM Execute", 116 "Option ROM Configurateion", 117 "<undefined>", 118 "Option ROM Microcode Update ", 119 "S-CRTM Version String", 120 "S-CRTM Contents", 121 "POST Contents", 122 "Table of Devices", 123 }; 124 125 static void 126 acpi_print_string(char *s, size_t length) 127 { 128 int c; 129 130 /* Trim trailing spaces and NULLs */ 131 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 132 length--; 133 134 while (length--) { 135 c = *s++; 136 putchar(c); 137 } 138 } 139 140 static void 141 acpi_print_gas(ACPI_GENERIC_ADDRESS *gas) 142 { 143 switch(gas->SpaceId) { 144 case ACPI_GAS_MEMORY: 145 printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->Address, 146 gas->BitOffset, gas->BitWidth); 147 break; 148 case ACPI_GAS_IO: 149 printf("0x%02lx:%u[%u] (IO)", (u_long)gas->Address, 150 gas->BitOffset, gas->BitWidth); 151 break; 152 case ACPI_GAS_PCI: 153 printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32), 154 (uint16_t)((gas->Address >> 16) & 0xffff), 155 (uint16_t)gas->Address); 156 break; 157 /* XXX How to handle these below? */ 158 case ACPI_GAS_EMBEDDED: 159 printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address, 160 gas->BitOffset, gas->BitWidth); 161 break; 162 case ACPI_GAS_SMBUS: 163 printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address, 164 gas->BitOffset, gas->BitWidth); 165 break; 166 case ACPI_GAS_CMOS: 167 case ACPI_GAS_PCIBAR: 168 case ACPI_GAS_DATATABLE: 169 case ACPI_GAS_FIXED: 170 default: 171 printf("0x%08lx (?)", (u_long)gas->Address); 172 break; 173 } 174 } 175 176 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */ 177 static int 178 acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt) 179 { 180 int fadt_revision; 181 182 /* Set the FADT revision separately from the RSDP version. */ 183 if (addr_size == 8) { 184 fadt_revision = 2; 185 186 /* 187 * A few systems (e.g., IBM T23) have an RSDP that claims 188 * revision 2 but the 64 bit addresses are invalid. If 189 * revision 2 and the 32 bit address is non-zero but the 190 * 32 and 64 bit versions don't match, prefer the 32 bit 191 * version for all subsequent tables. 192 */ 193 if (fadt->Facs != 0 && 194 (fadt->XFacs & 0xffffffff) != fadt->Facs) 195 fadt_revision = 1; 196 } else 197 fadt_revision = 1; 198 return (fadt_revision); 199 } 200 201 static void 202 acpi_handle_fadt(ACPI_TABLE_HEADER *sdp) 203 { 204 ACPI_TABLE_HEADER *dsdp; 205 ACPI_TABLE_FACS *facs; 206 ACPI_TABLE_FADT *fadt; 207 int fadt_revision; 208 209 fadt = (ACPI_TABLE_FADT *)sdp; 210 acpi_print_fadt(sdp); 211 212 fadt_revision = acpi_get_fadt_revision(fadt); 213 if (fadt_revision == 1) 214 facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs); 215 else 216 facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs); 217 if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64) 218 errx(1, "FACS is corrupt"); 219 acpi_print_facs(facs); 220 221 if (fadt_revision == 1) 222 dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt); 223 else 224 dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt); 225 if (acpi_checksum(dsdp, dsdp->Length)) 226 errx(1, "DSDT is corrupt"); 227 acpi_print_dsdt(dsdp); 228 } 229 230 static void 231 acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first, 232 void (*action)(ACPI_SUBTABLE_HEADER *)) 233 { 234 ACPI_SUBTABLE_HEADER *subtable; 235 char *end; 236 237 subtable = first; 238 end = (char *)table + table->Length; 239 while ((char *)subtable < end) { 240 printf("\n"); 241 action(subtable); 242 subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable + 243 subtable->Length); 244 } 245 } 246 247 static void 248 acpi_print_cpu(u_char cpu_id) 249 { 250 251 printf("\tACPI CPU="); 252 if (cpu_id == 0xff) 253 printf("ALL\n"); 254 else 255 printf("%d\n", (u_int)cpu_id); 256 } 257 258 static void 259 acpi_print_cpu_uid(uint32_t uid, char *uid_string) 260 { 261 262 printf("\tUID=%d", uid); 263 if (uid_string != NULL) 264 printf(" (%s)", uid_string); 265 printf("\n"); 266 } 267 268 static void 269 acpi_print_local_apic(uint32_t apic_id, uint32_t flags) 270 { 271 272 printf("\tFlags={"); 273 if (flags & ACPI_MADT_ENABLED) 274 printf("ENABLED"); 275 else 276 printf("DISABLED"); 277 printf("}\n"); 278 printf("\tAPIC ID=%d\n", apic_id); 279 } 280 281 static void 282 acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr) 283 { 284 285 printf("\tAPIC ID=%d\n", apic_id); 286 printf("\tINT BASE=%d\n", int_base); 287 printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr); 288 } 289 290 static void 291 acpi_print_mps_flags(uint16_t flags) 292 { 293 294 printf("\tFlags={Polarity="); 295 switch (flags & ACPI_MADT_POLARITY_MASK) { 296 case ACPI_MADT_POLARITY_CONFORMS: 297 printf("conforming"); 298 break; 299 case ACPI_MADT_POLARITY_ACTIVE_HIGH: 300 printf("active-hi"); 301 break; 302 case ACPI_MADT_POLARITY_ACTIVE_LOW: 303 printf("active-lo"); 304 break; 305 default: 306 printf("0x%x", flags & ACPI_MADT_POLARITY_MASK); 307 break; 308 } 309 printf(", Trigger="); 310 switch (flags & ACPI_MADT_TRIGGER_MASK) { 311 case ACPI_MADT_TRIGGER_CONFORMS: 312 printf("conforming"); 313 break; 314 case ACPI_MADT_TRIGGER_EDGE: 315 printf("edge"); 316 break; 317 case ACPI_MADT_TRIGGER_LEVEL: 318 printf("level"); 319 break; 320 default: 321 printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2); 322 } 323 printf("}\n"); 324 } 325 326 static void 327 acpi_print_intr(uint32_t intr, uint16_t mps_flags) 328 { 329 330 printf("\tINTR=%d\n", intr); 331 acpi_print_mps_flags(mps_flags); 332 } 333 334 static void 335 acpi_print_local_nmi(u_int lint, uint16_t mps_flags) 336 { 337 338 printf("\tLINT Pin=%d\n", lint); 339 acpi_print_mps_flags(mps_flags); 340 } 341 342 const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 343 "Local APIC NMI", "Local APIC Override", 344 "IO SAPIC", "Local SAPIC", "Platform Interrupt", 345 "Local X2APIC", "Local X2APIC NMI" }; 346 const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT", 347 "Corrected Platform Error" }; 348 349 static void 350 acpi_print_madt(ACPI_SUBTABLE_HEADER *mp) 351 { 352 ACPI_MADT_LOCAL_APIC *lapic; 353 ACPI_MADT_IO_APIC *ioapic; 354 ACPI_MADT_INTERRUPT_OVERRIDE *over; 355 ACPI_MADT_NMI_SOURCE *nmi; 356 ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi; 357 ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over; 358 ACPI_MADT_IO_SAPIC *iosapic; 359 ACPI_MADT_LOCAL_SAPIC *lsapic; 360 ACPI_MADT_INTERRUPT_SOURCE *isrc; 361 ACPI_MADT_LOCAL_X2APIC *x2apic; 362 ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi; 363 364 if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0])) 365 printf("\tType=%s\n", apic_types[mp->Type]); 366 else 367 printf("\tType=%d (unknown)\n", mp->Type); 368 switch (mp->Type) { 369 case ACPI_MADT_TYPE_LOCAL_APIC: 370 lapic = (ACPI_MADT_LOCAL_APIC *)mp; 371 acpi_print_cpu(lapic->ProcessorId); 372 acpi_print_local_apic(lapic->Id, lapic->LapicFlags); 373 break; 374 case ACPI_MADT_TYPE_IO_APIC: 375 ioapic = (ACPI_MADT_IO_APIC *)mp; 376 acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase, 377 ioapic->Address); 378 break; 379 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 380 over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp; 381 printf("\tBUS=%d\n", (u_int)over->Bus); 382 printf("\tIRQ=%d\n", (u_int)over->SourceIrq); 383 acpi_print_intr(over->GlobalIrq, over->IntiFlags); 384 break; 385 case ACPI_MADT_TYPE_NMI_SOURCE: 386 nmi = (ACPI_MADT_NMI_SOURCE *)mp; 387 acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags); 388 break; 389 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 390 lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp; 391 acpi_print_cpu(lapic_nmi->ProcessorId); 392 acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags); 393 break; 394 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: 395 lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp; 396 printf("\tLocal APIC ADDR=0x%016jx\n", 397 (uintmax_t)lapic_over->Address); 398 break; 399 case ACPI_MADT_TYPE_IO_SAPIC: 400 iosapic = (ACPI_MADT_IO_SAPIC *)mp; 401 acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase, 402 iosapic->Address); 403 break; 404 case ACPI_MADT_TYPE_LOCAL_SAPIC: 405 lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp; 406 acpi_print_cpu(lsapic->ProcessorId); 407 acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags); 408 printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid); 409 if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid)) 410 acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString); 411 break; 412 case ACPI_MADT_TYPE_INTERRUPT_SOURCE: 413 isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp; 414 if (isrc->Type < sizeof(platform_int_types) / 415 sizeof(platform_int_types[0])) 416 printf("\tType=%s\n", platform_int_types[isrc->Type]); 417 else 418 printf("\tType=%d (unknown)\n", isrc->Type); 419 printf("\tAPIC ID=%d\n", (u_int)isrc->Id); 420 printf("\tAPIC EID=%d\n", (u_int)isrc->Eid); 421 printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector); 422 acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags); 423 break; 424 case ACPI_MADT_TYPE_LOCAL_X2APIC: 425 x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp; 426 acpi_print_cpu_uid(x2apic->Uid, NULL); 427 acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags); 428 break; 429 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: 430 x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp; 431 acpi_print_cpu_uid(x2apic_nmi->Uid, NULL); 432 acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags); 433 break; 434 } 435 } 436 437 static void 438 acpi_handle_madt(ACPI_TABLE_HEADER *sdp) 439 { 440 ACPI_TABLE_MADT *madt; 441 442 printf(BEGIN_COMMENT); 443 acpi_print_sdt(sdp); 444 madt = (ACPI_TABLE_MADT *)sdp; 445 printf("\tLocal APIC ADDR=0x%08x\n", madt->Address); 446 printf("\tFlags={"); 447 if (madt->Flags & ACPI_MADT_PCAT_COMPAT) 448 printf("PC-AT"); 449 printf("}\n"); 450 acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt); 451 printf(END_COMMENT); 452 } 453 454 static void 455 acpi_handle_hpet(ACPI_TABLE_HEADER *sdp) 456 { 457 ACPI_TABLE_HPET *hpet; 458 459 printf(BEGIN_COMMENT); 460 acpi_print_sdt(sdp); 461 hpet = (ACPI_TABLE_HPET *)sdp; 462 printf("\tHPET Number=%d\n", hpet->Sequence); 463 printf("\tADDR="); 464 acpi_print_gas(&hpet->Address); 465 printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID); 466 printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >> 467 8); 468 printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ? 469 1 : 0); 470 printf("\tLegacy IRQ routing capable={"); 471 if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE) 472 printf("TRUE}\n"); 473 else 474 printf("FALSE}\n"); 475 printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16); 476 printf("\tMinimal Tick=%d\n", hpet->MinimumTick); 477 printf(END_COMMENT); 478 } 479 480 static void 481 acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp) 482 { 483 ACPI_TABLE_ECDT *ecdt; 484 485 printf(BEGIN_COMMENT); 486 acpi_print_sdt(sdp); 487 ecdt = (ACPI_TABLE_ECDT *)sdp; 488 printf("\tEC_CONTROL="); 489 acpi_print_gas(&ecdt->Control); 490 printf("\n\tEC_DATA="); 491 acpi_print_gas(&ecdt->Data); 492 printf("\n\tUID=%#x, ", ecdt->Uid); 493 printf("GPE_BIT=%#x\n", ecdt->Gpe); 494 printf("\tEC_ID=%s\n", ecdt->Id); 495 printf(END_COMMENT); 496 } 497 498 static void 499 acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp) 500 { 501 ACPI_TABLE_MCFG *mcfg; 502 ACPI_MCFG_ALLOCATION *alloc; 503 u_int i, entries; 504 505 printf(BEGIN_COMMENT); 506 acpi_print_sdt(sdp); 507 mcfg = (ACPI_TABLE_MCFG *)sdp; 508 entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) / 509 sizeof(ACPI_MCFG_ALLOCATION); 510 alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1); 511 for (i = 0; i < entries; i++, alloc++) { 512 printf("\n"); 513 printf("\tBase Address=0x%016jx\n", alloc->Address); 514 printf("\tSegment Group=0x%04x\n", alloc->PciSegment); 515 printf("\tStart Bus=%d\n", alloc->StartBusNumber); 516 printf("\tEnd Bus=%d\n", alloc->EndBusNumber); 517 } 518 printf(END_COMMENT); 519 } 520 521 static void 522 acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain, 523 uint32_t flags) 524 { 525 526 printf("\tFlags={"); 527 if (flags & ACPI_SRAT_CPU_ENABLED) 528 printf("ENABLED"); 529 else 530 printf("DISABLED"); 531 printf("}\n"); 532 printf("\tAPIC ID=%d\n", apic_id); 533 printf("\tProximity Domain=%d\n", proximity_domain); 534 } 535 536 static char * 537 acpi_tcpa_evname(struct TCPAevent *event) 538 { 539 struct TCPApc_event *pc_event; 540 char *eventname = NULL; 541 542 pc_event = (struct TCPApc_event *)(event + 1); 543 544 switch(event->event_type) { 545 case PREBOOT: 546 case POST_CODE: 547 case UNUSED: 548 case NO_ACTION: 549 case SEPARATOR: 550 case SCRTM_CONTENTS: 551 case SCRTM_VERSION: 552 case CPU_MICROCODE: 553 case PLATFORM_CONFIG_FLAGS: 554 case TABLE_OF_DEVICES: 555 case COMPACT_HASH: 556 case IPL: 557 case IPL_PARTITION_DATA: 558 case NONHOST_CODE: 559 case NONHOST_CONFIG: 560 case NONHOST_INFO: 561 asprintf(&eventname, "%s", 562 tcpa_event_type_strings[event->event_type]); 563 break; 564 565 case ACTION: 566 eventname = calloc(event->event_size + 1, sizeof(char)); 567 memcpy(eventname, pc_event, event->event_size); 568 break; 569 570 case EVENT_TAG: 571 switch (pc_event->event_id) { 572 case SMBIOS: 573 case BIS_CERT: 574 case CMOS: 575 case NVRAM: 576 case OPTION_ROM_EXEC: 577 case OPTION_ROM_CONFIG: 578 case S_CRTM_VERSION: 579 case POST_BIOS_ROM: 580 case ESCD: 581 case OPTION_ROM_MICROCODE: 582 case S_CRTM_CONTENTS: 583 case POST_CONTENTS: 584 asprintf(&eventname, "%s", 585 TCPA_pcclient_strings[pc_event->event_id]); 586 break; 587 588 default: 589 asprintf(&eventname, "<unknown tag 0x%02x>", 590 pc_event->event_id); 591 break; 592 } 593 break; 594 595 default: 596 asprintf(&eventname, "<unknown 0x%02x>", event->event_type); 597 break; 598 } 599 600 return eventname; 601 } 602 603 static void 604 acpi_print_tcpa(struct TCPAevent *event) 605 { 606 int i; 607 char *eventname; 608 609 eventname = acpi_tcpa_evname(event); 610 611 printf("\t%d", event->pcr_index); 612 printf(" 0x"); 613 for (i = 0; i < 20; i++) 614 printf("%02x", event->pcr_value[i]); 615 printf(" [%s]\n", eventname ? eventname : "<unknown>"); 616 617 free(eventname); 618 } 619 620 static void 621 acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp) 622 { 623 struct TCPAbody *tcpa; 624 struct TCPAevent *event; 625 uintmax_t len, paddr; 626 unsigned char *vaddr = NULL; 627 unsigned char *vend = NULL; 628 629 printf(BEGIN_COMMENT); 630 acpi_print_sdt(sdp); 631 tcpa = (struct TCPAbody *) sdp; 632 633 switch (tcpa->platform_class) { 634 case ACPI_TCPA_BIOS_CLIENT: 635 len = tcpa->client.log_max_len; 636 paddr = tcpa->client.log_start_addr; 637 break; 638 639 case ACPI_TCPA_BIOS_SERVER: 640 len = tcpa->server.log_max_len; 641 paddr = tcpa->server.log_start_addr; 642 break; 643 644 default: 645 printf("XXX"); 646 printf(END_COMMENT); 647 return; 648 } 649 printf("\tClass %u Base Address 0x%jx Length %ju\n\n", 650 tcpa->platform_class, paddr, len); 651 652 if (len == 0) { 653 printf("\tEmpty TCPA table\n"); 654 printf(END_COMMENT); 655 return; 656 } 657 658 vaddr = (unsigned char *)acpi_map_physical(paddr, len); 659 vend = vaddr + len; 660 661 while (vaddr != NULL) { 662 if (vaddr + sizeof(struct TCPAevent) >= vend) 663 break; 664 event = (struct TCPAevent *)(void *)vaddr; 665 if (vaddr + event->event_size >= vend) 666 break; 667 if (event->event_type == 0 && event->event_size == 0) 668 break; 669 #if 0 670 { 671 unsigned int i, j, k; 672 673 printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr); 674 for (j = 0, i = 0; i < 675 sizeof(struct TCPAevent) + event->event_size; i++) { 676 printf("%02x ", vaddr[i]); 677 if ((i+1) % 8 == 0) { 678 for (k = 0; k < 8; k++) 679 printf("%c", isprint(vaddr[j+k]) ? 680 vaddr[j+k] : '.'); 681 printf("\n\t\t%p ", &vaddr[i + 1]); 682 j = i + 1; 683 } 684 } 685 printf("\n"); } 686 #endif 687 acpi_print_tcpa(event); 688 689 vaddr += sizeof(struct TCPAevent) + event->event_size; 690 } 691 692 printf(END_COMMENT); 693 } 694 695 static void 696 acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp) 697 { 698 699 printf("\tFlags={"); 700 if (mp->Flags & ACPI_SRAT_MEM_ENABLED) 701 printf("ENABLED"); 702 else 703 printf("DISABLED"); 704 if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) 705 printf(",HOT_PLUGGABLE"); 706 if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE) 707 printf(",NON_VOLATILE"); 708 printf("}\n"); 709 printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress); 710 printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length); 711 printf("\tProximity Domain=%d\n", mp->ProximityDomain); 712 } 713 714 const char *srat_types[] = { "CPU", "Memory", "X2APIC" }; 715 716 static void 717 acpi_print_srat(ACPI_SUBTABLE_HEADER *srat) 718 { 719 ACPI_SRAT_CPU_AFFINITY *cpu; 720 ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic; 721 722 if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0])) 723 printf("\tType=%s\n", srat_types[srat->Type]); 724 else 725 printf("\tType=%d (unknown)\n", srat->Type); 726 switch (srat->Type) { 727 case ACPI_SRAT_TYPE_CPU_AFFINITY: 728 cpu = (ACPI_SRAT_CPU_AFFINITY *)srat; 729 acpi_print_srat_cpu(cpu->ApicId, 730 cpu->ProximityDomainHi[2] << 24 | 731 cpu->ProximityDomainHi[1] << 16 | 732 cpu->ProximityDomainHi[0] << 0 | 733 cpu->ProximityDomainLo, cpu->Flags); 734 break; 735 case ACPI_SRAT_TYPE_MEMORY_AFFINITY: 736 acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat); 737 break; 738 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: 739 x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat; 740 acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain, 741 x2apic->Flags); 742 break; 743 } 744 } 745 746 static void 747 acpi_handle_srat(ACPI_TABLE_HEADER *sdp) 748 { 749 ACPI_TABLE_SRAT *srat; 750 751 printf(BEGIN_COMMENT); 752 acpi_print_sdt(sdp); 753 srat = (ACPI_TABLE_SRAT *)sdp; 754 printf("\tTable Revision=%d\n", srat->TableRevision); 755 acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat); 756 printf(END_COMMENT); 757 } 758 759 static void 760 acpi_print_sdt(ACPI_TABLE_HEADER *sdp) 761 { 762 printf(" "); 763 acpi_print_string(sdp->Signature, ACPI_NAME_SIZE); 764 printf(": Length=%d, Revision=%d, Checksum=%d,\n", 765 sdp->Length, sdp->Revision, sdp->Checksum); 766 printf("\tOEMID="); 767 acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE); 768 printf(", OEM Table ID="); 769 acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE); 770 printf(", OEM Revision=0x%x,\n", sdp->OemRevision); 771 printf("\tCreator ID="); 772 acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE); 773 printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision); 774 } 775 776 static void 777 acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp) 778 { 779 ACPI_TABLE_RSDT *rsdt; 780 ACPI_TABLE_XSDT *xsdt; 781 int i, entries; 782 u_long addr; 783 784 rsdt = (ACPI_TABLE_RSDT *)rsdp; 785 xsdt = (ACPI_TABLE_XSDT *)rsdp; 786 printf(BEGIN_COMMENT); 787 acpi_print_sdt(rsdp); 788 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size; 789 printf("\tEntries={ "); 790 for (i = 0; i < entries; i++) { 791 if (i > 0) 792 printf(", "); 793 switch (addr_size) { 794 case 4: 795 addr = le32toh(rsdt->TableOffsetEntry[i]); 796 break; 797 case 8: 798 addr = le64toh(xsdt->TableOffsetEntry[i]); 799 break; 800 default: 801 addr = 0; 802 } 803 assert(addr != 0); 804 printf("0x%08lx", addr); 805 } 806 printf(" }\n"); 807 printf(END_COMMENT); 808 } 809 810 static const char *acpi_pm_profiles[] = { 811 "Unspecified", "Desktop", "Mobile", "Workstation", 812 "Enterprise Server", "SOHO Server", "Appliance PC" 813 }; 814 815 static void 816 acpi_print_fadt(ACPI_TABLE_HEADER *sdp) 817 { 818 ACPI_TABLE_FADT *fadt; 819 const char *pm; 820 char sep; 821 822 fadt = (ACPI_TABLE_FADT *)sdp; 823 printf(BEGIN_COMMENT); 824 acpi_print_sdt(sdp); 825 printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs, 826 fadt->Dsdt); 827 printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC"); 828 if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 829 pm = "Reserved"; 830 else 831 pm = acpi_pm_profiles[fadt->PreferredProfile]; 832 printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile); 833 printf("\tSCI_INT=%d\n", fadt->SciInterrupt); 834 printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand); 835 printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable); 836 printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable); 837 printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest); 838 printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl); 839 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 840 fadt->Pm1aEventBlock, 841 fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1); 842 if (fadt->Pm1bEventBlock != 0) 843 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 844 fadt->Pm1bEventBlock, 845 fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1); 846 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 847 fadt->Pm1aControlBlock, 848 fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1); 849 if (fadt->Pm1bControlBlock != 0) 850 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 851 fadt->Pm1bControlBlock, 852 fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1); 853 if (fadt->Pm2ControlBlock != 0) 854 printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 855 fadt->Pm2ControlBlock, 856 fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1); 857 printf("\tPM_TMR_BLK=0x%x-0x%x\n", 858 fadt->PmTimerBlock, 859 fadt->PmTimerBlock + fadt->PmTimerLength - 1); 860 if (fadt->Gpe0Block != 0) 861 printf("\tGPE0_BLK=0x%x-0x%x\n", 862 fadt->Gpe0Block, 863 fadt->Gpe0Block + fadt->Gpe0BlockLength - 1); 864 if (fadt->Gpe1Block != 0) 865 printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 866 fadt->Gpe1Block, 867 fadt->Gpe1Block + fadt->Gpe1BlockLength - 1, 868 fadt->Gpe1Base); 869 if (fadt->CstControl != 0) 870 printf("\tCST_CNT=0x%x\n", fadt->CstControl); 871 printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n", 872 fadt->C2Latency, fadt->C3Latency); 873 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 874 fadt->FlushSize, fadt->FlushStride); 875 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 876 fadt->DutyOffset, fadt->DutyWidth); 877 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 878 fadt->DayAlarm, fadt->MonthAlarm, fadt->Century); 879 880 #define PRINTFLAG(var, flag) do { \ 881 if ((var) & ACPI_FADT_## flag) { \ 882 printf("%c%s", sep, #flag); sep = ','; \ 883 } \ 884 } while (0) 885 886 printf("\tIAPC_BOOT_ARCH="); 887 sep = '{'; 888 PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES); 889 PRINTFLAG(fadt->BootFlags, 8042); 890 PRINTFLAG(fadt->BootFlags, NO_VGA); 891 PRINTFLAG(fadt->BootFlags, NO_MSI); 892 PRINTFLAG(fadt->BootFlags, NO_ASPM); 893 if (fadt->BootFlags != 0) 894 printf("}"); 895 printf("\n"); 896 897 printf("\tFlags="); 898 sep = '{'; 899 PRINTFLAG(fadt->Flags, WBINVD); 900 PRINTFLAG(fadt->Flags, WBINVD_FLUSH); 901 PRINTFLAG(fadt->Flags, C1_SUPPORTED); 902 PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED); 903 PRINTFLAG(fadt->Flags, POWER_BUTTON); 904 PRINTFLAG(fadt->Flags, SLEEP_BUTTON); 905 PRINTFLAG(fadt->Flags, FIXED_RTC); 906 PRINTFLAG(fadt->Flags, S4_RTC_WAKE); 907 PRINTFLAG(fadt->Flags, 32BIT_TIMER); 908 PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED); 909 PRINTFLAG(fadt->Flags, RESET_REGISTER); 910 PRINTFLAG(fadt->Flags, SEALED_CASE); 911 PRINTFLAG(fadt->Flags, HEADLESS); 912 PRINTFLAG(fadt->Flags, SLEEP_TYPE); 913 PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE); 914 PRINTFLAG(fadt->Flags, PLATFORM_CLOCK); 915 PRINTFLAG(fadt->Flags, S4_RTC_VALID); 916 PRINTFLAG(fadt->Flags, REMOTE_POWER_ON); 917 PRINTFLAG(fadt->Flags, APIC_CLUSTER); 918 PRINTFLAG(fadt->Flags, APIC_PHYSICAL); 919 if (fadt->Flags != 0) 920 printf("}\n"); 921 922 #undef PRINTFLAG 923 924 if (fadt->Flags & ACPI_FADT_RESET_REGISTER) { 925 printf("\tRESET_REG="); 926 acpi_print_gas(&fadt->ResetRegister); 927 printf(", RESET_VALUE=%#x\n", fadt->ResetValue); 928 } 929 if (acpi_get_fadt_revision(fadt) > 1) { 930 printf("\tX_FACS=0x%08lx, ", (u_long)fadt->XFacs); 931 printf("X_DSDT=0x%08lx\n", (u_long)fadt->XDsdt); 932 printf("\tX_PM1a_EVT_BLK="); 933 acpi_print_gas(&fadt->XPm1aEventBlock); 934 if (fadt->XPm1bEventBlock.Address != 0) { 935 printf("\n\tX_PM1b_EVT_BLK="); 936 acpi_print_gas(&fadt->XPm1bEventBlock); 937 } 938 printf("\n\tX_PM1a_CNT_BLK="); 939 acpi_print_gas(&fadt->XPm1aControlBlock); 940 if (fadt->XPm1bControlBlock.Address != 0) { 941 printf("\n\tX_PM1b_CNT_BLK="); 942 acpi_print_gas(&fadt->XPm1bControlBlock); 943 } 944 if (fadt->XPm2ControlBlock.Address != 0) { 945 printf("\n\tX_PM2_CNT_BLK="); 946 acpi_print_gas(&fadt->XPm2ControlBlock); 947 } 948 printf("\n\tX_PM_TMR_BLK="); 949 acpi_print_gas(&fadt->XPmTimerBlock); 950 if (fadt->XGpe0Block.Address != 0) { 951 printf("\n\tX_GPE0_BLK="); 952 acpi_print_gas(&fadt->XGpe0Block); 953 } 954 if (fadt->XGpe1Block.Address != 0) { 955 printf("\n\tX_GPE1_BLK="); 956 acpi_print_gas(&fadt->XGpe1Block); 957 } 958 printf("\n"); 959 } 960 961 printf(END_COMMENT); 962 } 963 964 static void 965 acpi_print_facs(ACPI_TABLE_FACS *facs) 966 { 967 printf(BEGIN_COMMENT); 968 printf(" FACS:\tLength=%u, ", facs->Length); 969 printf("HwSig=0x%08x, ", facs->HardwareSignature); 970 printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector); 971 972 printf("\tGlobal_Lock="); 973 if (facs->GlobalLock != 0) { 974 if (facs->GlobalLock & ACPI_GLOCK_PENDING) 975 printf("PENDING,"); 976 if (facs->GlobalLock & ACPI_GLOCK_OWNED) 977 printf("OWNED"); 978 } 979 printf("\n"); 980 981 printf("\tFlags="); 982 if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT) 983 printf("S4BIOS"); 984 printf("\n"); 985 986 if (facs->XFirmwareWakingVector != 0) { 987 printf("\tX_Firm_Wake_Vec=%08lx\n", 988 (u_long)facs->XFirmwareWakingVector); 989 } 990 printf("\tVersion=%u\n", facs->Version); 991 992 printf(END_COMMENT); 993 } 994 995 static void 996 acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp) 997 { 998 printf(BEGIN_COMMENT); 999 acpi_print_sdt(dsdp); 1000 printf(END_COMMENT); 1001 } 1002 1003 int 1004 acpi_checksum(void *p, size_t length) 1005 { 1006 uint8_t *bp; 1007 uint8_t sum; 1008 1009 bp = p; 1010 sum = 0; 1011 while (length--) 1012 sum += *bp++; 1013 1014 return (sum); 1015 } 1016 1017 static ACPI_TABLE_HEADER * 1018 acpi_map_sdt(vm_offset_t pa) 1019 { 1020 ACPI_TABLE_HEADER *sp; 1021 1022 sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER)); 1023 sp = acpi_map_physical(pa, sp->Length); 1024 return (sp); 1025 } 1026 1027 static void 1028 acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp) 1029 { 1030 printf(BEGIN_COMMENT); 1031 printf(" RSD PTR: OEM="); 1032 acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE); 1033 printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x", 1034 rp->Revision); 1035 if (rp->Revision < 2) { 1036 printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress, 1037 rp->Checksum); 1038 } else { 1039 printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n", 1040 (u_long)rp->XsdtPhysicalAddress, rp->Length, 1041 rp->ExtendedChecksum); 1042 } 1043 printf(END_COMMENT); 1044 } 1045 1046 static void 1047 acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp) 1048 { 1049 ACPI_TABLE_HEADER *sdp; 1050 ACPI_TABLE_RSDT *rsdt; 1051 ACPI_TABLE_XSDT *xsdt; 1052 vm_offset_t addr; 1053 int entries, i; 1054 1055 acpi_print_rsdt(rsdp); 1056 rsdt = (ACPI_TABLE_RSDT *)rsdp; 1057 xsdt = (ACPI_TABLE_XSDT *)rsdp; 1058 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size; 1059 for (i = 0; i < entries; i++) { 1060 switch (addr_size) { 1061 case 4: 1062 addr = le32toh(rsdt->TableOffsetEntry[i]); 1063 break; 1064 case 8: 1065 addr = le64toh(xsdt->TableOffsetEntry[i]); 1066 break; 1067 default: 1068 assert((addr = 0)); 1069 } 1070 1071 sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr); 1072 if (acpi_checksum(sdp, sdp->Length)) { 1073 warnx("RSDT entry %d (sig %.4s) is corrupt", i, 1074 sdp->Signature); 1075 continue; 1076 } 1077 if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4)) 1078 acpi_handle_fadt(sdp); 1079 else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4)) 1080 acpi_handle_madt(sdp); 1081 else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4)) 1082 acpi_handle_hpet(sdp); 1083 else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4)) 1084 acpi_handle_ecdt(sdp); 1085 else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4)) 1086 acpi_handle_mcfg(sdp); 1087 else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4)) 1088 acpi_handle_srat(sdp); 1089 else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4)) 1090 acpi_handle_tcpa(sdp); 1091 else { 1092 printf(BEGIN_COMMENT); 1093 acpi_print_sdt(sdp); 1094 printf(END_COMMENT); 1095 } 1096 } 1097 } 1098 1099 ACPI_TABLE_HEADER * 1100 sdt_load_devmem(void) 1101 { 1102 ACPI_TABLE_RSDP *rp; 1103 ACPI_TABLE_HEADER *rsdp; 1104 1105 rp = acpi_find_rsd_ptr(); 1106 if (!rp) 1107 errx(1, "Can't find ACPI information"); 1108 1109 if (tflag) 1110 acpi_print_rsd_ptr(rp); 1111 if (rp->Revision < 2) { 1112 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress); 1113 if (memcmp(rsdp->Signature, "RSDT", 4) != 0 || 1114 acpi_checksum(rsdp, rsdp->Length) != 0) 1115 errx(1, "RSDT is corrupted"); 1116 addr_size = sizeof(uint32_t); 1117 } else { 1118 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress); 1119 if (memcmp(rsdp->Signature, "XSDT", 4) != 0 || 1120 acpi_checksum(rsdp, rsdp->Length) != 0) 1121 errx(1, "XSDT is corrupted"); 1122 addr_size = sizeof(uint64_t); 1123 } 1124 return (rsdp); 1125 } 1126 1127 /* Write the DSDT to a file, concatenating any SSDTs (if present). */ 1128 static int 1129 write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt) 1130 { 1131 ACPI_TABLE_HEADER sdt; 1132 ACPI_TABLE_HEADER *ssdt; 1133 uint8_t sum; 1134 1135 /* Create a new checksum to account for the DSDT and any SSDTs. */ 1136 sdt = *dsdt; 1137 if (rsdt != NULL) { 1138 sdt.Checksum = 0; 1139 sum = acpi_checksum(dsdt + 1, dsdt->Length - 1140 sizeof(ACPI_TABLE_HEADER)); 1141 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL); 1142 while (ssdt != NULL) { 1143 sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER); 1144 sum += acpi_checksum(ssdt + 1, 1145 ssdt->Length - sizeof(ACPI_TABLE_HEADER)); 1146 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt); 1147 } 1148 sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER)); 1149 sdt.Checksum -= sum; 1150 } 1151 1152 /* Write out the DSDT header and body. */ 1153 write(fd, &sdt, sizeof(ACPI_TABLE_HEADER)); 1154 write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER)); 1155 1156 /* Write out any SSDTs (if present.) */ 1157 if (rsdt != NULL) { 1158 ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL); 1159 while (ssdt != NULL) { 1160 write(fd, ssdt + 1, ssdt->Length - 1161 sizeof(ACPI_TABLE_HEADER)); 1162 ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt); 1163 } 1164 } 1165 return (0); 1166 } 1167 1168 void 1169 dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp) 1170 { 1171 int fd; 1172 mode_t mode; 1173 1174 assert(outfile != NULL); 1175 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 1176 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 1177 if (fd == -1) { 1178 perror("dsdt_save_file"); 1179 return; 1180 } 1181 write_dsdt(fd, rsdt, dsdp); 1182 close(fd); 1183 } 1184 1185 void 1186 aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp) 1187 { 1188 char buf[PATH_MAX], tmpstr[PATH_MAX]; 1189 const char *tmpdir; 1190 char *tmpext; 1191 FILE *fp; 1192 size_t len; 1193 int fd; 1194 1195 tmpdir = getenv("TMPDIR"); 1196 if (tmpdir == NULL) 1197 tmpdir = _PATH_TMP; 1198 strncpy(tmpstr, tmpdir, sizeof(tmpstr)); 1199 strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(tmpdir)); 1200 if (realpath(tmpstr, buf) == NULL) { 1201 perror("realpath tmp file"); 1202 return; 1203 } 1204 strncpy(tmpstr, buf, sizeof(tmpstr)); 1205 len = strlen(buf); 1206 tmpext = tmpstr + len; 1207 strncpy(tmpext, "XXXXXX", sizeof(tmpstr) - len); 1208 fd = mkstemp(tmpstr); 1209 if (fd < 0) { 1210 perror("iasl tmp file"); 1211 return; 1212 } 1213 write_dsdt(fd, rsdt, dsdp); 1214 close(fd); 1215 1216 /* Run iasl -d on the temp file */ 1217 if (fork() == 0) { 1218 close(STDOUT_FILENO); 1219 if (vflag == 0) 1220 close(STDERR_FILENO); 1221 execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL); 1222 err(1, "exec"); 1223 } 1224 1225 wait(NULL); 1226 unlink(tmpstr); 1227 1228 /* Dump iasl's output to stdout */ 1229 strncpy(tmpext, "dsl", sizeof(tmpstr) - len); 1230 fp = fopen(tmpstr, "r"); 1231 unlink(tmpstr); 1232 if (fp == NULL) { 1233 perror("iasl tmp file (read)"); 1234 return; 1235 } 1236 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 1237 fwrite(buf, 1, len, stdout); 1238 fclose(fp); 1239 } 1240 1241 void 1242 sdt_print_all(ACPI_TABLE_HEADER *rsdp) 1243 { 1244 acpi_handle_rsdt(rsdp); 1245 } 1246 1247 /* Fetch a table matching the given signature via the RSDT. */ 1248 ACPI_TABLE_HEADER * 1249 sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last) 1250 { 1251 ACPI_TABLE_HEADER *sdt; 1252 ACPI_TABLE_RSDT *rsdt; 1253 ACPI_TABLE_XSDT *xsdt; 1254 vm_offset_t addr; 1255 int entries, i; 1256 1257 rsdt = (ACPI_TABLE_RSDT *)rsdp; 1258 xsdt = (ACPI_TABLE_XSDT *)rsdp; 1259 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size; 1260 for (i = 0; i < entries; i++) { 1261 switch (addr_size) { 1262 case 4: 1263 addr = le32toh(rsdt->TableOffsetEntry[i]); 1264 break; 1265 case 8: 1266 addr = le64toh(xsdt->TableOffsetEntry[i]); 1267 break; 1268 default: 1269 assert((addr = 0)); 1270 } 1271 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr); 1272 if (last != NULL) { 1273 if (sdt == last) 1274 last = NULL; 1275 continue; 1276 } 1277 if (memcmp(sdt->Signature, sig, strlen(sig))) 1278 continue; 1279 if (acpi_checksum(sdt, sdt->Length)) 1280 errx(1, "RSDT entry %d is corrupt", i); 1281 return (sdt); 1282 } 1283 1284 return (NULL); 1285 } 1286 1287 ACPI_TABLE_HEADER * 1288 dsdt_from_fadt(ACPI_TABLE_FADT *fadt) 1289 { 1290 ACPI_TABLE_HEADER *sdt; 1291 1292 /* Use the DSDT address if it is version 1, otherwise use XDSDT. */ 1293 if (acpi_get_fadt_revision(fadt) == 1) 1294 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt); 1295 else 1296 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt); 1297 if (acpi_checksum(sdt, sdt->Length)) 1298 errx(1, "DSDT is corrupt\n"); 1299 return (sdt); 1300 } 1301