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