xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision 338666582fa4c4cf556e45ac27d74c0cffb099d2)
1e1e9a4bfSMitsuru IWASAKI /*-
2e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 1998 Doug Rabson
3e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
4e1e9a4bfSMitsuru IWASAKI  * All rights reserved.
5e1e9a4bfSMitsuru IWASAKI  *
6e1e9a4bfSMitsuru IWASAKI  * Redistribution and use in source and binary forms, with or without
7e1e9a4bfSMitsuru IWASAKI  * modification, are permitted provided that the following conditions
8e1e9a4bfSMitsuru IWASAKI  * are met:
9e1e9a4bfSMitsuru IWASAKI  * 1. Redistributions of source code must retain the above copyright
10e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer.
11e1e9a4bfSMitsuru IWASAKI  * 2. Redistributions in binary form must reproduce the above copyright
12e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer in the
13e1e9a4bfSMitsuru IWASAKI  *    documentation and/or other materials provided with the distribution.
14e1e9a4bfSMitsuru IWASAKI  *
15e1e9a4bfSMitsuru IWASAKI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e1e9a4bfSMitsuru IWASAKI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e1e9a4bfSMitsuru IWASAKI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e1e9a4bfSMitsuru IWASAKI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e1e9a4bfSMitsuru IWASAKI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e1e9a4bfSMitsuru IWASAKI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e1e9a4bfSMitsuru IWASAKI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e1e9a4bfSMitsuru IWASAKI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e1e9a4bfSMitsuru IWASAKI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e1e9a4bfSMitsuru IWASAKI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e1e9a4bfSMitsuru IWASAKI  * SUCH DAMAGE.
26e1e9a4bfSMitsuru IWASAKI  *
27e1e9a4bfSMitsuru IWASAKI  *	$FreeBSD$
28e1e9a4bfSMitsuru IWASAKI  */
29e1e9a4bfSMitsuru IWASAKI 
30e1e9a4bfSMitsuru IWASAKI #include <sys/param.h>
31a74172abSNate Lawson #include <sys/endian.h>
32e1e9a4bfSMitsuru IWASAKI #include <sys/stat.h>
33945137d9SNate Lawson #include <sys/wait.h>
34e1e9a4bfSMitsuru IWASAKI #include <assert.h>
35e1e9a4bfSMitsuru IWASAKI #include <err.h>
36e1e9a4bfSMitsuru IWASAKI #include <fcntl.h>
3799065116SJung-uk Kim #include <paths.h>
38e1e9a4bfSMitsuru IWASAKI #include <stdio.h>
39a0333ad1SJohn Baldwin #include <stdint.h>
4099065116SJung-uk Kim #include <stdlib.h>
41945137d9SNate Lawson #include <string.h>
42e1e9a4bfSMitsuru IWASAKI #include <unistd.h>
43e1e9a4bfSMitsuru IWASAKI 
44e1e9a4bfSMitsuru IWASAKI #include "acpidump.h"
45e1e9a4bfSMitsuru IWASAKI 
46c62f1cccSMitsuru IWASAKI #define BEGIN_COMMENT	"/*\n"
47c62f1cccSMitsuru IWASAKI #define END_COMMENT	" */\n"
48c62f1cccSMitsuru IWASAKI 
49945137d9SNate Lawson static void	acpi_print_string(char *s, size_t length);
50986dffafSJohn Baldwin static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
51986dffafSJohn Baldwin static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
52986dffafSJohn Baldwin static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
53945137d9SNate Lawson static void	acpi_print_cpu(u_char cpu_id);
54986dffafSJohn Baldwin static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
55986dffafSJohn Baldwin static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
56986dffafSJohn Baldwin static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
57986dffafSJohn Baldwin 		    uint64_t apic_addr);
58986dffafSJohn Baldwin static void	acpi_print_mps_flags(uint16_t flags);
59986dffafSJohn Baldwin static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
60986dffafSJohn Baldwin static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
61986dffafSJohn Baldwin static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
62986dffafSJohn Baldwin static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
63986dffafSJohn Baldwin static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
64986dffafSJohn Baldwin static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
65986dffafSJohn Baldwin static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
66*33866658SJohn Baldwin static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
67a0333ad1SJohn Baldwin static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
68a0333ad1SJohn Baldwin 		    uint32_t flags);
69986dffafSJohn Baldwin static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
70986dffafSJohn Baldwin static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
71986dffafSJohn Baldwin static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
72c031c93bSTakanori Watanabe static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
73986dffafSJohn Baldwin static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
74986dffafSJohn Baldwin static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
75986dffafSJohn Baldwin static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
76986dffafSJohn Baldwin static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
77986dffafSJohn Baldwin static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
78986dffafSJohn Baldwin static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
79986dffafSJohn Baldwin static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
80986dffafSJohn Baldwin static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
81986dffafSJohn Baldwin 		    void (*action)(ACPI_SUBTABLE_HEADER *));
82c62f1cccSMitsuru IWASAKI 
83773b6454SNate Lawson /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
84a74172abSNate Lawson static int addr_size;
85a74172abSNate Lawson 
86c031c93bSTakanori Watanabe /* Strings used in the TCPA table */
87c031c93bSTakanori Watanabe static const char *tcpa_event_type_strings[] = {
88c031c93bSTakanori Watanabe 	"PREBOOT Certificate",
89c031c93bSTakanori Watanabe 	"POST Code",
90c031c93bSTakanori Watanabe 	"Unused",
91c031c93bSTakanori Watanabe 	"No Action",
92c031c93bSTakanori Watanabe 	"Separator",
93c031c93bSTakanori Watanabe 	"Action",
94c031c93bSTakanori Watanabe 	"Event Tag",
95c031c93bSTakanori Watanabe 	"S-CRTM Contents",
96c031c93bSTakanori Watanabe 	"S-CRTM Version",
97c031c93bSTakanori Watanabe 	"CPU Microcode",
98c031c93bSTakanori Watanabe 	"Platform Config Flags",
99c031c93bSTakanori Watanabe 	"Table of Devices",
100c031c93bSTakanori Watanabe 	"Compact Hash",
101c031c93bSTakanori Watanabe 	"IPL",
102c031c93bSTakanori Watanabe 	"IPL Partition Data",
103c031c93bSTakanori Watanabe 	"Non-Host Code",
104c031c93bSTakanori Watanabe 	"Non-Host Config",
105c031c93bSTakanori Watanabe 	"Non-Host Info"
106c031c93bSTakanori Watanabe };
107c031c93bSTakanori Watanabe 
108c031c93bSTakanori Watanabe static const char *TCPA_pcclient_strings[] = {
109c031c93bSTakanori Watanabe 	"<undefined>",
110c031c93bSTakanori Watanabe 	"SMBIOS",
111c031c93bSTakanori Watanabe 	"BIS Certificate",
112c031c93bSTakanori Watanabe 	"POST BIOS ROM Strings",
113c031c93bSTakanori Watanabe 	"ESCD",
114c031c93bSTakanori Watanabe 	"CMOS",
115c031c93bSTakanori Watanabe 	"NVRAM",
116c031c93bSTakanori Watanabe 	"Option ROM Execute",
117c031c93bSTakanori Watanabe 	"Option ROM Configurateion",
118c031c93bSTakanori Watanabe 	"<undefined>",
119c031c93bSTakanori Watanabe 	"Option ROM Microcode Update ",
120c031c93bSTakanori Watanabe 	"S-CRTM Version String",
121c031c93bSTakanori Watanabe 	"S-CRTM Contents",
122c031c93bSTakanori Watanabe 	"POST Contents",
123c031c93bSTakanori Watanabe 	"Table of Devices",
124c031c93bSTakanori Watanabe };
125c031c93bSTakanori Watanabe 
126e1e9a4bfSMitsuru IWASAKI static void
127e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
128e1e9a4bfSMitsuru IWASAKI {
129e1e9a4bfSMitsuru IWASAKI 	int	c;
130e1e9a4bfSMitsuru IWASAKI 
131e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
132e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
133e1e9a4bfSMitsuru IWASAKI 		length--;
134e1e9a4bfSMitsuru IWASAKI 
135e1e9a4bfSMitsuru IWASAKI 	while (length--) {
136e1e9a4bfSMitsuru IWASAKI 		c = *s++;
137e1e9a4bfSMitsuru IWASAKI 		putchar(c);
138e1e9a4bfSMitsuru IWASAKI 	}
139e1e9a4bfSMitsuru IWASAKI }
140e1e9a4bfSMitsuru IWASAKI 
141e1e9a4bfSMitsuru IWASAKI static void
142986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1438e6a8737SNate Lawson {
144986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1458e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
146986dffafSJohn Baldwin 		printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->Address,
147986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1488e6a8737SNate Lawson 		break;
1498e6a8737SNate Lawson 	case ACPI_GAS_IO:
150986dffafSJohn Baldwin 		printf("0x%02lx:%u[%u] (IO)", (u_long)gas->Address,
151986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1528e6a8737SNate Lawson 		break;
1538e6a8737SNate Lawson 	case ACPI_GAS_PCI:
154986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
155986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
156986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1578e6a8737SNate Lawson 		break;
1588e6a8737SNate Lawson 	/* XXX How to handle these below? */
1598e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
160986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
161986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1628e6a8737SNate Lawson 		break;
1638e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
164986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
165986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1668e6a8737SNate Lawson 		break;
167986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
168986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
169986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
1708e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
1718e6a8737SNate Lawson 	default:
172986dffafSJohn Baldwin 		printf("0x%08lx (?)", (u_long)gas->Address);
1738e6a8737SNate Lawson 		break;
1748e6a8737SNate Lawson 	}
1758e6a8737SNate Lawson }
1768e6a8737SNate Lawson 
177c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
178c2962974SNate Lawson static int
179986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
180e1e9a4bfSMitsuru IWASAKI {
181c2962974SNate Lawson 	int fadt_revision;
182e1e9a4bfSMitsuru IWASAKI 
183c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
184c83f0f99SNate Lawson 	if (addr_size == 8) {
185c83f0f99SNate Lawson 		fadt_revision = 2;
1868e6a8737SNate Lawson 
187773b6454SNate Lawson 		/*
188c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
189c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
190c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
191c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
192c83f0f99SNate Lawson 		 * version for all subsequent tables.
193773b6454SNate Lawson 		 */
194986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
195986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
196c83f0f99SNate Lawson 			fadt_revision = 1;
197c2962974SNate Lawson 	} else
198c83f0f99SNate Lawson 		fadt_revision = 1;
199c2962974SNate Lawson 	return (fadt_revision);
200c83f0f99SNate Lawson }
201c2962974SNate Lawson 
202c2962974SNate Lawson static void
203986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
204c2962974SNate Lawson {
205986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
206986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
207986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
208c2962974SNate Lawson 	int		fadt_revision;
209c2962974SNate Lawson 
210986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2112177d4e6SNate Lawson 	acpi_print_fadt(sdp);
212c83f0f99SNate Lawson 
213c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
214c83f0f99SNate Lawson 	if (fadt_revision == 1)
215986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
216773b6454SNate Lawson 	else
217986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
218986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2198e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2208e6a8737SNate Lawson 	acpi_print_facs(facs);
2218e6a8737SNate Lawson 
222c83f0f99SNate Lawson 	if (fadt_revision == 1)
223986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
224773b6454SNate Lawson 	else
225986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
226986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
227945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
228945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
229c62f1cccSMitsuru IWASAKI }
230c62f1cccSMitsuru IWASAKI 
231c62f1cccSMitsuru IWASAKI static void
232986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
233986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
234986dffafSJohn Baldwin {
235986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
236986dffafSJohn Baldwin 	char *end;
237986dffafSJohn Baldwin 
238986dffafSJohn Baldwin 	subtable = first;
239986dffafSJohn Baldwin 	end = (char *)table + table->Length;
240986dffafSJohn Baldwin 	while ((char *)subtable < end) {
241986dffafSJohn Baldwin 		printf("\n");
242986dffafSJohn Baldwin 		action(subtable);
243986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
244986dffafSJohn Baldwin 		    subtable->Length);
245986dffafSJohn Baldwin 	}
246986dffafSJohn Baldwin }
247986dffafSJohn Baldwin 
248986dffafSJohn Baldwin static void
2490a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
2500a473124SJohn Baldwin {
2510a473124SJohn Baldwin 
2520a473124SJohn Baldwin 	printf("\tACPI CPU=");
2530a473124SJohn Baldwin 	if (cpu_id == 0xff)
2540a473124SJohn Baldwin 		printf("ALL\n");
2550a473124SJohn Baldwin 	else
2560a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
2570a473124SJohn Baldwin }
2580a473124SJohn Baldwin 
2590a473124SJohn Baldwin static void
260986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
2610a473124SJohn Baldwin {
262986dffafSJohn Baldwin 
263986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
264986dffafSJohn Baldwin 	if (uid_string != NULL)
265986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
266986dffafSJohn Baldwin 	printf("\n");
267986dffafSJohn Baldwin }
268986dffafSJohn Baldwin 
269986dffafSJohn Baldwin static void
270986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
271986dffafSJohn Baldwin {
272986dffafSJohn Baldwin 
2730a473124SJohn Baldwin 	printf("\tFlags={");
274986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
2750a473124SJohn Baldwin 		printf("ENABLED");
2760a473124SJohn Baldwin 	else
2770a473124SJohn Baldwin 		printf("DISABLED");
2780a473124SJohn Baldwin 	printf("}\n");
279986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
2800a473124SJohn Baldwin }
2810a473124SJohn Baldwin 
2820a473124SJohn Baldwin static void
283986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
2840a473124SJohn Baldwin {
285986dffafSJohn Baldwin 
286986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
2870a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
288986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
2890a473124SJohn Baldwin }
2900a473124SJohn Baldwin 
2910a473124SJohn Baldwin static void
292986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
2930a473124SJohn Baldwin {
2940a473124SJohn Baldwin 
2950a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
296986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
297986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
2980a473124SJohn Baldwin 		printf("conforming");
2990a473124SJohn Baldwin 		break;
300986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3010a473124SJohn Baldwin 		printf("active-hi");
3020a473124SJohn Baldwin 		break;
303986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3040a473124SJohn Baldwin 		printf("active-lo");
3050a473124SJohn Baldwin 		break;
3060a473124SJohn Baldwin 	default:
307986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3080a473124SJohn Baldwin 		break;
3090a473124SJohn Baldwin 	}
3100a473124SJohn Baldwin 	printf(", Trigger=");
311986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
312986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3130a473124SJohn Baldwin 		printf("conforming");
3140a473124SJohn Baldwin 		break;
315986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3160a473124SJohn Baldwin 		printf("edge");
3170a473124SJohn Baldwin 		break;
318986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3190a473124SJohn Baldwin 		printf("level");
3200a473124SJohn Baldwin 		break;
3210a473124SJohn Baldwin 	default:
322986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3230a473124SJohn Baldwin 	}
3240a473124SJohn Baldwin 	printf("}\n");
3250a473124SJohn Baldwin }
3260a473124SJohn Baldwin 
3270a473124SJohn Baldwin static void
328986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
3290a473124SJohn Baldwin {
3300a473124SJohn Baldwin 
331986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
332986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
333986dffafSJohn Baldwin }
334986dffafSJohn Baldwin 
335986dffafSJohn Baldwin static void
336986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
337986dffafSJohn Baldwin {
338986dffafSJohn Baldwin 
339986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
3400a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
3410a473124SJohn Baldwin }
3420a473124SJohn Baldwin 
3430a473124SJohn Baldwin const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI",
344986dffafSJohn Baldwin 			     "Local APIC NMI", "Local APIC Override",
345986dffafSJohn Baldwin 			     "IO SAPIC", "Local SAPIC", "Platform Interrupt",
346986dffafSJohn Baldwin 			     "Local X2APIC", "Local X2APIC NMI" };
347986dffafSJohn Baldwin const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
3480a473124SJohn Baldwin 				     "Corrected Platform Error" };
3490a473124SJohn Baldwin 
3500a473124SJohn Baldwin static void
351986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
3520a473124SJohn Baldwin {
353986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
354986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
355986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
356986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
357986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
358986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
359986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
360986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
361986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
362986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
363986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
3640a473124SJohn Baldwin 
365986dffafSJohn Baldwin 	if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0]))
366986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
367a0333ad1SJohn Baldwin 	else
368986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
369986dffafSJohn Baldwin 	switch (mp->Type) {
370986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
371986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
372986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
373986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
3740a473124SJohn Baldwin 		break;
375986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
376986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
377986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
378986dffafSJohn Baldwin 		    ioapic->Address);
3790a473124SJohn Baldwin 		break;
380986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
381986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
382986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
383986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
384986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
3850a473124SJohn Baldwin 		break;
386986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
387986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
388986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
3890a473124SJohn Baldwin 		break;
390986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
391986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
392986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
393986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
3940a473124SJohn Baldwin 		break;
395986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
396986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
397945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
398986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
3990a473124SJohn Baldwin 		break;
400986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
401986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
402986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
403986dffafSJohn Baldwin 		    iosapic->Address);
4040a473124SJohn Baldwin 		break;
405986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
406986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
407986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
408986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
409986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
410986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
411986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
4120a473124SJohn Baldwin 		break;
413986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
414986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
415986dffafSJohn Baldwin 		if (isrc->Type < sizeof(platform_int_types) /
416986dffafSJohn Baldwin 		    sizeof(platform_int_types[0]))
417986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
418986dffafSJohn Baldwin 		else
419986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
420986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
421986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
422986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
423986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
424986dffafSJohn Baldwin 		break;
425986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
426986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
427986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
428986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
429986dffafSJohn Baldwin 		break;
430986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
431986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
432986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
433986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
4340a473124SJohn Baldwin 		break;
4350a473124SJohn Baldwin 	}
4360a473124SJohn Baldwin }
4370a473124SJohn Baldwin 
4380a473124SJohn Baldwin static void
439986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
4400a473124SJohn Baldwin {
441986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
4420a473124SJohn Baldwin 
443773b6454SNate Lawson 	printf(BEGIN_COMMENT);
444773b6454SNate Lawson 	acpi_print_sdt(sdp);
445986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
446986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
4470a473124SJohn Baldwin 	printf("\tFlags={");
448986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
4490a473124SJohn Baldwin 		printf("PC-AT");
4500a473124SJohn Baldwin 	printf("}\n");
451986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
4520a473124SJohn Baldwin 	printf(END_COMMENT);
4530a473124SJohn Baldwin }
4540a473124SJohn Baldwin 
4550a473124SJohn Baldwin static void
456986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
45779d7565cSPeter Wemm {
458986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
45979d7565cSPeter Wemm 
460773b6454SNate Lawson 	printf(BEGIN_COMMENT);
461773b6454SNate Lawson 	acpi_print_sdt(sdp);
462986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
463986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
46487f9f09aSTakanori Watanabe 	printf("\tADDR=");
465986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
466986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
467986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
468986dffafSJohn Baldwin 	    8);
469986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
470986dffafSJohn Baldwin 	    1 : 0);
47179d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
472986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
47379d7565cSPeter Wemm 		printf("TRUE}\n");
47479d7565cSPeter Wemm 	else
47579d7565cSPeter Wemm 		printf("FALSE}\n");
476986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
477986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
47879d7565cSPeter Wemm 	printf(END_COMMENT);
47979d7565cSPeter Wemm }
48079d7565cSPeter Wemm 
48179d7565cSPeter Wemm static void
482986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
48355d7ff9eSNate Lawson {
484986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
48555d7ff9eSNate Lawson 
48655d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
48755d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
488986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
48955d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
490986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
49155d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
492986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
493986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
494986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
495986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
49655d7ff9eSNate Lawson 	printf(END_COMMENT);
49755d7ff9eSNate Lawson }
49855d7ff9eSNate Lawson 
49955d7ff9eSNate Lawson static void
500986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
501a47e681bSScott Long {
502986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
503986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
504986dffafSJohn Baldwin 	u_int i, entries;
505a47e681bSScott Long 
506a47e681bSScott Long 	printf(BEGIN_COMMENT);
507a47e681bSScott Long 	acpi_print_sdt(sdp);
508986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
509986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
510986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
511986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
512986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
513a47e681bSScott Long 		printf("\n");
514986dffafSJohn Baldwin 		printf("\tBase Address=0x%016jx\n", alloc->Address);
515986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
516986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
517986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
518a47e681bSScott Long 	}
519a47e681bSScott Long 	printf(END_COMMENT);
520a47e681bSScott Long }
521a47e681bSScott Long 
522a47e681bSScott Long static void
523*33866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
524*33866658SJohn Baldwin {
525*33866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
526*33866658SJohn Baldwin 	UINT64 i, j;
527*33866658SJohn Baldwin 
528*33866658SJohn Baldwin 	printf(BEGIN_COMMENT);
529*33866658SJohn Baldwin 	acpi_print_sdt(sdp);
530*33866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
531*33866658SJohn Baldwin 	printf("\tLocality Count=%jd\n", slit->LocalityCount);
532*33866658SJohn Baldwin 	printf("\n\t      ");
533*33866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
534*33866658SJohn Baldwin 		printf(" %3jd", i);
535*33866658SJohn Baldwin 	printf("\n\t     +");
536*33866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
537*33866658SJohn Baldwin 		printf("----");
538*33866658SJohn Baldwin 	printf("\n");
539*33866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
540*33866658SJohn Baldwin 		printf("\t %3jd |", i);
541*33866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
542*33866658SJohn Baldwin 			printf(" %3d",
543*33866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
544*33866658SJohn Baldwin 		printf("\n");
545*33866658SJohn Baldwin 	}
546*33866658SJohn Baldwin 	printf(END_COMMENT);
547*33866658SJohn Baldwin }
548*33866658SJohn Baldwin 
549*33866658SJohn Baldwin static void
550a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
551a0333ad1SJohn Baldwin     uint32_t flags)
552a0333ad1SJohn Baldwin {
553a0333ad1SJohn Baldwin 
554a0333ad1SJohn Baldwin 	printf("\tFlags={");
555a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
556a0333ad1SJohn Baldwin 		printf("ENABLED");
557a0333ad1SJohn Baldwin 	else
558a0333ad1SJohn Baldwin 		printf("DISABLED");
559a0333ad1SJohn Baldwin 	printf("}\n");
560a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
561a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
562a0333ad1SJohn Baldwin }
563a0333ad1SJohn Baldwin 
564c031c93bSTakanori Watanabe static char *
565c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
566c031c93bSTakanori Watanabe {
567c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
568c031c93bSTakanori Watanabe 	char *eventname = NULL;
569c031c93bSTakanori Watanabe 
570c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
571c031c93bSTakanori Watanabe 
572c031c93bSTakanori Watanabe 	switch(event->event_type) {
573c031c93bSTakanori Watanabe 	case PREBOOT:
574c031c93bSTakanori Watanabe 	case POST_CODE:
575c031c93bSTakanori Watanabe 	case UNUSED:
576c031c93bSTakanori Watanabe 	case NO_ACTION:
577c031c93bSTakanori Watanabe 	case SEPARATOR:
578c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
579c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
580c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
581c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
582c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
583c031c93bSTakanori Watanabe 	case COMPACT_HASH:
584c031c93bSTakanori Watanabe 	case IPL:
585c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
586c031c93bSTakanori Watanabe 	case NONHOST_CODE:
587c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
588c031c93bSTakanori Watanabe 	case NONHOST_INFO:
589c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
590c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
591c031c93bSTakanori Watanabe 		break;
592c031c93bSTakanori Watanabe 
593c031c93bSTakanori Watanabe 	case ACTION:
594c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
595c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
596c031c93bSTakanori Watanabe 		break;
597c031c93bSTakanori Watanabe 
598c031c93bSTakanori Watanabe 	case EVENT_TAG:
599c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
600c031c93bSTakanori Watanabe 		case SMBIOS:
601c031c93bSTakanori Watanabe 		case BIS_CERT:
602c031c93bSTakanori Watanabe 		case CMOS:
603c031c93bSTakanori Watanabe 		case NVRAM:
604c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
605c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
606c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
607c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
608c031c93bSTakanori Watanabe 		case ESCD:
609c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
610c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
611c031c93bSTakanori Watanabe 		case POST_CONTENTS:
612c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
613c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
614c031c93bSTakanori Watanabe 			break;
615c031c93bSTakanori Watanabe 
616c031c93bSTakanori Watanabe 		default:
617c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
618c031c93bSTakanori Watanabe 			    pc_event->event_id);
619c031c93bSTakanori Watanabe 			break;
620c031c93bSTakanori Watanabe 		}
621c031c93bSTakanori Watanabe 		break;
622c031c93bSTakanori Watanabe 
623c031c93bSTakanori Watanabe 	default:
624c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
625c031c93bSTakanori Watanabe 		break;
626c031c93bSTakanori Watanabe 	}
627c031c93bSTakanori Watanabe 
628c031c93bSTakanori Watanabe 	return eventname;
629c031c93bSTakanori Watanabe }
630c031c93bSTakanori Watanabe 
631c031c93bSTakanori Watanabe static void
632c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
633c031c93bSTakanori Watanabe {
634c031c93bSTakanori Watanabe 	int i;
635c031c93bSTakanori Watanabe 	char *eventname;
636c031c93bSTakanori Watanabe 
637c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
638c031c93bSTakanori Watanabe 
639c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
640c031c93bSTakanori Watanabe 	printf(" 0x");
641c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
642c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
643c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
644c031c93bSTakanori Watanabe 
645c031c93bSTakanori Watanabe 	free(eventname);
646c031c93bSTakanori Watanabe }
647c031c93bSTakanori Watanabe 
648c031c93bSTakanori Watanabe static void
649c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
650c031c93bSTakanori Watanabe {
651c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
652c031c93bSTakanori Watanabe 	struct TCPAevent *event;
653977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
654c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
655c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
656c031c93bSTakanori Watanabe 
657c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
658c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
659c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
660c031c93bSTakanori Watanabe 
661c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
662c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
663c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
664c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
665c031c93bSTakanori Watanabe 		break;
666c031c93bSTakanori Watanabe 
667c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
668c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
669c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
670c031c93bSTakanori Watanabe 		break;
671c031c93bSTakanori Watanabe 
672c031c93bSTakanori Watanabe 	default:
673c031c93bSTakanori Watanabe 		printf("XXX");
674c031c93bSTakanori Watanabe 		printf(END_COMMENT);
675c031c93bSTakanori Watanabe 		return;
676c031c93bSTakanori Watanabe 	}
6770e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
678c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
679c031c93bSTakanori Watanabe 
680c031c93bSTakanori Watanabe 	if (len == 0) {
681c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
682c031c93bSTakanori Watanabe 		printf(END_COMMENT);
683c031c93bSTakanori Watanabe 		return;
684c031c93bSTakanori Watanabe 	}
6852ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
6862ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
6872ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
6882ef23c6dSTakanori Watanabe 		return;
6892ef23c6dSTakanori Watanabe 	}
690c031c93bSTakanori Watanabe 
691c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
692c031c93bSTakanori Watanabe 	vend = vaddr + len;
693c031c93bSTakanori Watanabe 
694c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
6952ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
6962ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
697c031c93bSTakanori Watanabe 			break;
6980e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
699c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
700c031c93bSTakanori Watanabe 			break;
7012ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
7022ef23c6dSTakanori Watanabe 			break;
703c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
704c031c93bSTakanori Watanabe 			break;
705c031c93bSTakanori Watanabe #if 0
706c031c93bSTakanori Watanabe 		{
707c031c93bSTakanori Watanabe 		unsigned int i, j, k;
708c031c93bSTakanori Watanabe 
709c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
710c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
711c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
712c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
713c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
714c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
715c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
716c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
717c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
718c031c93bSTakanori Watanabe 				j = i + 1;
719c031c93bSTakanori Watanabe 			}
720c031c93bSTakanori Watanabe 		}
721c031c93bSTakanori Watanabe 		printf("\n"); }
722c031c93bSTakanori Watanabe #endif
723c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
724c031c93bSTakanori Watanabe 
725c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
726c031c93bSTakanori Watanabe 	}
727c031c93bSTakanori Watanabe 
728c031c93bSTakanori Watanabe 	printf(END_COMMENT);
729c031c93bSTakanori Watanabe }
730c031c93bSTakanori Watanabe 
731a0333ad1SJohn Baldwin static void
732986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
733a0333ad1SJohn Baldwin {
734a0333ad1SJohn Baldwin 
735a0333ad1SJohn Baldwin 	printf("\tFlags={");
736986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
737a0333ad1SJohn Baldwin 		printf("ENABLED");
738a0333ad1SJohn Baldwin 	else
739a0333ad1SJohn Baldwin 		printf("DISABLED");
740986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
741a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
742986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
743a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
744a0333ad1SJohn Baldwin 	printf("}\n");
745986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
746986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
747986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
748a0333ad1SJohn Baldwin }
749a0333ad1SJohn Baldwin 
750a0333ad1SJohn Baldwin const char *srat_types[] = { "CPU", "Memory", "X2APIC" };
751a0333ad1SJohn Baldwin 
752a0333ad1SJohn Baldwin static void
753986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
754a0333ad1SJohn Baldwin {
755986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
756986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
757a0333ad1SJohn Baldwin 
758986dffafSJohn Baldwin 	if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0]))
759986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
760a0333ad1SJohn Baldwin 	else
761986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
762986dffafSJohn Baldwin 	switch (srat->Type) {
763a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
764986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
765986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
766986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
767986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
768986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
769986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
770a0333ad1SJohn Baldwin 		break;
771a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
772986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
773a0333ad1SJohn Baldwin 		break;
774a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
775986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
776986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
777986dffafSJohn Baldwin 		    x2apic->Flags);
778a0333ad1SJohn Baldwin 		break;
779a0333ad1SJohn Baldwin 	}
780a0333ad1SJohn Baldwin }
781a0333ad1SJohn Baldwin 
782a0333ad1SJohn Baldwin static void
783986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
784a0333ad1SJohn Baldwin {
785986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
786a0333ad1SJohn Baldwin 
787a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
788a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
789986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
790986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
791986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
792a0333ad1SJohn Baldwin 	printf(END_COMMENT);
793a0333ad1SJohn Baldwin }
794a0333ad1SJohn Baldwin 
795a0333ad1SJohn Baldwin static void
796986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
797c62f1cccSMitsuru IWASAKI {
798773b6454SNate Lawson 	printf("  ");
799986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
800c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
801986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
802e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
803986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
804e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
805986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
806986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
807e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
808986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
809986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
810e1e9a4bfSMitsuru IWASAKI }
811e1e9a4bfSMitsuru IWASAKI 
812945137d9SNate Lawson static void
813986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
814e1e9a4bfSMitsuru IWASAKI {
815986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
816986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
817e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
818a74172abSNate Lawson 	u_long	addr;
819e1e9a4bfSMitsuru IWASAKI 
820986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
821986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
822773b6454SNate Lawson 	printf(BEGIN_COMMENT);
823773b6454SNate Lawson 	acpi_print_sdt(rsdp);
824986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
825e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
826e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
827e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
828e1e9a4bfSMitsuru IWASAKI 			printf(", ");
829a74172abSNate Lawson 		switch (addr_size) {
830a74172abSNate Lawson 		case 4:
831986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
832a74172abSNate Lawson 			break;
833a74172abSNate Lawson 		case 8:
834986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
835a74172abSNate Lawson 			break;
836a74172abSNate Lawson 		default:
837a74172abSNate Lawson 			addr = 0;
838a74172abSNate Lawson 		}
839a74172abSNate Lawson 		assert(addr != 0);
840a74172abSNate Lawson 		printf("0x%08lx", addr);
841e1e9a4bfSMitsuru IWASAKI 	}
842e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
843c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
844e1e9a4bfSMitsuru IWASAKI }
845e1e9a4bfSMitsuru IWASAKI 
8468e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
8478e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
8488e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
8498e6a8737SNate Lawson };
8508e6a8737SNate Lawson 
851945137d9SNate Lawson static void
852986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
853e1e9a4bfSMitsuru IWASAKI {
854986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
8558e6a8737SNate Lawson 	const char *pm;
856e1e9a4bfSMitsuru IWASAKI 	char	    sep;
857e1e9a4bfSMitsuru IWASAKI 
858986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
859c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
8602177d4e6SNate Lawson 	acpi_print_sdt(sdp);
861986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
862986dffafSJohn Baldwin 	       fadt->Dsdt);
863986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
864986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
8658e6a8737SNate Lawson 		pm = "Reserved";
8668e6a8737SNate Lawson 	else
867986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
868986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
869986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
870986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
871986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
872986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
873986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
874986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
875e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
876986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
877986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
878986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
879e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
880986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
881986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
882e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
883986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
884986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
885986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
886e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
887986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
888986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
889986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
890e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
891986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
892986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
893c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
894986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
895986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
896986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
8978e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
898986dffafSJohn Baldwin 		       fadt->Gpe0Block,
899986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
900986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
9018e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
902986dffafSJohn Baldwin 		       fadt->Gpe1Block,
903986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
904986dffafSJohn Baldwin 		       fadt->Gpe1Base);
905986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
906986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
90751c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
908986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
909e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
910986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
911e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
912986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
913e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
914986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
915e1e9a4bfSMitsuru IWASAKI 
9168e6a8737SNate Lawson #define PRINTFLAG(var, flag) do {			\
917986dffafSJohn Baldwin 	if ((var) & ACPI_FADT_## flag) {		\
9188e6a8737SNate Lawson 		printf("%c%s", sep, #flag); sep = ',';	\
919e1e9a4bfSMitsuru IWASAKI 	}						\
920e1e9a4bfSMitsuru IWASAKI } while (0)
921e1e9a4bfSMitsuru IWASAKI 
9228e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
9238e6a8737SNate Lawson 	sep = '{';
924986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
925986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
926986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
927986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
928986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
929986dffafSJohn Baldwin 	if (fadt->BootFlags != 0)
9304e36f5a1SNate Lawson 		printf("}");
9314e36f5a1SNate Lawson 	printf("\n");
9328e6a8737SNate Lawson 
9338e6a8737SNate Lawson 	printf("\tFlags=");
9348e6a8737SNate Lawson 	sep = '{';
935986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
936986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
937986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
938986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
939986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
940986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
941986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
942986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
943986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
944986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
945986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
946986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
947986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
948986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
949986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
950986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
951986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
952986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
953986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
954986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
955986dffafSJohn Baldwin 	if (fadt->Flags != 0)
9568e6a8737SNate Lawson 		printf("}\n");
957e1e9a4bfSMitsuru IWASAKI 
958e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
959e1e9a4bfSMitsuru IWASAKI 
960986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
9618e6a8737SNate Lawson 		printf("\tRESET_REG=");
962986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
963986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
9648e6a8737SNate Lawson 	}
965c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
966986dffafSJohn Baldwin 		printf("\tX_FACS=0x%08lx, ", (u_long)fadt->XFacs);
967986dffafSJohn Baldwin 		printf("X_DSDT=0x%08lx\n", (u_long)fadt->XDsdt);
968c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
969986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
970986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
971c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
972986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
973c08c4e81SNate Lawson 		}
974c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
975986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
976986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
977c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
978986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
979c08c4e81SNate Lawson 		}
980986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
981773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
982986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
983c08c4e81SNate Lawson 		}
984773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
985986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
986986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
987773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
988986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
989c08c4e81SNate Lawson 		}
990986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
991773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
992986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
993c08c4e81SNate Lawson 		}
994773b6454SNate Lawson 		printf("\n");
995773b6454SNate Lawson 	}
9968e6a8737SNate Lawson 
9978e6a8737SNate Lawson 	printf(END_COMMENT);
9988e6a8737SNate Lawson }
9998e6a8737SNate Lawson 
10008e6a8737SNate Lawson static void
1001986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
10028e6a8737SNate Lawson {
10038e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1004986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1005986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1006986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
10078e6a8737SNate Lawson 
1008773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1009986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1010986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
10118e6a8737SNate Lawson 			printf("PENDING,");
1012986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
10138e6a8737SNate Lawson 			printf("OWNED");
10148e6a8737SNate Lawson 	}
1015773b6454SNate Lawson 	printf("\n");
10168e6a8737SNate Lawson 
1017773b6454SNate Lawson 	printf("\tFlags=");
1018986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
10198e6a8737SNate Lawson 		printf("S4BIOS");
1020773b6454SNate Lawson 	printf("\n");
10218e6a8737SNate Lawson 
1022986dffafSJohn Baldwin 	if (facs->XFirmwareWakingVector != 0) {
10238e6a8737SNate Lawson 		printf("\tX_Firm_Wake_Vec=%08lx\n",
1024986dffafSJohn Baldwin 		       (u_long)facs->XFirmwareWakingVector);
10258e6a8737SNate Lawson 	}
1026986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
10278e6a8737SNate Lawson 
1028c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1029e1e9a4bfSMitsuru IWASAKI }
1030e1e9a4bfSMitsuru IWASAKI 
1031945137d9SNate Lawson static void
1032986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1033e1e9a4bfSMitsuru IWASAKI {
1034773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1035773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1036773b6454SNate Lawson 	printf(END_COMMENT);
1037e1e9a4bfSMitsuru IWASAKI }
1038e1e9a4bfSMitsuru IWASAKI 
1039e1e9a4bfSMitsuru IWASAKI int
1040e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1041e1e9a4bfSMitsuru IWASAKI {
1042986dffafSJohn Baldwin 	uint8_t *bp;
1043986dffafSJohn Baldwin 	uint8_t sum;
1044e1e9a4bfSMitsuru IWASAKI 
1045e1e9a4bfSMitsuru IWASAKI 	bp = p;
1046e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1047e1e9a4bfSMitsuru IWASAKI 	while (length--)
1048e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1049e1e9a4bfSMitsuru IWASAKI 
1050e1e9a4bfSMitsuru IWASAKI 	return (sum);
1051e1e9a4bfSMitsuru IWASAKI }
1052e1e9a4bfSMitsuru IWASAKI 
1053986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1054e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1055e1e9a4bfSMitsuru IWASAKI {
1056986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1057e1e9a4bfSMitsuru IWASAKI 
1058986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1059986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1060e1e9a4bfSMitsuru IWASAKI 	return (sp);
1061e1e9a4bfSMitsuru IWASAKI }
1062e1e9a4bfSMitsuru IWASAKI 
1063945137d9SNate Lawson static void
1064986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1065e1e9a4bfSMitsuru IWASAKI {
1066c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1067a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1068986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1069986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1070986dffafSJohn Baldwin 	       rp->Revision);
1071986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1072986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1073986dffafSJohn Baldwin 		    rp->Checksum);
1074a74172abSNate Lawson 	} else {
1075a74172abSNate Lawson 		printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n",
1076986dffafSJohn Baldwin 		    (u_long)rp->XsdtPhysicalAddress, rp->Length,
1077986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1078a74172abSNate Lawson 	}
1079c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1080e1e9a4bfSMitsuru IWASAKI }
1081e1e9a4bfSMitsuru IWASAKI 
1082945137d9SNate Lawson static void
1083986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1084e1e9a4bfSMitsuru IWASAKI {
1085986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1086986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1087986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1088a74172abSNate Lawson 	vm_offset_t addr;
1089a74172abSNate Lawson 	int entries, i;
1090e1e9a4bfSMitsuru IWASAKI 
1091e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1092986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1093986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1094986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1095e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1096a74172abSNate Lawson 		switch (addr_size) {
1097a74172abSNate Lawson 		case 4:
1098986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1099a74172abSNate Lawson 			break;
1100a74172abSNate Lawson 		case 8:
1101986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1102a74172abSNate Lawson 			break;
1103a74172abSNate Lawson 		default:
1104a74172abSNate Lawson 			assert((addr = 0));
1105a74172abSNate Lawson 		}
1106a74172abSNate Lawson 
1107986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1108986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
11095cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1110986dffafSJohn Baldwin 			    sdp->Signature);
11115cf6d493SNate Lawson 			continue;
11125cf6d493SNate Lawson 		}
1113986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
11142177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1115986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1116986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1117986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
111879d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1119986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
112055d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1121986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1122a47e681bSScott Long 			acpi_handle_mcfg(sdp);
1123*33866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
1124*33866658SJohn Baldwin 			acpi_handle_slit(sdp);
1125986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1126a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1127c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1128c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1129773b6454SNate Lawson 		else {
1130773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1131773b6454SNate Lawson 			acpi_print_sdt(sdp);
1132773b6454SNate Lawson 			printf(END_COMMENT);
1133773b6454SNate Lawson 		}
1134e1e9a4bfSMitsuru IWASAKI 	}
1135e1e9a4bfSMitsuru IWASAKI }
1136c62f1cccSMitsuru IWASAKI 
1137986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1138476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1139945137d9SNate Lawson {
1140986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1141986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1142945137d9SNate Lawson 
1143945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1144945137d9SNate Lawson 	if (!rp)
1145945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1146945137d9SNate Lawson 
1147945137d9SNate Lawson 	if (tflag)
1148945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1149986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1150986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1151986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1152986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1153945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1154a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1155a74172abSNate Lawson 	} else {
1156986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1157986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1158986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1159a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1160a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1161a74172abSNate Lawson 	}
1162945137d9SNate Lawson 	return (rsdp);
1163945137d9SNate Lawson }
1164c62f1cccSMitsuru IWASAKI 
116562c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1166bfa3f012SMarcel Moolenaar static int
1167986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1168bfa3f012SMarcel Moolenaar {
1169986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1170986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1171bfa3f012SMarcel Moolenaar 	uint8_t sum;
1172bfa3f012SMarcel Moolenaar 
117362c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1174bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1175bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1176986dffafSJohn Baldwin 		sdt.Checksum = 0;
1177986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1178986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1179986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1180f7675a56SNate Lawson 		while (ssdt != NULL) {
1181986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1182986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1183986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1184986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1185bfa3f012SMarcel Moolenaar 		}
1186986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1187986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1188bfa3f012SMarcel Moolenaar 	}
118962c7bde1SNate Lawson 
119062c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1191986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1192986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
119362c7bde1SNate Lawson 
1194b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1195f7675a56SNate Lawson 	if (rsdt != NULL) {
1196bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1197bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1198986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1199986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1200bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1201bfa3f012SMarcel Moolenaar 		}
1202bfa3f012SMarcel Moolenaar 	}
1203bfa3f012SMarcel Moolenaar 	return (0);
1204bfa3f012SMarcel Moolenaar }
1205bfa3f012SMarcel Moolenaar 
1206c62f1cccSMitsuru IWASAKI void
1207986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1208c62f1cccSMitsuru IWASAKI {
1209945137d9SNate Lawson 	int	fd;
1210945137d9SNate Lawson 	mode_t	mode;
1211945137d9SNate Lawson 
1212945137d9SNate Lawson 	assert(outfile != NULL);
1213945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1214945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1215945137d9SNate Lawson 	if (fd == -1) {
1216945137d9SNate Lawson 		perror("dsdt_save_file");
1217945137d9SNate Lawson 		return;
1218945137d9SNate Lawson 	}
1219bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1220945137d9SNate Lawson 	close(fd);
1221c62f1cccSMitsuru IWASAKI }
1222c62f1cccSMitsuru IWASAKI 
1223945137d9SNate Lawson void
1224986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1225c62f1cccSMitsuru IWASAKI {
122699065116SJung-uk Kim 	char buf[PATH_MAX], tmpstr[PATH_MAX];
122799065116SJung-uk Kim 	const char *tmpdir;
122899065116SJung-uk Kim 	char *tmpext;
1229945137d9SNate Lawson 	FILE *fp;
123099065116SJung-uk Kim 	size_t len;
123199065116SJung-uk Kim 	int fd;
1232945137d9SNate Lawson 
123399065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
123499065116SJung-uk Kim 	if (tmpdir == NULL)
123599065116SJung-uk Kim 		tmpdir = _PATH_TMP;
123699065116SJung-uk Kim 	strncpy(tmpstr, tmpdir, sizeof(tmpstr));
123799065116SJung-uk Kim 	if (realpath(tmpstr, buf) == NULL) {
1238d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
123999065116SJung-uk Kim 		return;
124099065116SJung-uk Kim 	}
124199065116SJung-uk Kim 	strncpy(tmpstr, buf, sizeof(tmpstr));
1242d6a6e590SJung-uk Kim 	strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(buf));
1243d6a6e590SJung-uk Kim 	len = strlen(tmpstr);
124499065116SJung-uk Kim 	tmpext = tmpstr + len;
124599065116SJung-uk Kim 	strncpy(tmpext, "XXXXXX", sizeof(tmpstr) - len);
1246945137d9SNate Lawson 	fd = mkstemp(tmpstr);
1247945137d9SNate Lawson 	if (fd < 0) {
1248945137d9SNate Lawson 		perror("iasl tmp file");
1249945137d9SNate Lawson 		return;
1250c62f1cccSMitsuru IWASAKI 	}
1251bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1252945137d9SNate Lawson 	close(fd);
1253945137d9SNate Lawson 
1254945137d9SNate Lawson 	/* Run iasl -d on the temp file */
1255945137d9SNate Lawson 	if (fork() == 0) {
1256945137d9SNate Lawson 		close(STDOUT_FILENO);
1257945137d9SNate Lawson 		if (vflag == 0)
1258945137d9SNate Lawson 			close(STDERR_FILENO);
125999065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1260945137d9SNate Lawson 		err(1, "exec");
1261c62f1cccSMitsuru IWASAKI 	}
1262c62f1cccSMitsuru IWASAKI 
1263945137d9SNate Lawson 	wait(NULL);
1264945137d9SNate Lawson 	unlink(tmpstr);
1265945137d9SNate Lawson 
1266945137d9SNate Lawson 	/* Dump iasl's output to stdout */
126799065116SJung-uk Kim 	strncpy(tmpext, "dsl", sizeof(tmpstr) - len);
126899065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
126999065116SJung-uk Kim 	unlink(tmpstr);
1270945137d9SNate Lawson 	if (fp == NULL) {
1271945137d9SNate Lawson 		perror("iasl tmp file (read)");
1272945137d9SNate Lawson 		return;
1273945137d9SNate Lawson 	}
1274945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1275945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1276945137d9SNate Lawson 	fclose(fp);
1277c62f1cccSMitsuru IWASAKI }
1278c62f1cccSMitsuru IWASAKI 
1279945137d9SNate Lawson void
1280986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1281c62f1cccSMitsuru IWASAKI {
1282945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1283c62f1cccSMitsuru IWASAKI }
1284c62f1cccSMitsuru IWASAKI 
1285bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1286986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1287986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1288c62f1cccSMitsuru IWASAKI {
1289986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1290986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1291986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1292a74172abSNate Lawson 	vm_offset_t addr;
1293a74172abSNate Lawson 	int entries, i;
1294945137d9SNate Lawson 
1295986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1296986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1297986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1298945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1299a74172abSNate Lawson 		switch (addr_size) {
1300a74172abSNate Lawson 		case 4:
1301986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1302a74172abSNate Lawson 			break;
1303a74172abSNate Lawson 		case 8:
1304986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1305a74172abSNate Lawson 			break;
1306a74172abSNate Lawson 		default:
1307a74172abSNate Lawson 			assert((addr = 0));
1308a74172abSNate Lawson 		}
1309986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1310bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1311bfa3f012SMarcel Moolenaar 			if (sdt == last)
1312bfa3f012SMarcel Moolenaar 				last = NULL;
1313bfa3f012SMarcel Moolenaar 			continue;
1314bfa3f012SMarcel Moolenaar 		}
1315986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1316a74172abSNate Lawson 			continue;
1317986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1318945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1319945137d9SNate Lawson 		return (sdt);
1320c62f1cccSMitsuru IWASAKI 	}
1321c62f1cccSMitsuru IWASAKI 
1322945137d9SNate Lawson 	return (NULL);
1323c62f1cccSMitsuru IWASAKI }
1324c62f1cccSMitsuru IWASAKI 
1325986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1326986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1327c62f1cccSMitsuru IWASAKI {
1328986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1329c62f1cccSMitsuru IWASAKI 
1330986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1331c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1332986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
13332e71eb12SNate Lawson 	else
1334986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1335986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1336945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1337945137d9SNate Lawson 	return (sdt);
1338c62f1cccSMitsuru IWASAKI }
1339