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 <stdio.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include "acpidump.h" 42 43 #define BEGIN_COMMENT "/*\n" 44 #define END_COMMENT " */\n" 45 46 static void acpi_print_string(char *s, size_t length); 47 static void acpi_print_gas(struct ACPIgas *gas); 48 static int acpi_get_fadt_revision(struct FADTbody *fadt); 49 static void acpi_handle_fadt(struct FADTbody *fadt); 50 static void acpi_print_cpu(u_char cpu_id); 51 static void acpi_print_local_apic(u_char cpu_id, u_char apic_id, 52 u_int32_t flags); 53 static void acpi_print_io_apic(u_char apic_id, u_int32_t int_base, 54 u_int64_t apic_addr); 55 static void acpi_print_mps_flags(u_int16_t flags); 56 static void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags); 57 static void acpi_print_apic(struct MADT_APIC *mp); 58 static void acpi_handle_apic(struct ACPIsdt *sdp); 59 static void acpi_handle_hpet(struct ACPIsdt *sdp); 60 static void acpi_print_sdt(struct ACPIsdt *sdp); 61 static void acpi_print_fadt(struct FADTbody *fadt); 62 static void acpi_print_facs(struct FACSbody *facs); 63 static void acpi_print_dsdt(struct ACPIsdt *dsdp); 64 static struct ACPIsdt *acpi_map_sdt(vm_offset_t pa); 65 static void acpi_print_rsd_ptr(struct ACPIrsdp *rp); 66 static void acpi_handle_rsdt(struct ACPIsdt *rsdp); 67 68 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */ 69 static int addr_size; 70 71 static void 72 acpi_print_string(char *s, size_t length) 73 { 74 int c; 75 76 /* Trim trailing spaces and NULLs */ 77 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0')) 78 length--; 79 80 while (length--) { 81 c = *s++; 82 putchar(c); 83 } 84 } 85 86 static void 87 acpi_print_gas(struct ACPIgas *gas) 88 { 89 switch(gas->address_space_id) { 90 case ACPI_GAS_MEMORY: 91 printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->address, 92 gas->bit_offset, gas->bit_width); 93 break; 94 case ACPI_GAS_IO: 95 printf("0x%02lx:%u[%u] (IO)", (u_long)gas->address, 96 gas->bit_offset, gas->bit_width); 97 break; 98 case ACPI_GAS_PCI: 99 printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->address >> 32), 100 (uint16_t)((gas->address >> 16) & 0xffff), 101 (uint16_t)gas->address); 102 break; 103 /* XXX How to handle these below? */ 104 case ACPI_GAS_EMBEDDED: 105 printf("0x%x:%u[%u] (EC)", (uint16_t)gas->address, 106 gas->bit_offset, gas->bit_width); 107 break; 108 case ACPI_GAS_SMBUS: 109 printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->address, 110 gas->bit_offset, gas->bit_width); 111 break; 112 case ACPI_GAS_FIXED: 113 default: 114 printf("0x%08lx (?)", (u_long)gas->address); 115 break; 116 } 117 } 118 119 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */ 120 static int 121 acpi_get_fadt_revision(struct FADTbody *fadt) 122 { 123 int fadt_revision; 124 125 /* Set the FADT revision separately from the RSDP version. */ 126 if (addr_size == 8) { 127 fadt_revision = 2; 128 129 /* 130 * A few systems (e.g., IBM T23) have an RSDP that claims 131 * revision 2 but the 64 bit addresses are invalid. If 132 * revision 2 and the 32 bit address is non-zero but the 133 * 32 and 64 bit versions don't match, prefer the 32 bit 134 * version for all subsequent tables. 135 */ 136 if (fadt->facs_ptr != 0 && 137 (fadt->x_facs_ptr & 0xffffffff) != fadt->facs_ptr) 138 fadt_revision = 1; 139 } else 140 fadt_revision = 1; 141 return (fadt_revision); 142 } 143 144 static void 145 acpi_handle_fadt(struct FADTbody *fadt) 146 { 147 struct ACPIsdt *dsdp; 148 struct FACSbody *facs; 149 int fadt_revision; 150 151 acpi_print_fadt(fadt); 152 153 fadt_revision = acpi_get_fadt_revision(fadt); 154 if (fadt_revision == 1) 155 facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr); 156 else 157 facs = (struct FACSbody *)acpi_map_sdt(fadt->x_facs_ptr); 158 if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64) 159 errx(1, "FACS is corrupt"); 160 acpi_print_facs(facs); 161 162 if (fadt_revision == 1) 163 dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 164 else 165 dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr); 166 if (acpi_checksum(dsdp, dsdp->len)) 167 errx(1, "DSDT is corrupt"); 168 acpi_print_dsdt(dsdp); 169 } 170 171 static void 172 acpi_print_cpu(u_char cpu_id) 173 { 174 175 printf("\tACPI CPU="); 176 if (cpu_id == 0xff) 177 printf("ALL\n"); 178 else 179 printf("%d\n", (u_int)cpu_id); 180 } 181 182 static void 183 acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags) 184 { 185 acpi_print_cpu(cpu_id); 186 printf("\tFlags={"); 187 if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED) 188 printf("ENABLED"); 189 else 190 printf("DISABLED"); 191 printf("}\n"); 192 printf("\tAPIC ID=%d\n", (u_int)apic_id); 193 } 194 195 static void 196 acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr) 197 { 198 printf("\tAPIC ID=%d\n", (u_int)apic_id); 199 printf("\tINT BASE=%d\n", int_base); 200 printf("\tADDR=0x%016jx\n", apic_addr); 201 } 202 203 static void 204 acpi_print_mps_flags(u_int16_t flags) 205 { 206 207 printf("\tFlags={Polarity="); 208 switch (flags & MPS_INT_FLAG_POLARITY_MASK) { 209 case MPS_INT_FLAG_POLARITY_CONFORM: 210 printf("conforming"); 211 break; 212 case MPS_INT_FLAG_POLARITY_HIGH: 213 printf("active-hi"); 214 break; 215 case MPS_INT_FLAG_POLARITY_LOW: 216 printf("active-lo"); 217 break; 218 default: 219 printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK); 220 break; 221 } 222 printf(", Trigger="); 223 switch (flags & MPS_INT_FLAG_TRIGGER_MASK) { 224 case MPS_INT_FLAG_TRIGGER_CONFORM: 225 printf("conforming"); 226 break; 227 case MPS_INT_FLAG_TRIGGER_EDGE: 228 printf("edge"); 229 break; 230 case MPS_INT_FLAG_TRIGGER_LEVEL: 231 printf("level"); 232 break; 233 default: 234 printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2); 235 } 236 printf("}\n"); 237 } 238 239 static void 240 acpi_print_intr(u_int32_t intr, u_int16_t mps_flags) 241 { 242 243 printf("\tINTR=%d\n", (u_int)intr); 244 acpi_print_mps_flags(mps_flags); 245 } 246 247 const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", 248 "Local NMI", "Local APIC Override", "IO SAPIC", 249 "Local SAPIC", "Platform Interrupt" }; 250 const char *platform_int_types[] = { "PMI", "INIT", 251 "Corrected Platform Error" }; 252 253 static void 254 acpi_print_apic(struct MADT_APIC *mp) 255 { 256 257 printf("\tType=%s\n", apic_types[mp->type]); 258 switch (mp->type) { 259 case ACPI_MADT_APIC_TYPE_LOCAL_APIC: 260 acpi_print_local_apic(mp->body.local_apic.cpu_id, 261 mp->body.local_apic.apic_id, mp->body.local_apic.flags); 262 break; 263 case ACPI_MADT_APIC_TYPE_IO_APIC: 264 acpi_print_io_apic(mp->body.io_apic.apic_id, 265 mp->body.io_apic.int_base, 266 mp->body.io_apic.apic_addr); 267 break; 268 case ACPI_MADT_APIC_TYPE_INT_OVERRIDE: 269 printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus); 270 printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source); 271 acpi_print_intr(mp->body.int_override.intr, 272 mp->body.int_override.mps_flags); 273 break; 274 case ACPI_MADT_APIC_TYPE_NMI: 275 acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags); 276 break; 277 case ACPI_MADT_APIC_TYPE_LOCAL_NMI: 278 acpi_print_cpu(mp->body.local_nmi.cpu_id); 279 printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin); 280 acpi_print_mps_flags(mp->body.local_nmi.mps_flags); 281 break; 282 case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE: 283 printf("\tLocal APIC ADDR=0x%016jx\n", 284 mp->body.local_apic_override.apic_addr); 285 break; 286 case ACPI_MADT_APIC_TYPE_IO_SAPIC: 287 acpi_print_io_apic(mp->body.io_sapic.apic_id, 288 mp->body.io_sapic.int_base, 289 mp->body.io_sapic.apic_addr); 290 break; 291 case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC: 292 acpi_print_local_apic(mp->body.local_sapic.cpu_id, 293 mp->body.local_sapic.apic_id, mp->body.local_sapic.flags); 294 printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid); 295 break; 296 case ACPI_MADT_APIC_TYPE_INT_SRC: 297 printf("\tType=%s\n", 298 platform_int_types[mp->body.int_src.type]); 299 printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id); 300 printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id); 301 printf("\tSAPIC Vector=%d\n", 302 (u_int)mp->body.int_src.sapic_vector); 303 acpi_print_intr(mp->body.int_src.intr, 304 mp->body.int_src.mps_flags); 305 break; 306 default: 307 printf("\tUnknown type %d\n", (u_int)mp->type); 308 break; 309 } 310 } 311 312 static void 313 acpi_handle_apic(struct ACPIsdt *sdp) 314 { 315 struct MADTbody *madtp; 316 struct MADT_APIC *madt_apicp; 317 318 printf(BEGIN_COMMENT); 319 acpi_print_sdt(sdp); 320 madtp = (struct MADTbody *) sdp->body; 321 printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr); 322 printf("\tFlags={"); 323 if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT) 324 printf("PC-AT"); 325 printf("}\n"); 326 madt_apicp = (struct MADT_APIC *)madtp->body; 327 while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) { 328 printf("\n"); 329 acpi_print_apic(madt_apicp); 330 madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp + 331 madt_apicp->len); 332 } 333 printf(END_COMMENT); 334 } 335 336 static void 337 acpi_handle_hpet(struct ACPIsdt *sdp) 338 { 339 struct HPETbody *hpetp; 340 341 printf(BEGIN_COMMENT); 342 acpi_print_sdt(sdp); 343 hpetp = (struct HPETbody *) sdp->body; 344 printf("\tHPET Number=%d\n", hpetp->hpet_number); 345 printf("\tADDR=0x%08x\n", hpetp->base_addr); 346 printf("\tHW Rev=0x%x\n", hpetp->block_hwrev); 347 printf("\tComparitors=%d\n", hpetp->block_comparitors); 348 printf("\tCounter Size=%d\n", hpetp->block_counter_size); 349 printf("\tLegacy IRQ routing capable={"); 350 if (hpetp->block_legacy_capable) 351 printf("TRUE}\n"); 352 else 353 printf("FALSE}\n"); 354 printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor); 355 printf("\tMinimal Tick=%d\n", hpetp->clock_tick); 356 printf(END_COMMENT); 357 } 358 359 static void 360 acpi_handle_ecdt(struct ACPIsdt *sdp) 361 { 362 struct ECDTbody *ecdt; 363 364 printf(BEGIN_COMMENT); 365 acpi_print_sdt(sdp); 366 ecdt = (struct ECDTbody *) sdp->body; 367 printf("\tEC_CONTROL="); 368 acpi_print_gas(&ecdt->ec_control); 369 printf("\n\tEC_DATA="); 370 acpi_print_gas(&ecdt->ec_data); 371 printf("\n\tUID=%#x, ", ecdt->uid); 372 printf("GPE_BIT=%#x\n", ecdt->gpe_bit); 373 printf("\tEC_ID=%s\n", ecdt->ec_id); 374 printf(END_COMMENT); 375 } 376 377 static void 378 acpi_print_sdt(struct ACPIsdt *sdp) 379 { 380 printf(" "); 381 acpi_print_string(sdp->signature, 4); 382 printf(": Length=%d, Revision=%d, Checksum=%d,\n", 383 sdp->len, sdp->rev, sdp->check); 384 printf("\tOEMID="); 385 acpi_print_string(sdp->oemid, 6); 386 printf(", OEM Table ID="); 387 acpi_print_string(sdp->oemtblid, 8); 388 printf(", OEM Revision=0x%x,\n", sdp->oemrev); 389 printf("\tCreator ID="); 390 acpi_print_string(sdp->creator, 4); 391 printf(", Creator Revision=0x%x\n", sdp->crerev); 392 } 393 394 static void 395 acpi_print_rsdt(struct ACPIsdt *rsdp) 396 { 397 int i, entries; 398 u_long addr; 399 400 printf(BEGIN_COMMENT); 401 acpi_print_sdt(rsdp); 402 entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 403 printf("\tEntries={ "); 404 for (i = 0; i < entries; i++) { 405 if (i > 0) 406 printf(", "); 407 switch (addr_size) { 408 case 4: 409 addr = le32dec((char*)rsdp->body + i * addr_size); 410 break; 411 case 8: 412 addr = le64dec((char*)rsdp->body + i * addr_size); 413 break; 414 default: 415 addr = 0; 416 } 417 assert(addr != 0); 418 printf("0x%08lx", addr); 419 } 420 printf(" }\n"); 421 printf(END_COMMENT); 422 } 423 424 static const char *acpi_pm_profiles[] = { 425 "Unspecified", "Desktop", "Mobile", "Workstation", 426 "Enterprise Server", "SOHO Server", "Appliance PC" 427 }; 428 429 static void 430 acpi_print_fadt(struct FADTbody *fadt) 431 { 432 const char *pm; 433 char sep; 434 435 printf(BEGIN_COMMENT); 436 printf(" FADT:\tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr, 437 fadt->dsdt_ptr); 438 printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC"); 439 if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *)) 440 pm = "Reserved"; 441 else 442 pm = acpi_pm_profiles[fadt->pm_profile]; 443 printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile); 444 printf("\tSCI_INT=%d\n", fadt->sci_int); 445 printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd); 446 printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable); 447 printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable); 448 printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq); 449 printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt); 450 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n", 451 fadt->pm1a_evt_blk, 452 fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1); 453 if (fadt->pm1b_evt_blk != 0) 454 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n", 455 fadt->pm1b_evt_blk, 456 fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1); 457 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n", 458 fadt->pm1a_cnt_blk, 459 fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1); 460 if (fadt->pm1b_cnt_blk != 0) 461 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n", 462 fadt->pm1b_cnt_blk, 463 fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1); 464 if (fadt->pm2_cnt_blk != 0) 465 printf("\tPM2_CNT_BLK=0x%x-0x%x\n", 466 fadt->pm2_cnt_blk, 467 fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1); 468 printf("\tPM_TMR_BLK=0x%x-0x%x\n", 469 fadt->pm_tmr_blk, 470 fadt->pm_tmr_blk + fadt->pm_tmr_len - 1); 471 if (fadt->gpe0_blk != 0) 472 printf("\tGPE0_BLK=0x%x-0x%x\n", 473 fadt->gpe0_blk, 474 fadt->gpe0_blk + fadt->gpe0_len - 1); 475 if (fadt->gpe1_blk != 0) 476 printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n", 477 fadt->gpe1_blk, 478 fadt->gpe1_blk + fadt->gpe1_len - 1, 479 fadt->gpe1_base); 480 if (fadt->cst_cnt != 0) 481 printf("\tCST_CNT=0x%x\n", fadt->cst_cnt); 482 printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n", 483 fadt->p_lvl2_lat, fadt->p_lvl3_lat); 484 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n", 485 fadt->flush_size, fadt->flush_stride); 486 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n", 487 fadt->duty_off, fadt->duty_width); 488 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n", 489 fadt->day_alrm, fadt->mon_alrm, fadt->century); 490 491 #define PRINTFLAG(var, flag) do { \ 492 if ((var) & FADT_FLAG_## flag) { \ 493 printf("%c%s", sep, #flag); sep = ','; \ 494 } \ 495 } while (0) 496 497 printf("\tIAPC_BOOT_ARCH="); 498 sep = '{'; 499 PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV); 500 PRINTFLAG(fadt->iapc_boot_arch, 8042); 501 if (fadt->iapc_boot_arch != 0) 502 printf("}"); 503 printf("\n"); 504 505 printf("\tFlags="); 506 sep = '{'; 507 PRINTFLAG(fadt->flags, WBINVD); 508 PRINTFLAG(fadt->flags, WBINVD_FLUSH); 509 PRINTFLAG(fadt->flags, PROC_C1); 510 PRINTFLAG(fadt->flags, P_LVL2_UP); 511 PRINTFLAG(fadt->flags, PWR_BUTTON); 512 PRINTFLAG(fadt->flags, SLP_BUTTON); 513 PRINTFLAG(fadt->flags, FIX_RTC); 514 PRINTFLAG(fadt->flags, RTC_S4); 515 PRINTFLAG(fadt->flags, TMR_VAL_EXT); 516 PRINTFLAG(fadt->flags, DCK_CAP); 517 PRINTFLAG(fadt->flags, RESET_REG); 518 PRINTFLAG(fadt->flags, SEALED_CASE); 519 PRINTFLAG(fadt->flags, HEADLESS); 520 PRINTFLAG(fadt->flags, CPU_SW_SLP); 521 if (fadt->flags != 0) 522 printf("}\n"); 523 524 #undef PRINTFLAG 525 526 if (fadt->flags & FADT_FLAG_RESET_REG) { 527 printf("\tRESET_REG="); 528 acpi_print_gas(&fadt->reset_reg); 529 printf(", RESET_VALUE=%#x\n", fadt->reset_value); 530 } 531 if (acpi_get_fadt_revision(fadt) > 1) { 532 printf("\tX_FACS=0x%08lx, ", (u_long)fadt->x_facs_ptr); 533 printf("X_DSDT=0x%08lx\n", (u_long)fadt->x_dsdt_ptr); 534 printf("\tX_PM1a_EVT_BLK="); 535 acpi_print_gas(&fadt->x_pm1a_evt_blk); 536 if (fadt->x_pm1b_evt_blk.address != 0) { 537 printf("\n\tX_PM1b_EVT_BLK="); 538 acpi_print_gas(&fadt->x_pm1b_evt_blk); 539 } 540 printf("\n\tX_PM1a_CNT_BLK="); 541 acpi_print_gas(&fadt->x_pm1a_cnt_blk); 542 if (fadt->x_pm1b_cnt_blk.address != 0) { 543 printf("\n\tX_PM1b_CNT_BLK="); 544 acpi_print_gas(&fadt->x_pm1b_cnt_blk); 545 } 546 if (fadt->x_pm1b_cnt_blk.address != 0) { 547 printf("\n\tX_PM2_CNT_BLK="); 548 acpi_print_gas(&fadt->x_pm2_cnt_blk); 549 } 550 printf("\n\tX_PM_TMR_BLK="); 551 acpi_print_gas(&fadt->x_pm_tmr_blk); 552 if (fadt->x_gpe0_blk.address != 0) { 553 printf("\n\tX_GPE0_BLK="); 554 acpi_print_gas(&fadt->x_gpe0_blk); 555 } 556 if (fadt->x_gpe1_blk.address != 0) { 557 printf("\n\tX_GPE1_BLK="); 558 acpi_print_gas(&fadt->x_gpe1_blk); 559 } 560 printf("\n"); 561 } 562 563 printf(END_COMMENT); 564 } 565 566 static void 567 acpi_print_facs(struct FACSbody *facs) 568 { 569 printf(BEGIN_COMMENT); 570 printf(" FACS:\tLength=%u, ", facs->len); 571 printf("HwSig=0x%08x, ", facs->hw_sig); 572 printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec); 573 574 printf("\tGlobal_Lock="); 575 if (facs->global_lock != 0) { 576 if (facs->global_lock & FACS_FLAG_LOCK_PENDING) 577 printf("PENDING,"); 578 if (facs->global_lock & FACS_FLAG_LOCK_OWNED) 579 printf("OWNED"); 580 } 581 printf("\n"); 582 583 printf("\tFlags="); 584 if (facs->flags & FACS_FLAG_S4BIOS_F) 585 printf("S4BIOS"); 586 printf("\n"); 587 588 if (facs->x_firm_wake_vec != 0) { 589 printf("\tX_Firm_Wake_Vec=%08lx\n", 590 (u_long)facs->x_firm_wake_vec); 591 } 592 printf("\tVersion=%u\n", facs->version); 593 594 printf(END_COMMENT); 595 } 596 597 static void 598 acpi_print_dsdt(struct ACPIsdt *dsdp) 599 { 600 printf(BEGIN_COMMENT); 601 acpi_print_sdt(dsdp); 602 printf(END_COMMENT); 603 } 604 605 int 606 acpi_checksum(void *p, size_t length) 607 { 608 u_int8_t *bp; 609 u_int8_t sum; 610 611 bp = p; 612 sum = 0; 613 while (length--) 614 sum += *bp++; 615 616 return (sum); 617 } 618 619 static struct ACPIsdt * 620 acpi_map_sdt(vm_offset_t pa) 621 { 622 struct ACPIsdt *sp; 623 624 sp = acpi_map_physical(pa, sizeof(struct ACPIsdt)); 625 sp = acpi_map_physical(pa, sp->len); 626 return (sp); 627 } 628 629 static void 630 acpi_print_rsd_ptr(struct ACPIrsdp *rp) 631 { 632 printf(BEGIN_COMMENT); 633 printf(" RSD PTR: OEM="); 634 acpi_print_string(rp->oem, 6); 635 printf(", ACPI_Rev=%s (%d)\n", rp->revision < 2 ? "1.0x" : "2.0x", 636 rp->revision); 637 if (rp->revision < 2) { 638 printf("\tRSDT=0x%08x, cksum=%u\n", rp->rsdt_addr, rp->sum); 639 } else { 640 printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n", 641 (u_long)rp->xsdt_addr, rp->length, rp->xsum); 642 } 643 printf(END_COMMENT); 644 } 645 646 static void 647 acpi_handle_rsdt(struct ACPIsdt *rsdp) 648 { 649 struct ACPIsdt *sdp; 650 vm_offset_t addr; 651 int entries, i; 652 653 acpi_print_rsdt(rsdp); 654 entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size; 655 for (i = 0; i < entries; i++) { 656 switch (addr_size) { 657 case 4: 658 addr = le32dec((char*)rsdp->body + i * addr_size); 659 break; 660 case 8: 661 addr = le64dec((char*)rsdp->body + i * addr_size); 662 break; 663 default: 664 assert((addr = 0)); 665 } 666 667 sdp = (struct ACPIsdt *)acpi_map_sdt(addr); 668 if (acpi_checksum(sdp, sdp->len)) 669 errx(1, "RSDT entry %d is corrupt", i); 670 if (!memcmp(sdp->signature, "FACP", 4)) 671 acpi_handle_fadt((struct FADTbody *) sdp->body); 672 else if (!memcmp(sdp->signature, "APIC", 4)) 673 acpi_handle_apic(sdp); 674 else if (!memcmp(sdp->signature, "HPET", 4)) 675 acpi_handle_hpet(sdp); 676 else if (!memcmp(sdp->signature, "ECDT", 4)) 677 acpi_handle_ecdt(sdp); 678 else { 679 printf(BEGIN_COMMENT); 680 acpi_print_sdt(sdp); 681 printf(END_COMMENT); 682 } 683 } 684 } 685 686 struct ACPIsdt * 687 sdt_load_devmem(void) 688 { 689 struct ACPIrsdp *rp; 690 struct ACPIsdt *rsdp; 691 692 rp = acpi_find_rsd_ptr(); 693 if (!rp) 694 errx(1, "Can't find ACPI information"); 695 696 if (tflag) 697 acpi_print_rsd_ptr(rp); 698 if (rp->revision < 2) { 699 rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr); 700 if (memcmp(rsdp->signature, "RSDT", 4) != 0 || 701 acpi_checksum(rsdp, rsdp->len) != 0) 702 errx(1, "RSDT is corrupted"); 703 addr_size = sizeof(uint32_t); 704 } else { 705 rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr); 706 if (memcmp(rsdp->signature, "XSDT", 4) != 0 || 707 acpi_checksum(rsdp, rsdp->len) != 0) 708 errx(1, "XSDT is corrupted"); 709 addr_size = sizeof(uint64_t); 710 } 711 return (rsdp); 712 } 713 714 void 715 dsdt_save_file(char *outfile, struct ACPIsdt *dsdp) 716 { 717 int fd; 718 mode_t mode; 719 720 assert(outfile != NULL); 721 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 722 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode); 723 if (fd == -1) { 724 perror("dsdt_save_file"); 725 return; 726 } 727 write(fd, dsdp, SIZEOF_SDT_HDR); 728 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 729 close(fd); 730 } 731 732 void 733 aml_disassemble(struct ACPIsdt *dsdp) 734 { 735 char tmpstr[32], buf[256]; 736 FILE *fp; 737 int fd, len; 738 739 strcpy(tmpstr, "/tmp/acpidump.XXXXXX"); 740 fd = mkstemp(tmpstr); 741 if (fd < 0) { 742 perror("iasl tmp file"); 743 return; 744 } 745 746 /* Dump DSDT to the temp file */ 747 write(fd, dsdp, SIZEOF_SDT_HDR); 748 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR); 749 close(fd); 750 751 /* Run iasl -d on the temp file */ 752 if (fork() == 0) { 753 close(STDOUT_FILENO); 754 if (vflag == 0) 755 close(STDERR_FILENO); 756 execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0); 757 err(1, "exec"); 758 } 759 760 wait(NULL); 761 unlink(tmpstr); 762 763 /* Dump iasl's output to stdout */ 764 fp = fopen("acpidump.dsl", "r"); 765 unlink("acpidump.dsl"); 766 if (fp == NULL) { 767 perror("iasl tmp file (read)"); 768 return; 769 } 770 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) 771 fwrite(buf, 1, len, stdout); 772 fclose(fp); 773 } 774 775 void 776 sdt_print_all(struct ACPIsdt *rsdp) 777 { 778 acpi_handle_rsdt(rsdp); 779 } 780 781 /* Fetch a table matching the given signature via the RSDT */ 782 struct ACPIsdt * 783 sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig) 784 { 785 struct ACPIsdt *sdt; 786 vm_offset_t addr; 787 int entries, i; 788 789 entries = (rsdt->len - SIZEOF_SDT_HDR) / addr_size; 790 for (i = 0; i < entries; i++) { 791 switch (addr_size) { 792 case 4: 793 addr = le32dec((char*)rsdt->body + i * addr_size); 794 break; 795 case 8: 796 addr = le64dec((char*)rsdt->body + i * addr_size); 797 break; 798 default: 799 assert((addr = 0)); 800 } 801 sdt = (struct ACPIsdt *)acpi_map_sdt(addr); 802 if (memcmp(sdt->signature, sig, strlen(sig))) 803 continue; 804 if (acpi_checksum(sdt, sdt->len)) 805 errx(1, "RSDT entry %d is corrupt", i); 806 return (sdt); 807 } 808 809 return (NULL); 810 } 811 812 struct ACPIsdt * 813 dsdt_from_fadt(struct FADTbody *fadt) 814 { 815 struct ACPIsdt *sdt; 816 817 /* Use the DSDT address if it is version 1, otherwise use X_DSDT. */ 818 if (acpi_get_fadt_revision(fadt) == 1) 819 sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr); 820 else 821 sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr); 822 if (acpi_checksum(sdt, sdt->len)) 823 errx(1, "DSDT is corrupt\n"); 824 return (sdt); 825 } 826