2 * Copyright (c) 1998 Doug Rabson
3 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
27 * $FreeBSD: src/usr.sbin/acpi/acpidump/acpi.c,v 1.25 2004/06/30 03:23:51 njl Exp $
28 * $DragonFly: src/usr.sbin/acpi/acpidump/acpi.c,v 1.1 2004/07/05 00:22:43 dillon Exp $
31 #include <sys/param.h>
32 #include <sys/endian.h>
44 #define BEGIN_COMMENT "/*\n"
45 #define END_COMMENT " */\n"
47 static void acpi_print_string(char *s, size_t length);
48 static void acpi_print_gas(struct ACPIgas *gas);
49 static int acpi_get_fadt_revision(struct FADTbody *fadt);
50 static void acpi_handle_fadt(struct ACPIsdt *fadt);
51 static void acpi_print_cpu(u_char cpu_id);
52 static void acpi_print_local_apic(u_char cpu_id, u_char apic_id,
54 static void acpi_print_io_apic(u_char apic_id, u_int32_t int_base,
56 static void acpi_print_mps_flags(u_int16_t flags);
57 static void acpi_print_intr(u_int32_t intr, u_int16_t mps_flags);
58 static void acpi_print_apic(struct MADT_APIC *mp);
59 static void acpi_handle_apic(struct ACPIsdt *sdp);
60 static void acpi_handle_hpet(struct ACPIsdt *sdp);
61 static void acpi_print_sdt(struct ACPIsdt *sdp);
62 static void acpi_print_fadt(struct ACPIsdt *sdp);
63 static void acpi_print_facs(struct FACSbody *facs);
64 static void acpi_print_dsdt(struct ACPIsdt *dsdp);
65 static struct ACPIsdt *acpi_map_sdt(vm_offset_t pa);
66 static void acpi_print_rsd_ptr(struct ACPIrsdp *rp);
67 static void acpi_handle_rsdt(struct ACPIsdt *rsdp);
69 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
73 * XXX: borrow endian-conversion functions from FreeBSD-CURRENT's endian.h
75 static __inline uint32_t
76 le32dec(const void *pp)
78 unsigned char const *p = (unsigned char const *)pp;
80 return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
83 static __inline uint64_t
84 le64dec(const void *pp)
86 unsigned char const *p = (unsigned char const *)pp;
88 return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
92 acpi_print_string(char *s, size_t length)
96 /* Trim trailing spaces and NULLs */
97 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
107 acpi_print_gas(struct ACPIgas *gas)
109 switch(gas->address_space_id) {
110 case ACPI_GAS_MEMORY:
111 printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->address,
112 gas->bit_offset, gas->bit_width);
115 printf("0x%02lx:%u[%u] (IO)", (u_long)gas->address,
116 gas->bit_offset, gas->bit_width);
119 printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->address >> 32),
120 (uint16_t)((gas->address >> 16) & 0xffff),
121 (uint16_t)gas->address);
123 /* XXX How to handle these below? */
124 case ACPI_GAS_EMBEDDED:
125 printf("0x%x:%u[%u] (EC)", (uint16_t)gas->address,
126 gas->bit_offset, gas->bit_width);
129 printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->address,
130 gas->bit_offset, gas->bit_width);
134 printf("0x%08lx (?)", (u_long)gas->address);
139 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
141 acpi_get_fadt_revision(struct FADTbody *fadt)
145 /* Set the FADT revision separately from the RSDP version. */
146 if (addr_size == 8) {
150 * A few systems (e.g., IBM T23) have an RSDP that claims
151 * revision 2 but the 64 bit addresses are invalid. If
152 * revision 2 and the 32 bit address is non-zero but the
153 * 32 and 64 bit versions don't match, prefer the 32 bit
154 * version for all subsequent tables.
156 if (fadt->facs_ptr != 0 &&
157 (fadt->x_facs_ptr & 0xffffffff) != fadt->facs_ptr)
161 return (fadt_revision);
165 acpi_handle_fadt(struct ACPIsdt *sdp)
167 struct ACPIsdt *dsdp;
168 struct FACSbody *facs;
169 struct FADTbody *fadt;
172 fadt = (struct FADTbody *)sdp->body;
173 acpi_print_fadt(sdp);
175 fadt_revision = acpi_get_fadt_revision(fadt);
176 if (fadt_revision == 1)
177 facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr);
179 facs = (struct FACSbody *)acpi_map_sdt(fadt->x_facs_ptr);
180 if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64)
181 errx(1, "FACS is corrupt");
182 acpi_print_facs(facs);
184 if (fadt_revision == 1)
185 dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr);
187 dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr);
188 if (acpi_checksum(dsdp, dsdp->len))
189 errx(1, "DSDT is corrupt");
190 acpi_print_dsdt(dsdp);
194 acpi_print_cpu(u_char cpu_id)
197 printf("\tACPI CPU=");
201 printf("%d\n", (u_int)cpu_id);
205 acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags)
207 acpi_print_cpu(cpu_id);
209 if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED)
214 printf("\tAPIC ID=%d\n", (u_int)apic_id);
218 acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr)
220 printf("\tAPIC ID=%d\n", (u_int)apic_id);
221 printf("\tINT BASE=%d\n", int_base);
222 printf("\tADDR=0x%016jx\n", apic_addr);
226 acpi_print_mps_flags(u_int16_t flags)
229 printf("\tFlags={Polarity=");
230 switch (flags & MPS_INT_FLAG_POLARITY_MASK) {
231 case MPS_INT_FLAG_POLARITY_CONFORM:
232 printf("conforming");
234 case MPS_INT_FLAG_POLARITY_HIGH:
237 case MPS_INT_FLAG_POLARITY_LOW:
241 printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK);
244 printf(", Trigger=");
245 switch (flags & MPS_INT_FLAG_TRIGGER_MASK) {
246 case MPS_INT_FLAG_TRIGGER_CONFORM:
247 printf("conforming");
249 case MPS_INT_FLAG_TRIGGER_EDGE:
252 case MPS_INT_FLAG_TRIGGER_LEVEL:
256 printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2);
262 acpi_print_intr(u_int32_t intr, u_int16_t mps_flags)
265 printf("\tINTR=%d\n", (u_int)intr);
266 acpi_print_mps_flags(mps_flags);
269 const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI",
270 "Local NMI", "Local APIC Override", "IO SAPIC",
271 "Local SAPIC", "Platform Interrupt" };
272 const char *platform_int_types[] = { "PMI", "INIT",
273 "Corrected Platform Error" };
276 acpi_print_apic(struct MADT_APIC *mp)
279 printf("\tType=%s\n", apic_types[mp->type]);
281 case ACPI_MADT_APIC_TYPE_LOCAL_APIC:
282 acpi_print_local_apic(mp->body.local_apic.cpu_id,
283 mp->body.local_apic.apic_id, mp->body.local_apic.flags);
285 case ACPI_MADT_APIC_TYPE_IO_APIC:
286 acpi_print_io_apic(mp->body.io_apic.apic_id,
287 mp->body.io_apic.int_base,
288 mp->body.io_apic.apic_addr);
290 case ACPI_MADT_APIC_TYPE_INT_OVERRIDE:
291 printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus);
292 printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source);
293 acpi_print_intr(mp->body.int_override.intr,
294 mp->body.int_override.mps_flags);
296 case ACPI_MADT_APIC_TYPE_NMI:
297 acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags);
299 case ACPI_MADT_APIC_TYPE_LOCAL_NMI:
300 acpi_print_cpu(mp->body.local_nmi.cpu_id);
301 printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin);
302 acpi_print_mps_flags(mp->body.local_nmi.mps_flags);
304 case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE:
305 printf("\tLocal APIC ADDR=0x%016jx\n",
306 mp->body.local_apic_override.apic_addr);
308 case ACPI_MADT_APIC_TYPE_IO_SAPIC:
309 acpi_print_io_apic(mp->body.io_sapic.apic_id,
310 mp->body.io_sapic.int_base,
311 mp->body.io_sapic.apic_addr);
313 case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC:
314 acpi_print_local_apic(mp->body.local_sapic.cpu_id,
315 mp->body.local_sapic.apic_id, mp->body.local_sapic.flags);
316 printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid);
318 case ACPI_MADT_APIC_TYPE_INT_SRC:
319 printf("\tType=%s\n",
320 platform_int_types[mp->body.int_src.type]);
321 printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id);
322 printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id);
323 printf("\tSAPIC Vector=%d\n",
324 (u_int)mp->body.int_src.sapic_vector);
325 acpi_print_intr(mp->body.int_src.intr,
326 mp->body.int_src.mps_flags);
329 printf("\tUnknown type %d\n", (u_int)mp->type);
335 acpi_handle_apic(struct ACPIsdt *sdp)
337 struct MADTbody *madtp;
338 struct MADT_APIC *madt_apicp;
340 printf(BEGIN_COMMENT);
342 madtp = (struct MADTbody *) sdp->body;
343 printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr);
345 if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT)
348 madt_apicp = (struct MADT_APIC *)madtp->body;
349 while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) {
351 acpi_print_apic(madt_apicp);
352 madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp +
359 acpi_handle_hpet(struct ACPIsdt *sdp)
361 struct HPETbody *hpetp;
363 printf(BEGIN_COMMENT);
365 hpetp = (struct HPETbody *) sdp->body;
366 printf("\tHPET Number=%d\n", hpetp->hpet_number);
367 printf("\tADDR=0x%08x\n", hpetp->base_addr);
368 printf("\tHW Rev=0x%x\n", hpetp->block_hwrev);
369 printf("\tComparitors=%d\n", hpetp->block_comparitors);
370 printf("\tCounter Size=%d\n", hpetp->block_counter_size);
371 printf("\tLegacy IRQ routing capable={");
372 if (hpetp->block_legacy_capable)
376 printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor);
377 printf("\tMinimal Tick=%d\n", hpetp->clock_tick);
382 acpi_handle_ecdt(struct ACPIsdt *sdp)
384 struct ECDTbody *ecdt;
386 printf(BEGIN_COMMENT);
388 ecdt = (struct ECDTbody *) sdp->body;
389 printf("\tEC_CONTROL=");
390 acpi_print_gas(&ecdt->ec_control);
391 printf("\n\tEC_DATA=");
392 acpi_print_gas(&ecdt->ec_data);
393 printf("\n\tUID=%#x, ", ecdt->uid);
394 printf("GPE_BIT=%#x\n", ecdt->gpe_bit);
395 printf("\tEC_ID=%s\n", ecdt->ec_id);
400 acpi_print_sdt(struct ACPIsdt *sdp)
403 acpi_print_string(sdp->signature, 4);
404 printf(": Length=%d, Revision=%d, Checksum=%d,\n",
405 sdp->len, sdp->rev, sdp->check);
407 acpi_print_string(sdp->oemid, 6);
408 printf(", OEM Table ID=");
409 acpi_print_string(sdp->oemtblid, 8);
410 printf(", OEM Revision=0x%x,\n", sdp->oemrev);
411 printf("\tCreator ID=");
412 acpi_print_string(sdp->creator, 4);
413 printf(", Creator Revision=0x%x\n", sdp->crerev);
417 acpi_print_rsdt(struct ACPIsdt *rsdp)
422 printf(BEGIN_COMMENT);
423 acpi_print_sdt(rsdp);
424 entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size;
425 printf("\tEntries={ ");
426 for (i = 0; i < entries; i++) {
431 addr = le32dec((char*)rsdp->body + i * addr_size);
434 addr = le64dec((char*)rsdp->body + i * addr_size);
440 printf("0x%08lx", addr);
446 static const char *acpi_pm_profiles[] = {
447 "Unspecified", "Desktop", "Mobile", "Workstation",
448 "Enterprise Server", "SOHO Server", "Appliance PC"
452 acpi_print_fadt(struct ACPIsdt *sdp)
454 struct FADTbody *fadt;
458 fadt = (struct FADTbody *)sdp->body;
459 printf(BEGIN_COMMENT);
461 printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr,
463 printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC");
464 if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *))
467 pm = acpi_pm_profiles[fadt->pm_profile];
468 printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile);
469 printf("\tSCI_INT=%d\n", fadt->sci_int);
470 printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd);
471 printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable);
472 printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable);
473 printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq);
474 printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt);
475 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
477 fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1);
478 if (fadt->pm1b_evt_blk != 0)
479 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
481 fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1);
482 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
484 fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1);
485 if (fadt->pm1b_cnt_blk != 0)
486 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
488 fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1);
489 if (fadt->pm2_cnt_blk != 0)
490 printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
492 fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1);
493 printf("\tPM_TMR_BLK=0x%x-0x%x\n",
495 fadt->pm_tmr_blk + fadt->pm_tmr_len - 1);
496 if (fadt->gpe0_blk != 0)
497 printf("\tGPE0_BLK=0x%x-0x%x\n",
499 fadt->gpe0_blk + fadt->gpe0_len - 1);
500 if (fadt->gpe1_blk != 0)
501 printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
503 fadt->gpe1_blk + fadt->gpe1_len - 1,
505 if (fadt->cst_cnt != 0)
506 printf("\tCST_CNT=0x%x\n", fadt->cst_cnt);
507 printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
508 fadt->p_lvl2_lat, fadt->p_lvl3_lat);
509 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
510 fadt->flush_size, fadt->flush_stride);
511 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
512 fadt->duty_off, fadt->duty_width);
513 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
514 fadt->day_alrm, fadt->mon_alrm, fadt->century);
516 #define PRINTFLAG(var, flag) do { \
517 if ((var) & FADT_FLAG_## flag) { \
518 printf("%c%s", sep, #flag); sep = ','; \
522 printf("\tIAPC_BOOT_ARCH=");
524 PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV);
525 PRINTFLAG(fadt->iapc_boot_arch, 8042);
526 if (fadt->iapc_boot_arch != 0)
532 PRINTFLAG(fadt->flags, WBINVD);
533 PRINTFLAG(fadt->flags, WBINVD_FLUSH);
534 PRINTFLAG(fadt->flags, PROC_C1);
535 PRINTFLAG(fadt->flags, P_LVL2_UP);
536 PRINTFLAG(fadt->flags, PWR_BUTTON);
537 PRINTFLAG(fadt->flags, SLP_BUTTON);
538 PRINTFLAG(fadt->flags, FIX_RTC);
539 PRINTFLAG(fadt->flags, RTC_S4);
540 PRINTFLAG(fadt->flags, TMR_VAL_EXT);
541 PRINTFLAG(fadt->flags, DCK_CAP);
542 PRINTFLAG(fadt->flags, RESET_REG);
543 PRINTFLAG(fadt->flags, SEALED_CASE);
544 PRINTFLAG(fadt->flags, HEADLESS);
545 PRINTFLAG(fadt->flags, CPU_SW_SLP);
546 if (fadt->flags != 0)
551 if (fadt->flags & FADT_FLAG_RESET_REG) {
552 printf("\tRESET_REG=");
553 acpi_print_gas(&fadt->reset_reg);
554 printf(", RESET_VALUE=%#x\n", fadt->reset_value);
556 if (acpi_get_fadt_revision(fadt) > 1) {
557 printf("\tX_FACS=0x%08lx, ", (u_long)fadt->x_facs_ptr);
558 printf("X_DSDT=0x%08lx\n", (u_long)fadt->x_dsdt_ptr);
559 printf("\tX_PM1a_EVT_BLK=");
560 acpi_print_gas(&fadt->x_pm1a_evt_blk);
561 if (fadt->x_pm1b_evt_blk.address != 0) {
562 printf("\n\tX_PM1b_EVT_BLK=");
563 acpi_print_gas(&fadt->x_pm1b_evt_blk);
565 printf("\n\tX_PM1a_CNT_BLK=");
566 acpi_print_gas(&fadt->x_pm1a_cnt_blk);
567 if (fadt->x_pm1b_cnt_blk.address != 0) {
568 printf("\n\tX_PM1b_CNT_BLK=");
569 acpi_print_gas(&fadt->x_pm1b_cnt_blk);
571 if (fadt->x_pm1b_cnt_blk.address != 0) {
572 printf("\n\tX_PM2_CNT_BLK=");
573 acpi_print_gas(&fadt->x_pm2_cnt_blk);
575 printf("\n\tX_PM_TMR_BLK=");
576 acpi_print_gas(&fadt->x_pm_tmr_blk);
577 if (fadt->x_gpe0_blk.address != 0) {
578 printf("\n\tX_GPE0_BLK=");
579 acpi_print_gas(&fadt->x_gpe0_blk);
581 if (fadt->x_gpe1_blk.address != 0) {
582 printf("\n\tX_GPE1_BLK=");
583 acpi_print_gas(&fadt->x_gpe1_blk);
592 acpi_print_facs(struct FACSbody *facs)
594 printf(BEGIN_COMMENT);
595 printf(" FACS:\tLength=%u, ", facs->len);
596 printf("HwSig=0x%08x, ", facs->hw_sig);
597 printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec);
599 printf("\tGlobal_Lock=");
600 if (facs->global_lock != 0) {
601 if (facs->global_lock & FACS_FLAG_LOCK_PENDING)
603 if (facs->global_lock & FACS_FLAG_LOCK_OWNED)
609 if (facs->flags & FACS_FLAG_S4BIOS_F)
613 if (facs->x_firm_wake_vec != 0) {
614 printf("\tX_Firm_Wake_Vec=%08lx\n",
615 (u_long)facs->x_firm_wake_vec);
617 printf("\tVersion=%u\n", facs->version);
623 acpi_print_dsdt(struct ACPIsdt *dsdp)
625 printf(BEGIN_COMMENT);
626 acpi_print_sdt(dsdp);
631 acpi_checksum(void *p, size_t length)
644 static struct ACPIsdt *
645 acpi_map_sdt(vm_offset_t pa)
649 sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
650 sp = acpi_map_physical(pa, sp->len);
655 acpi_print_rsd_ptr(struct ACPIrsdp *rp)
657 printf(BEGIN_COMMENT);
658 printf(" RSD PTR: OEM=");
659 acpi_print_string(rp->oem, 6);
660 printf(", ACPI_Rev=%s (%d)\n", rp->revision < 2 ? "1.0x" : "2.0x",
662 if (rp->revision < 2) {
663 printf("\tRSDT=0x%08x, cksum=%u\n", rp->rsdt_addr, rp->sum);
665 printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n",
666 (u_long)rp->xsdt_addr, rp->length, rp->xsum);
672 acpi_handle_rsdt(struct ACPIsdt *rsdp)
678 acpi_print_rsdt(rsdp);
679 entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size;
680 for (i = 0; i < entries; i++) {
683 addr = le32dec((char*)rsdp->body + i * addr_size);
686 addr = le64dec((char*)rsdp->body + i * addr_size);
692 sdp = (struct ACPIsdt *)acpi_map_sdt(addr);
693 if (acpi_checksum(sdp, sdp->len))
694 errx(1, "RSDT entry %d is corrupt", i);
695 if (!memcmp(sdp->signature, "FACP", 4))
696 acpi_handle_fadt(sdp);
697 else if (!memcmp(sdp->signature, "APIC", 4))
698 acpi_handle_apic(sdp);
699 else if (!memcmp(sdp->signature, "HPET", 4))
700 acpi_handle_hpet(sdp);
701 else if (!memcmp(sdp->signature, "ECDT", 4))
702 acpi_handle_ecdt(sdp);
704 printf(BEGIN_COMMENT);
712 sdt_load_devmem(void)
715 struct ACPIsdt *rsdp;
717 rp = acpi_find_rsd_ptr();
719 errx(1, "Can't find ACPI information");
722 acpi_print_rsd_ptr(rp);
723 if (rp->revision < 2) {
724 rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr);
725 if (memcmp(rsdp->signature, "RSDT", 4) != 0 ||
726 acpi_checksum(rsdp, rsdp->len) != 0)
727 errx(1, "RSDT is corrupted");
728 addr_size = sizeof(uint32_t);
730 rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr);
731 if (memcmp(rsdp->signature, "XSDT", 4) != 0 ||
732 acpi_checksum(rsdp, rsdp->len) != 0)
733 errx(1, "XSDT is corrupted");
734 addr_size = sizeof(uint64_t);
740 dsdt_save_file(char *outfile, struct ACPIsdt *dsdp)
745 assert(outfile != NULL);
746 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
747 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
749 perror("dsdt_save_file");
752 write(fd, dsdp, SIZEOF_SDT_HDR);
753 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR);
758 aml_disassemble(struct ACPIsdt *dsdp)
760 char tmpstr[32], buf[256];
764 strcpy(tmpstr, "/tmp/acpidump.XXXXXX");
765 fd = mkstemp(tmpstr);
767 perror("iasl tmp file");
771 /* Dump DSDT to the temp file */
772 write(fd, dsdp, SIZEOF_SDT_HDR);
773 write(fd, dsdp->body, dsdp->len - SIZEOF_SDT_HDR);
776 /* Run iasl -d on the temp file */
778 close(STDOUT_FILENO);
780 close(STDERR_FILENO);
781 execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, 0);
788 /* Dump iasl's output to stdout */
789 fp = fopen("acpidump.dsl", "r");
790 unlink("acpidump.dsl");
792 perror("iasl tmp file (read)");
795 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
796 fwrite(buf, 1, len, stdout);
801 sdt_print_all(struct ACPIsdt *rsdp)
803 acpi_handle_rsdt(rsdp);
806 /* Fetch a table matching the given signature via the RSDT */
808 sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig)
814 entries = (rsdt->len - SIZEOF_SDT_HDR) / addr_size;
815 for (i = 0; i < entries; i++) {
818 addr = le32dec((char*)rsdt->body + i * addr_size);
821 addr = le64dec((char*)rsdt->body + i * addr_size);
826 sdt = (struct ACPIsdt *)acpi_map_sdt(addr);
827 if (memcmp(sdt->signature, sig, strlen(sig)))
829 if (acpi_checksum(sdt, sdt->len))
830 errx(1, "RSDT entry %d is corrupt", i);
838 dsdt_from_fadt(struct FADTbody *fadt)
842 /* Use the DSDT address if it is version 1, otherwise use X_DSDT. */
843 if (acpi_get_fadt_revision(fadt) == 1)
844 sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr);
846 sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr);
847 if (acpi_checksum(sdt, sdt->len))
848 errx(1, "DSDT is corrupt\n");