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