xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision 27941afae670b92722d63b4ce3efc8e4b2d17830)
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);
6633866658SJohn 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 
126ec650989SNeel Natu #define	PRINTFLAG_END()		printflag_end()
127ec650989SNeel Natu 
128ec650989SNeel Natu static char pf_sep = '{';
129ec650989SNeel Natu 
130ec650989SNeel Natu static void
131ec650989SNeel Natu printflag_end(void)
132ec650989SNeel Natu {
133ec650989SNeel Natu 
134ec650989SNeel Natu 	if (pf_sep != '{') {
135ec650989SNeel Natu 		printf("}");
136ec650989SNeel Natu 		pf_sep = '{';
137ec650989SNeel Natu 	}
138ec650989SNeel Natu 	printf("\n");
139ec650989SNeel Natu }
140ec650989SNeel Natu 
141ec650989SNeel Natu static void
142ec650989SNeel Natu printflag(uint64_t var, uint64_t mask, const char *name)
143ec650989SNeel Natu {
144ec650989SNeel Natu 
145ec650989SNeel Natu 	if (var & mask) {
146ec650989SNeel Natu 		printf("%c%s", pf_sep, name);
147ec650989SNeel Natu 		pf_sep = ',';
148ec650989SNeel Natu 	}
149ec650989SNeel Natu }
150ec650989SNeel Natu 
151e1e9a4bfSMitsuru IWASAKI static void
152e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
153e1e9a4bfSMitsuru IWASAKI {
154e1e9a4bfSMitsuru IWASAKI 	int	c;
155e1e9a4bfSMitsuru IWASAKI 
156e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
157e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
158e1e9a4bfSMitsuru IWASAKI 		length--;
159e1e9a4bfSMitsuru IWASAKI 
160e1e9a4bfSMitsuru IWASAKI 	while (length--) {
161e1e9a4bfSMitsuru IWASAKI 		c = *s++;
162e1e9a4bfSMitsuru IWASAKI 		putchar(c);
163e1e9a4bfSMitsuru IWASAKI 	}
164e1e9a4bfSMitsuru IWASAKI }
165e1e9a4bfSMitsuru IWASAKI 
166e1e9a4bfSMitsuru IWASAKI static void
167986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1688e6a8737SNate Lawson {
169986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1708e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
1717d369c6eSJung-uk Kim 		if (gas->BitWidth <= 32)
1727d369c6eSJung-uk Kim 			printf("0x%08x:%u[%u] (Memory)",
1737d369c6eSJung-uk Kim 			    (u_int)gas->Address, gas->BitOffset,
1747d369c6eSJung-uk Kim 			    gas->BitWidth);
1757d369c6eSJung-uk Kim 		else
1767d369c6eSJung-uk Kim 			printf("0x%016jx:%u[%u] (Memory)",
1777d369c6eSJung-uk Kim 			    (uintmax_t)gas->Address, gas->BitOffset,
1787d369c6eSJung-uk Kim 			    gas->BitWidth);
1798e6a8737SNate Lawson 		break;
1808e6a8737SNate Lawson 	case ACPI_GAS_IO:
1817d369c6eSJung-uk Kim 		printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
182986dffafSJohn Baldwin 		    gas->BitOffset, gas->BitWidth);
1838e6a8737SNate Lawson 		break;
1848e6a8737SNate Lawson 	case ACPI_GAS_PCI:
185986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
186986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
187986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1888e6a8737SNate Lawson 		break;
1898e6a8737SNate Lawson 	/* XXX How to handle these below? */
1908e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
191986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
192986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1938e6a8737SNate Lawson 		break;
1948e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
195986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
196986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1978e6a8737SNate Lawson 		break;
198986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
199986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
200986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
2018e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
2028e6a8737SNate Lawson 	default:
2037d369c6eSJung-uk Kim 		printf("0x%016jx (?)", (uintmax_t)gas->Address);
2048e6a8737SNate Lawson 		break;
2058e6a8737SNate Lawson 	}
2068e6a8737SNate Lawson }
2078e6a8737SNate Lawson 
208c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
209c2962974SNate Lawson static int
210986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
211e1e9a4bfSMitsuru IWASAKI {
212c2962974SNate Lawson 	int fadt_revision;
213e1e9a4bfSMitsuru IWASAKI 
214c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
215c83f0f99SNate Lawson 	if (addr_size == 8) {
216c83f0f99SNate Lawson 		fadt_revision = 2;
2178e6a8737SNate Lawson 
218773b6454SNate Lawson 		/*
219c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
220c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
221c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
222c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
223c83f0f99SNate Lawson 		 * version for all subsequent tables.
224773b6454SNate Lawson 		 */
225986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
226986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
227c83f0f99SNate Lawson 			fadt_revision = 1;
228c2962974SNate Lawson 	} else
229c83f0f99SNate Lawson 		fadt_revision = 1;
230c2962974SNate Lawson 	return (fadt_revision);
231c83f0f99SNate Lawson }
232c2962974SNate Lawson 
233c2962974SNate Lawson static void
234986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
235c2962974SNate Lawson {
236986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
237986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
238986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
239c2962974SNate Lawson 	int		fadt_revision;
240c2962974SNate Lawson 
241986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2422177d4e6SNate Lawson 	acpi_print_fadt(sdp);
243c83f0f99SNate Lawson 
244c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
245c83f0f99SNate Lawson 	if (fadt_revision == 1)
246986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
247773b6454SNate Lawson 	else
248986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
249986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2508e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2518e6a8737SNate Lawson 	acpi_print_facs(facs);
2528e6a8737SNate Lawson 
253c83f0f99SNate Lawson 	if (fadt_revision == 1)
254986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
255773b6454SNate Lawson 	else
256986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
257986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
258945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
259945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
260c62f1cccSMitsuru IWASAKI }
261c62f1cccSMitsuru IWASAKI 
262c62f1cccSMitsuru IWASAKI static void
263986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
264986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
265986dffafSJohn Baldwin {
266986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
267986dffafSJohn Baldwin 	char *end;
268986dffafSJohn Baldwin 
269986dffafSJohn Baldwin 	subtable = first;
270986dffafSJohn Baldwin 	end = (char *)table + table->Length;
271986dffafSJohn Baldwin 	while ((char *)subtable < end) {
272986dffafSJohn Baldwin 		printf("\n");
273f5d0a8f7SEd Maste 		if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
274f5d0a8f7SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
275f5d0a8f7SEd Maste 			return;
276f5d0a8f7SEd Maste 		}
277986dffafSJohn Baldwin 		action(subtable);
278986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
279986dffafSJohn Baldwin 		    subtable->Length);
280986dffafSJohn Baldwin 	}
281986dffafSJohn Baldwin }
282986dffafSJohn Baldwin 
283986dffafSJohn Baldwin static void
2840a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
2850a473124SJohn Baldwin {
2860a473124SJohn Baldwin 
2870a473124SJohn Baldwin 	printf("\tACPI CPU=");
2880a473124SJohn Baldwin 	if (cpu_id == 0xff)
2890a473124SJohn Baldwin 		printf("ALL\n");
2900a473124SJohn Baldwin 	else
2910a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
2920a473124SJohn Baldwin }
2930a473124SJohn Baldwin 
2940a473124SJohn Baldwin static void
295986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
2960a473124SJohn Baldwin {
297986dffafSJohn Baldwin 
298986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
299986dffafSJohn Baldwin 	if (uid_string != NULL)
300986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
301986dffafSJohn Baldwin 	printf("\n");
302986dffafSJohn Baldwin }
303986dffafSJohn Baldwin 
304986dffafSJohn Baldwin static void
305986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
306986dffafSJohn Baldwin {
307986dffafSJohn Baldwin 
3080a473124SJohn Baldwin 	printf("\tFlags={");
309986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
3100a473124SJohn Baldwin 		printf("ENABLED");
3110a473124SJohn Baldwin 	else
3120a473124SJohn Baldwin 		printf("DISABLED");
3130a473124SJohn Baldwin 	printf("}\n");
314986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3150a473124SJohn Baldwin }
3160a473124SJohn Baldwin 
3170a473124SJohn Baldwin static void
318986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
3190a473124SJohn Baldwin {
320986dffafSJohn Baldwin 
321986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3220a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
323986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
3240a473124SJohn Baldwin }
3250a473124SJohn Baldwin 
3260a473124SJohn Baldwin static void
327986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
3280a473124SJohn Baldwin {
3290a473124SJohn Baldwin 
3300a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
331986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
332986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
3330a473124SJohn Baldwin 		printf("conforming");
3340a473124SJohn Baldwin 		break;
335986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3360a473124SJohn Baldwin 		printf("active-hi");
3370a473124SJohn Baldwin 		break;
338986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3390a473124SJohn Baldwin 		printf("active-lo");
3400a473124SJohn Baldwin 		break;
3410a473124SJohn Baldwin 	default:
342986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3430a473124SJohn Baldwin 		break;
3440a473124SJohn Baldwin 	}
3450a473124SJohn Baldwin 	printf(", Trigger=");
346986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
347986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3480a473124SJohn Baldwin 		printf("conforming");
3490a473124SJohn Baldwin 		break;
350986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3510a473124SJohn Baldwin 		printf("edge");
3520a473124SJohn Baldwin 		break;
353986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3540a473124SJohn Baldwin 		printf("level");
3550a473124SJohn Baldwin 		break;
3560a473124SJohn Baldwin 	default:
357986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3580a473124SJohn Baldwin 	}
3590a473124SJohn Baldwin 	printf("}\n");
3600a473124SJohn Baldwin }
3610a473124SJohn Baldwin 
3620a473124SJohn Baldwin static void
3632b2b1f42SAndrew Turner acpi_print_gicc_flags(uint32_t flags)
3642b2b1f42SAndrew Turner {
3652b2b1f42SAndrew Turner 
3662b2b1f42SAndrew Turner 	printf("\tFlags={Performance intr=");
3672b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
3682b2b1f42SAndrew Turner 		printf("edge");
3692b2b1f42SAndrew Turner 	else
3702b2b1f42SAndrew Turner 		printf("level");
3712b2b1f42SAndrew Turner 	printf(", VGIC intr=");
3722b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_VGIC_IRQ_MODE)
3732b2b1f42SAndrew Turner 		printf("edge");
3742b2b1f42SAndrew Turner 	else
3752b2b1f42SAndrew Turner 		printf("level");
3762b2b1f42SAndrew Turner 	printf("}\n");
3772b2b1f42SAndrew Turner }
3782b2b1f42SAndrew Turner 
3792b2b1f42SAndrew Turner static void
380986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
3810a473124SJohn Baldwin {
3820a473124SJohn Baldwin 
383986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
384986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
385986dffafSJohn Baldwin }
386986dffafSJohn Baldwin 
387986dffafSJohn Baldwin static void
388986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
389986dffafSJohn Baldwin {
390986dffafSJohn Baldwin 
391986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
3920a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
3930a473124SJohn Baldwin }
3940a473124SJohn Baldwin 
395*27941afaSEd Maste static const char *apic_types[] = {
396*27941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
397*27941afaSEd Maste     [ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
398*27941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
399*27941afaSEd Maste     [ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
400*27941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
401*27941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
402*27941afaSEd Maste     [ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
403*27941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
404*27941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
405*27941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
406*27941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
407*27941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
408*27941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
409*27941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
410*27941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
411*27941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
412*27941afaSEd Maste };
413*27941afaSEd Maste 
414bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
4150a473124SJohn Baldwin 					    "Corrected Platform Error" };
4160a473124SJohn Baldwin 
4170a473124SJohn Baldwin static void
418986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
4190a473124SJohn Baldwin {
420986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
421986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
422986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
423986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
424986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
425986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
426986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
427986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
428986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
429986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
430986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
4312b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_INTERRUPT *gicc;
4322b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
4332b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
4342b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_TRANSLATOR *gict;
4350a473124SJohn Baldwin 
436c86932b6SMarcelo Araujo 	if (mp->Type < nitems(apic_types))
437986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
438a0333ad1SJohn Baldwin 	else
439986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
440986dffafSJohn Baldwin 	switch (mp->Type) {
441986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
442986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
443986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
444986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4450a473124SJohn Baldwin 		break;
446986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
447986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
448986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
449986dffafSJohn Baldwin 		    ioapic->Address);
4500a473124SJohn Baldwin 		break;
451986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
452986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
453986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
454986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
455986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
4560a473124SJohn Baldwin 		break;
457986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
458986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
459986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
4600a473124SJohn Baldwin 		break;
461986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
462986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
463986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
464986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
4650a473124SJohn Baldwin 		break;
466986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
467986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
468945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
469986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
4700a473124SJohn Baldwin 		break;
471986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
472986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
473986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
474986dffafSJohn Baldwin 		    iosapic->Address);
4750a473124SJohn Baldwin 		break;
476986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
477986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
478986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
479986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
480986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
481986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
482986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
4830a473124SJohn Baldwin 		break;
484986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
485986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
486c86932b6SMarcelo Araujo 		if (isrc->Type < nitems(platform_int_types))
487986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
488986dffafSJohn Baldwin 		else
489986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
490986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
491986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
492986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
493986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
494986dffafSJohn Baldwin 		break;
495986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
496986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
497986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
498986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
499986dffafSJohn Baldwin 		break;
500986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
501986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
502986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
503986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
5040a473124SJohn Baldwin 		break;
5052b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
5062b2b1f42SAndrew Turner 		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
5072b2b1f42SAndrew Turner 		acpi_print_cpu_uid(gicc->Uid, NULL);
5082b2b1f42SAndrew Turner 		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
5092b2b1f42SAndrew Turner 		acpi_print_gicc_flags(gicc->Flags);
5102b2b1f42SAndrew Turner 		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
5112b2b1f42SAndrew Turner 		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
5122b2b1f42SAndrew Turner 		printf("\tParked ADDR=%016jx\n",
5132b2b1f42SAndrew Turner 		    (uintmax_t)gicc->ParkedAddress);
5142b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
5152b2b1f42SAndrew Turner 		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
5162b2b1f42SAndrew Turner 		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
5172b2b1f42SAndrew Turner 		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
5182b2b1f42SAndrew Turner 		printf("\tGICR ADDR=%016jx\n",
5192b2b1f42SAndrew Turner 		    (uintmax_t)gicc->GicrBaseAddress);
5202b2b1f42SAndrew Turner 		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
5212b2b1f42SAndrew Turner 		printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass);
5222b2b1f42SAndrew Turner 		break;
5232b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
5242b2b1f42SAndrew Turner 		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
5252b2b1f42SAndrew Turner 		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
5262b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
5272b2b1f42SAndrew Turner 		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
5282b2b1f42SAndrew Turner 		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
5292b2b1f42SAndrew Turner 		break;
5302b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
5312b2b1f42SAndrew Turner 		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
5322b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
5332b2b1f42SAndrew Turner 		printf("\tLength=%08x\n", gicr->Length);
5342b2b1f42SAndrew Turner 		break;
5352b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
5362b2b1f42SAndrew Turner 		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
5372b2b1f42SAndrew Turner 		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
5382b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
5392b2b1f42SAndrew Turner 		break;
5400a473124SJohn Baldwin 	}
5410a473124SJohn Baldwin }
5420a473124SJohn Baldwin 
5430a473124SJohn Baldwin static void
544986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
5450a473124SJohn Baldwin {
546986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
5470a473124SJohn Baldwin 
548773b6454SNate Lawson 	printf(BEGIN_COMMENT);
549773b6454SNate Lawson 	acpi_print_sdt(sdp);
550986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
551986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
5520a473124SJohn Baldwin 	printf("\tFlags={");
553986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
5540a473124SJohn Baldwin 		printf("PC-AT");
5550a473124SJohn Baldwin 	printf("}\n");
556986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
5570a473124SJohn Baldwin 	printf(END_COMMENT);
5580a473124SJohn Baldwin }
5590a473124SJohn Baldwin 
5600a473124SJohn Baldwin static void
561986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
56279d7565cSPeter Wemm {
563986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
56479d7565cSPeter Wemm 
565773b6454SNate Lawson 	printf(BEGIN_COMMENT);
566773b6454SNate Lawson 	acpi_print_sdt(sdp);
567986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
568986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
56987f9f09aSTakanori Watanabe 	printf("\tADDR=");
570986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
571986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
572986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
573986dffafSJohn Baldwin 	    8);
574986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
575986dffafSJohn Baldwin 	    1 : 0);
57679d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
577986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
57879d7565cSPeter Wemm 		printf("TRUE}\n");
57979d7565cSPeter Wemm 	else
58079d7565cSPeter Wemm 		printf("FALSE}\n");
581986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
582986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
5839785e979SNeel Natu 	printf("\tFlags=0x%02x\n", hpet->Flags);
58479d7565cSPeter Wemm 	printf(END_COMMENT);
58579d7565cSPeter Wemm }
58679d7565cSPeter Wemm 
58779d7565cSPeter Wemm static void
588986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
58955d7ff9eSNate Lawson {
590986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
59155d7ff9eSNate Lawson 
59255d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
59355d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
594986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
59555d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
596986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
59755d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
598986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
599986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
600986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
601986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
60255d7ff9eSNate Lawson 	printf(END_COMMENT);
60355d7ff9eSNate Lawson }
60455d7ff9eSNate Lawson 
60555d7ff9eSNate Lawson static void
606986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
607a47e681bSScott Long {
608986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
609986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
610986dffafSJohn Baldwin 	u_int i, entries;
611a47e681bSScott Long 
612a47e681bSScott Long 	printf(BEGIN_COMMENT);
613a47e681bSScott Long 	acpi_print_sdt(sdp);
614986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
615986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
616986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
617986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
618986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
619a47e681bSScott Long 		printf("\n");
6200c10b85aSJung-uk Kim 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
621986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
622986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
623986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
624a47e681bSScott Long 	}
625a47e681bSScott Long 	printf(END_COMMENT);
626a47e681bSScott Long }
627a47e681bSScott Long 
628a47e681bSScott Long static void
62933866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
63033866658SJohn Baldwin {
63133866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
63233866658SJohn Baldwin 	UINT64 i, j;
63333866658SJohn Baldwin 
63433866658SJohn Baldwin 	printf(BEGIN_COMMENT);
63533866658SJohn Baldwin 	acpi_print_sdt(sdp);
63633866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
6370c10b85aSJung-uk Kim 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
63833866658SJohn Baldwin 	printf("\n\t      ");
63933866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
6400c10b85aSJung-uk Kim 		printf(" %3ju", (uintmax_t)i);
64133866658SJohn Baldwin 	printf("\n\t     +");
64233866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
64333866658SJohn Baldwin 		printf("----");
64433866658SJohn Baldwin 	printf("\n");
64533866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
6460c10b85aSJung-uk Kim 		printf("\t %3ju |", (uintmax_t)i);
64733866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
64833866658SJohn Baldwin 			printf(" %3d",
64933866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
65033866658SJohn Baldwin 		printf("\n");
65133866658SJohn Baldwin 	}
65233866658SJohn Baldwin 	printf(END_COMMENT);
65333866658SJohn Baldwin }
65433866658SJohn Baldwin 
65533866658SJohn Baldwin static void
656a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
657a0333ad1SJohn Baldwin     uint32_t flags)
658a0333ad1SJohn Baldwin {
659a0333ad1SJohn Baldwin 
660a0333ad1SJohn Baldwin 	printf("\tFlags={");
661a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
662a0333ad1SJohn Baldwin 		printf("ENABLED");
663a0333ad1SJohn Baldwin 	else
664a0333ad1SJohn Baldwin 		printf("DISABLED");
665a0333ad1SJohn Baldwin 	printf("}\n");
666a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
667a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
668a0333ad1SJohn Baldwin }
669a0333ad1SJohn Baldwin 
670c031c93bSTakanori Watanabe static char *
671c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
672c031c93bSTakanori Watanabe {
673c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
674c031c93bSTakanori Watanabe 	char *eventname = NULL;
675c031c93bSTakanori Watanabe 
676c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
677c031c93bSTakanori Watanabe 
678c031c93bSTakanori Watanabe 	switch(event->event_type) {
679c031c93bSTakanori Watanabe 	case PREBOOT:
680c031c93bSTakanori Watanabe 	case POST_CODE:
681c031c93bSTakanori Watanabe 	case UNUSED:
682c031c93bSTakanori Watanabe 	case NO_ACTION:
683c031c93bSTakanori Watanabe 	case SEPARATOR:
684c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
685c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
686c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
687c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
688c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
689c031c93bSTakanori Watanabe 	case COMPACT_HASH:
690c031c93bSTakanori Watanabe 	case IPL:
691c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
692c031c93bSTakanori Watanabe 	case NONHOST_CODE:
693c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
694c031c93bSTakanori Watanabe 	case NONHOST_INFO:
695c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
696c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
697c031c93bSTakanori Watanabe 		break;
698c031c93bSTakanori Watanabe 
699c031c93bSTakanori Watanabe 	case ACTION:
700c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
701c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
702c031c93bSTakanori Watanabe 		break;
703c031c93bSTakanori Watanabe 
704c031c93bSTakanori Watanabe 	case EVENT_TAG:
705c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
706c031c93bSTakanori Watanabe 		case SMBIOS:
707c031c93bSTakanori Watanabe 		case BIS_CERT:
708c031c93bSTakanori Watanabe 		case CMOS:
709c031c93bSTakanori Watanabe 		case NVRAM:
710c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
711c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
712c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
713c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
714c031c93bSTakanori Watanabe 		case ESCD:
715c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
716c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
717c031c93bSTakanori Watanabe 		case POST_CONTENTS:
718c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
719c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
720c031c93bSTakanori Watanabe 			break;
721c031c93bSTakanori Watanabe 
722c031c93bSTakanori Watanabe 		default:
723c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
724c031c93bSTakanori Watanabe 			    pc_event->event_id);
725c031c93bSTakanori Watanabe 			break;
726c031c93bSTakanori Watanabe 		}
727c031c93bSTakanori Watanabe 		break;
728c031c93bSTakanori Watanabe 
729c031c93bSTakanori Watanabe 	default:
730c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
731c031c93bSTakanori Watanabe 		break;
732c031c93bSTakanori Watanabe 	}
733c031c93bSTakanori Watanabe 
734c031c93bSTakanori Watanabe 	return eventname;
735c031c93bSTakanori Watanabe }
736c031c93bSTakanori Watanabe 
737c031c93bSTakanori Watanabe static void
738c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
739c031c93bSTakanori Watanabe {
740c031c93bSTakanori Watanabe 	int i;
741c031c93bSTakanori Watanabe 	char *eventname;
742c031c93bSTakanori Watanabe 
743c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
744c031c93bSTakanori Watanabe 
745c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
746c031c93bSTakanori Watanabe 	printf(" 0x");
747c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
748c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
749c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
750c031c93bSTakanori Watanabe 
751c031c93bSTakanori Watanabe 	free(eventname);
752c031c93bSTakanori Watanabe }
753c031c93bSTakanori Watanabe 
754c031c93bSTakanori Watanabe static void
755c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
756c031c93bSTakanori Watanabe {
757c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
758c031c93bSTakanori Watanabe 	struct TCPAevent *event;
759977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
760c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
761c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
762c031c93bSTakanori Watanabe 
763c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
764c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
765c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
766c031c93bSTakanori Watanabe 
767c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
768c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
769c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
770c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
771c031c93bSTakanori Watanabe 		break;
772c031c93bSTakanori Watanabe 
773c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
774c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
775c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
776c031c93bSTakanori Watanabe 		break;
777c031c93bSTakanori Watanabe 
778c031c93bSTakanori Watanabe 	default:
779c031c93bSTakanori Watanabe 		printf("XXX");
780c031c93bSTakanori Watanabe 		printf(END_COMMENT);
781c031c93bSTakanori Watanabe 		return;
782c031c93bSTakanori Watanabe 	}
7830e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
784c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
785c031c93bSTakanori Watanabe 
786c031c93bSTakanori Watanabe 	if (len == 0) {
787c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
788c031c93bSTakanori Watanabe 		printf(END_COMMENT);
789c031c93bSTakanori Watanabe 		return;
790c031c93bSTakanori Watanabe 	}
7912ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
7922ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
7932ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
7942ef23c6dSTakanori Watanabe 		return;
7952ef23c6dSTakanori Watanabe 	}
796c031c93bSTakanori Watanabe 
797c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
798c031c93bSTakanori Watanabe 	vend = vaddr + len;
799c031c93bSTakanori Watanabe 
800c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
8012ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
8022ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
803c031c93bSTakanori Watanabe 			break;
8040e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
805c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
806c031c93bSTakanori Watanabe 			break;
8072ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
8082ef23c6dSTakanori Watanabe 			break;
809c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
810c031c93bSTakanori Watanabe 			break;
811c031c93bSTakanori Watanabe #if 0
812c031c93bSTakanori Watanabe 		{
813c031c93bSTakanori Watanabe 		unsigned int i, j, k;
814c031c93bSTakanori Watanabe 
815c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
816c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
817c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
818c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
819c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
820c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
821c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
822c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
823c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
824c031c93bSTakanori Watanabe 				j = i + 1;
825c031c93bSTakanori Watanabe 			}
826c031c93bSTakanori Watanabe 		}
827c031c93bSTakanori Watanabe 		printf("\n"); }
828c031c93bSTakanori Watanabe #endif
829c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
830c031c93bSTakanori Watanabe 
831c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
832c031c93bSTakanori Watanabe 	}
833c031c93bSTakanori Watanabe 
834c031c93bSTakanori Watanabe 	printf(END_COMMENT);
835c031c93bSTakanori Watanabe }
836c031c93bSTakanori Watanabe 
837ec650989SNeel Natu static const char *
838ec650989SNeel Natu devscope_type2str(int type)
839ec650989SNeel Natu {
840ec650989SNeel Natu 	static char typebuf[16];
841ec650989SNeel Natu 
842ec650989SNeel Natu 	switch (type) {
843ec650989SNeel Natu 	case 1:
844ec650989SNeel Natu 		return ("PCI Endpoint Device");
845ec650989SNeel Natu 	case 2:
846ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
847ec650989SNeel Natu 	case 3:
848ec650989SNeel Natu 		return ("IOAPIC");
849ec650989SNeel Natu 	case 4:
850ec650989SNeel Natu 		return ("HPET");
851ec650989SNeel Natu 	default:
852ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
853ec650989SNeel Natu 		return (typebuf);
854ec650989SNeel Natu 	}
855ec650989SNeel Natu }
856ec650989SNeel Natu 
857ec650989SNeel Natu static int
858ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
859ec650989SNeel Natu {
860ec650989SNeel Natu 	char sep;
861ec650989SNeel Natu 	int pathlen;
862ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
863ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
864ec650989SNeel Natu 
865ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
866ec650989SNeel Natu 		return (-1);
867ec650989SNeel Natu 
868ec650989SNeel Natu 	if (remaining < devscope->Length)
869ec650989SNeel Natu 		return (-1);
870ec650989SNeel Natu 
871ec650989SNeel Natu 	printf("\n");
872ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
873ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
874ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
875ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
876ec650989SNeel Natu 
877ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
878ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
879ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
880ec650989SNeel Natu 	if (path < pathend) {
881ec650989SNeel Natu 		sep = '{';
882ec650989SNeel Natu 		printf("\t\tPath=");
883ec650989SNeel Natu 		do {
884ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
885ec650989SNeel Natu 			sep=',';
886ec650989SNeel Natu 			path++;
887ec650989SNeel Natu 		} while (path < pathend);
888ec650989SNeel Natu 		printf("}\n");
889ec650989SNeel Natu 	}
890ec650989SNeel Natu 
891ec650989SNeel Natu 	return (devscope->Length);
892ec650989SNeel Natu }
893ec650989SNeel Natu 
894ec650989SNeel Natu static void
895ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
896ec650989SNeel Natu {
897ec650989SNeel Natu 	char *cp;
898ec650989SNeel Natu 	int remaining, consumed;
899ec650989SNeel Natu 
900ec650989SNeel Natu 	printf("\n");
901ec650989SNeel Natu 	printf("\tType=DRHD\n");
902ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
903ec650989SNeel Natu 
904ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
905ec650989SNeel Natu 
906ec650989SNeel Natu 	printf("\tFlags=");
907ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
908ec650989SNeel Natu 	PRINTFLAG_END();
909ec650989SNeel Natu 
910ec650989SNeel Natu #undef PRINTFLAG
911ec650989SNeel Natu 
912ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
9137d369c6eSJung-uk Kim 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
914ec650989SNeel Natu 
915ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
916ec650989SNeel Natu 	if (remaining > 0)
917ec650989SNeel Natu 		printf("\tDevice Scope:");
918ec650989SNeel Natu 	while (remaining > 0) {
919ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
920ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
921ec650989SNeel Natu 		if (consumed <= 0)
922ec650989SNeel Natu 			break;
923ec650989SNeel Natu 		else
924ec650989SNeel Natu 			remaining -= consumed;
925ec650989SNeel Natu 	}
926ec650989SNeel Natu }
927ec650989SNeel Natu 
928ec650989SNeel Natu static void
929ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
930ec650989SNeel Natu {
931ec650989SNeel Natu 	char *cp;
932ec650989SNeel Natu 	int remaining, consumed;
933ec650989SNeel Natu 
934ec650989SNeel Natu 	printf("\n");
935ec650989SNeel Natu 	printf("\tType=RMRR\n");
936ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
937ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
9387d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
9397d369c6eSJung-uk Kim 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
940ec650989SNeel Natu 
941ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
942ec650989SNeel Natu 	if (remaining > 0)
943ec650989SNeel Natu 		printf("\tDevice Scope:");
944ec650989SNeel Natu 	while (remaining > 0) {
945ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
946ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
947ec650989SNeel Natu 		if (consumed <= 0)
948ec650989SNeel Natu 			break;
949ec650989SNeel Natu 		else
950ec650989SNeel Natu 			remaining -= consumed;
951ec650989SNeel Natu 	}
952ec650989SNeel Natu }
953ec650989SNeel Natu 
954ec650989SNeel Natu static void
955ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
956ec650989SNeel Natu {
957ec650989SNeel Natu 	char *cp;
958ec650989SNeel Natu 	int remaining, consumed;
959ec650989SNeel Natu 
960ec650989SNeel Natu 	printf("\n");
961ec650989SNeel Natu 	printf("\tType=ATSR\n");
962ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
963ec650989SNeel Natu 
964ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
965ec650989SNeel Natu 
966ec650989SNeel Natu 	printf("\tFlags=");
967ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
968ec650989SNeel Natu 	PRINTFLAG_END();
969ec650989SNeel Natu 
970ec650989SNeel Natu #undef PRINTFLAG
971ec650989SNeel Natu 
972ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
973ec650989SNeel Natu 
974ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
975ec650989SNeel Natu 	if (remaining > 0)
976ec650989SNeel Natu 		printf("\tDevice Scope:");
977ec650989SNeel Natu 	while (remaining > 0) {
978ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
979ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
980ec650989SNeel Natu 		if (consumed <= 0)
981ec650989SNeel Natu 			break;
982ec650989SNeel Natu 		else
983ec650989SNeel Natu 			remaining -= consumed;
984ec650989SNeel Natu 	}
985ec650989SNeel Natu }
986ec650989SNeel Natu 
987ec650989SNeel Natu static void
988ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
989ec650989SNeel Natu {
990ec650989SNeel Natu 
991ec650989SNeel Natu 	printf("\n");
992ec650989SNeel Natu 	printf("\tType=RHSA\n");
993ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
9947d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
995ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
996ec650989SNeel Natu }
997ec650989SNeel Natu 
998ec650989SNeel Natu static int
999ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
1000ec650989SNeel Natu {
1001ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
1002ec650989SNeel Natu 
1003ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
1004ec650989SNeel Natu 		return (-1);
1005ec650989SNeel Natu 
1006ec650989SNeel Natu 	if (remaining < hdr->Length)
1007ec650989SNeel Natu 		return (-1);
1008ec650989SNeel Natu 
1009ec650989SNeel Natu 	switch (hdr->Type) {
1010ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1011ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
1012ec650989SNeel Natu 		break;
1013ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1014ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
1015ec650989SNeel Natu 		break;
1016313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_ROOT_ATS:
1017ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
1018ec650989SNeel Natu 		break;
1019313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1020ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
1021ec650989SNeel Natu 		break;
1022ec650989SNeel Natu 	default:
1023ec650989SNeel Natu 		printf("\n");
1024ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
1025ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
1026ec650989SNeel Natu 		break;
1027ec650989SNeel Natu 	}
1028ec650989SNeel Natu 	return (hdr->Length);
1029ec650989SNeel Natu }
1030ec650989SNeel Natu 
1031ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1032ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
1033ec650989SNeel Natu #endif
1034ec650989SNeel Natu 
1035ec650989SNeel Natu static void
1036ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1037ec650989SNeel Natu {
1038ec650989SNeel Natu 	char *cp;
1039ec650989SNeel Natu 	int remaining, consumed;
1040ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
1041ec650989SNeel Natu 
1042ec650989SNeel Natu 	printf(BEGIN_COMMENT);
1043ec650989SNeel Natu 	acpi_print_sdt(sdp);
1044ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
1045ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
1046ec650989SNeel Natu 
1047ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1048ec650989SNeel Natu 
1049ec650989SNeel Natu 	printf("\tFlags=");
1050ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
1051ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1052ec650989SNeel Natu 	PRINTFLAG_END();
1053ec650989SNeel Natu 
1054ec650989SNeel Natu #undef PRINTFLAG
1055ec650989SNeel Natu 
1056ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1057ec650989SNeel Natu 	while (remaining > 0) {
1058ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
1059ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1060ec650989SNeel Natu 		if (consumed <= 0)
1061ec650989SNeel Natu 			break;
1062ec650989SNeel Natu 		else
1063ec650989SNeel Natu 			remaining -= consumed;
1064ec650989SNeel Natu 	}
1065ec650989SNeel Natu 
1066ec650989SNeel Natu 	printf(END_COMMENT);
1067ec650989SNeel Natu }
1068ec650989SNeel Natu 
1069a0333ad1SJohn Baldwin static void
1070986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1071a0333ad1SJohn Baldwin {
1072a0333ad1SJohn Baldwin 
1073a0333ad1SJohn Baldwin 	printf("\tFlags={");
1074986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1075a0333ad1SJohn Baldwin 		printf("ENABLED");
1076a0333ad1SJohn Baldwin 	else
1077a0333ad1SJohn Baldwin 		printf("DISABLED");
1078986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1079a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1080986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1081a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1082a0333ad1SJohn Baldwin 	printf("}\n");
1083986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1084986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1085986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1086a0333ad1SJohn Baldwin }
1087a0333ad1SJohn Baldwin 
1088*27941afaSEd Maste static const char *srat_types[] = {
1089*27941afaSEd Maste     [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
1090*27941afaSEd Maste     [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
1091*27941afaSEd Maste     [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
1092*27941afaSEd Maste     [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC"
1093*27941afaSEd Maste };
1094a0333ad1SJohn Baldwin 
1095a0333ad1SJohn Baldwin static void
1096986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1097a0333ad1SJohn Baldwin {
1098986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1099986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
11002b2b1f42SAndrew Turner 	ACPI_SRAT_GICC_AFFINITY *gic;
1101a0333ad1SJohn Baldwin 
1102c86932b6SMarcelo Araujo 	if (srat->Type < nitems(srat_types))
1103986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1104a0333ad1SJohn Baldwin 	else
1105986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1106986dffafSJohn Baldwin 	switch (srat->Type) {
1107a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1108986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1109986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1110986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1111986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1112986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1113986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1114a0333ad1SJohn Baldwin 		break;
1115a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1116986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1117a0333ad1SJohn Baldwin 		break;
1118a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1119986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1120986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1121986dffafSJohn Baldwin 		    x2apic->Flags);
1122a0333ad1SJohn Baldwin 		break;
11232b2b1f42SAndrew Turner 	case ACPI_SRAT_TYPE_GICC_AFFINITY:
11242b2b1f42SAndrew Turner 		gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
11252b2b1f42SAndrew Turner 		acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
11262b2b1f42SAndrew Turner 		    gic->Flags);
11272b2b1f42SAndrew Turner 		break;
1128a0333ad1SJohn Baldwin 	}
1129a0333ad1SJohn Baldwin }
1130a0333ad1SJohn Baldwin 
1131a0333ad1SJohn Baldwin static void
1132986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1133a0333ad1SJohn Baldwin {
1134986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1135a0333ad1SJohn Baldwin 
1136a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1137a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1138986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1139986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1140986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1141a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1142a0333ad1SJohn Baldwin }
1143a0333ad1SJohn Baldwin 
1144a0333ad1SJohn Baldwin static void
1145986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1146c62f1cccSMitsuru IWASAKI {
1147773b6454SNate Lawson 	printf("  ");
1148986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
1149c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1150986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1151e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1152986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1153e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1154986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1155986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1156e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1157986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
1158986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1159e1e9a4bfSMitsuru IWASAKI }
1160e1e9a4bfSMitsuru IWASAKI 
1161945137d9SNate Lawson static void
1162986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1163e1e9a4bfSMitsuru IWASAKI {
1164986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1165986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1166e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1167e1e9a4bfSMitsuru IWASAKI 
1168986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1169986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1170773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1171773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1172986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1173e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1174e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1175e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1176e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1177fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
11787d369c6eSJung-uk Kim 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1179fe1d0c2dSJung-uk Kim 		else
11807d369c6eSJung-uk Kim 			printf("0x%016jx",
11817d369c6eSJung-uk Kim 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1182e1e9a4bfSMitsuru IWASAKI 	}
1183e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1184c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1185e1e9a4bfSMitsuru IWASAKI }
1186e1e9a4bfSMitsuru IWASAKI 
11878e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
11888e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
11898e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
11908e6a8737SNate Lawson };
11918e6a8737SNate Lawson 
1192945137d9SNate Lawson static void
1193986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1194e1e9a4bfSMitsuru IWASAKI {
1195986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
11968e6a8737SNate Lawson 	const char *pm;
1197e1e9a4bfSMitsuru IWASAKI 
1198986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1199c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
12002177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1201986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1202986dffafSJohn Baldwin 	       fadt->Dsdt);
1203986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1204986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
12058e6a8737SNate Lawson 		pm = "Reserved";
12068e6a8737SNate Lawson 	else
1207986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1208986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1209986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1210986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1211986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1212986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1213986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1214986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1215e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1216986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1217986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1218986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1219e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1220986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1221986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1222e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1223986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1224986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1225986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1226e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1227986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1228986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1229986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1230e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1231986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1232986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1233c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1234986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1235986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1236986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
12378e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1238986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1239986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1240986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
12418e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1242986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1243986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1244986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1245986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1246986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
124751c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1248986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1249e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1250986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1251e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1252986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1253e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1254986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1255e1e9a4bfSMitsuru IWASAKI 
1256ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1257e1e9a4bfSMitsuru IWASAKI 
12588e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1259986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1260986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1261986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1262986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1263986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1264f6469ce1SAndrew Turner 	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1265ec650989SNeel Natu 	PRINTFLAG_END();
12668e6a8737SNate Lawson 
12678e6a8737SNate Lawson 	printf("\tFlags=");
1268986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1269986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1270986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1271986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1272986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1273986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1274986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1275986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1276986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1277986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1278986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1279986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1280986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1281986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1282986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1283986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1284986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1285986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1286986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1287986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1288f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, HW_REDUCED);
1289f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1290ec650989SNeel Natu 	PRINTFLAG_END();
1291e1e9a4bfSMitsuru IWASAKI 
1292e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1293e1e9a4bfSMitsuru IWASAKI 
1294986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
12958e6a8737SNate Lawson 		printf("\tRESET_REG=");
1296986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1297986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
12988e6a8737SNate Lawson 	}
1299c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
13007d369c6eSJung-uk Kim 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
13017d369c6eSJung-uk Kim 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1302c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1303986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1304986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1305c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1306986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1307c08c4e81SNate Lawson 		}
1308c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1309986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1310986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1311c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1312986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1313c08c4e81SNate Lawson 		}
1314986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1315773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1316986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1317c08c4e81SNate Lawson 		}
1318773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1319986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1320986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1321773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1322986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1323c08c4e81SNate Lawson 		}
1324986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1325773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1326986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1327c08c4e81SNate Lawson 		}
1328773b6454SNate Lawson 		printf("\n");
1329773b6454SNate Lawson 	}
13308e6a8737SNate Lawson 
13318e6a8737SNate Lawson 	printf(END_COMMENT);
13328e6a8737SNate Lawson }
13338e6a8737SNate Lawson 
13348e6a8737SNate Lawson static void
1335986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
13368e6a8737SNate Lawson {
13378e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1338986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1339986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1340986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
13418e6a8737SNate Lawson 
1342773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1343986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1344986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
13458e6a8737SNate Lawson 			printf("PENDING,");
1346986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
13478e6a8737SNate Lawson 			printf("OWNED");
13488e6a8737SNate Lawson 	}
1349773b6454SNate Lawson 	printf("\n");
13508e6a8737SNate Lawson 
1351773b6454SNate Lawson 	printf("\tFlags=");
1352986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
13538e6a8737SNate Lawson 		printf("S4BIOS");
1354773b6454SNate Lawson 	printf("\n");
13558e6a8737SNate Lawson 
13567d369c6eSJung-uk Kim 	if (facs->XFirmwareWakingVector != 0)
13577d369c6eSJung-uk Kim 		printf("\tX_Firm_Wake_Vec=%016jx\n",
13587d369c6eSJung-uk Kim 		    (uintmax_t)facs->XFirmwareWakingVector);
1359986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
13608e6a8737SNate Lawson 
1361c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1362e1e9a4bfSMitsuru IWASAKI }
1363e1e9a4bfSMitsuru IWASAKI 
1364945137d9SNate Lawson static void
1365986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1366e1e9a4bfSMitsuru IWASAKI {
1367773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1368773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1369773b6454SNate Lawson 	printf(END_COMMENT);
1370e1e9a4bfSMitsuru IWASAKI }
1371e1e9a4bfSMitsuru IWASAKI 
1372e1e9a4bfSMitsuru IWASAKI int
1373e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1374e1e9a4bfSMitsuru IWASAKI {
1375986dffafSJohn Baldwin 	uint8_t *bp;
1376986dffafSJohn Baldwin 	uint8_t sum;
1377e1e9a4bfSMitsuru IWASAKI 
1378e1e9a4bfSMitsuru IWASAKI 	bp = p;
1379e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1380e1e9a4bfSMitsuru IWASAKI 	while (length--)
1381e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1382e1e9a4bfSMitsuru IWASAKI 
1383e1e9a4bfSMitsuru IWASAKI 	return (sum);
1384e1e9a4bfSMitsuru IWASAKI }
1385e1e9a4bfSMitsuru IWASAKI 
1386986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1387e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1388e1e9a4bfSMitsuru IWASAKI {
1389986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1390e1e9a4bfSMitsuru IWASAKI 
1391986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1392986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1393e1e9a4bfSMitsuru IWASAKI 	return (sp);
1394e1e9a4bfSMitsuru IWASAKI }
1395e1e9a4bfSMitsuru IWASAKI 
1396945137d9SNate Lawson static void
1397986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1398e1e9a4bfSMitsuru IWASAKI {
1399c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1400a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1401986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1402986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1403986dffafSJohn Baldwin 	       rp->Revision);
1404986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1405986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1406986dffafSJohn Baldwin 		    rp->Checksum);
1407a74172abSNate Lawson 	} else {
14087d369c6eSJung-uk Kim 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
14097d369c6eSJung-uk Kim 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
1410986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1411a74172abSNate Lawson 	}
1412c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1413e1e9a4bfSMitsuru IWASAKI }
1414e1e9a4bfSMitsuru IWASAKI 
1415945137d9SNate Lawson static void
1416986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1417e1e9a4bfSMitsuru IWASAKI {
1418986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1419986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1420986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1421a74172abSNate Lawson 	vm_offset_t addr;
1422a74172abSNate Lawson 	int entries, i;
1423e1e9a4bfSMitsuru IWASAKI 
1424e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1425986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1426986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1427986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1428e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1429fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1430986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1431fe1d0c2dSJung-uk Kim 		else
1432986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1433fe1d0c2dSJung-uk Kim 		if (addr == 0)
1434fe1d0c2dSJung-uk Kim 			continue;
1435986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1436986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
14375cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1438986dffafSJohn Baldwin 			    sdp->Signature);
14395cf6d493SNate Lawson 			continue;
14405cf6d493SNate Lawson 		}
1441986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
14422177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1443986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1444986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1445986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
144679d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1447986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
144855d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1449986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1450a47e681bSScott Long 			acpi_handle_mcfg(sdp);
145133866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
145233866658SJohn Baldwin 			acpi_handle_slit(sdp);
1453986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1454a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1455c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1456c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1457ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1458ec650989SNeel Natu 			acpi_handle_dmar(sdp);
1459773b6454SNate Lawson 		else {
1460773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1461773b6454SNate Lawson 			acpi_print_sdt(sdp);
1462773b6454SNate Lawson 			printf(END_COMMENT);
1463773b6454SNate Lawson 		}
1464e1e9a4bfSMitsuru IWASAKI 	}
1465e1e9a4bfSMitsuru IWASAKI }
1466c62f1cccSMitsuru IWASAKI 
1467986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1468476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1469945137d9SNate Lawson {
1470986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1471986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1472945137d9SNate Lawson 
1473945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1474945137d9SNate Lawson 	if (!rp)
1475945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1476945137d9SNate Lawson 
1477945137d9SNate Lawson 	if (tflag)
1478945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1479986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1480986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1481986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1482986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1483945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1484a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1485a74172abSNate Lawson 	} else {
1486986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1487986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1488986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1489a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1490a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1491a74172abSNate Lawson 	}
1492945137d9SNate Lawson 	return (rsdp);
1493945137d9SNate Lawson }
1494c62f1cccSMitsuru IWASAKI 
149562c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1496bfa3f012SMarcel Moolenaar static int
1497986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1498bfa3f012SMarcel Moolenaar {
1499986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1500986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1501bfa3f012SMarcel Moolenaar 	uint8_t sum;
1502bfa3f012SMarcel Moolenaar 
150362c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1504bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1505bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1506986dffafSJohn Baldwin 		sdt.Checksum = 0;
1507986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1508986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1509986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1510f7675a56SNate Lawson 		while (ssdt != NULL) {
1511986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1512986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1513986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1514986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1515bfa3f012SMarcel Moolenaar 		}
1516986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1517986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1518bfa3f012SMarcel Moolenaar 	}
151962c7bde1SNate Lawson 
152062c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1521986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1522986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
152362c7bde1SNate Lawson 
1524b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1525f7675a56SNate Lawson 	if (rsdt != NULL) {
1526bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1527bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1528986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1529986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1530bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1531bfa3f012SMarcel Moolenaar 		}
1532bfa3f012SMarcel Moolenaar 	}
1533bfa3f012SMarcel Moolenaar 	return (0);
1534bfa3f012SMarcel Moolenaar }
1535bfa3f012SMarcel Moolenaar 
1536c62f1cccSMitsuru IWASAKI void
1537986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1538c62f1cccSMitsuru IWASAKI {
1539945137d9SNate Lawson 	int	fd;
1540945137d9SNate Lawson 	mode_t	mode;
1541945137d9SNate Lawson 
1542945137d9SNate Lawson 	assert(outfile != NULL);
1543945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1544945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1545945137d9SNate Lawson 	if (fd == -1) {
1546945137d9SNate Lawson 		perror("dsdt_save_file");
1547945137d9SNate Lawson 		return;
1548945137d9SNate Lawson 	}
1549bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1550945137d9SNate Lawson 	close(fd);
1551c62f1cccSMitsuru IWASAKI }
1552c62f1cccSMitsuru IWASAKI 
1553945137d9SNate Lawson void
1554986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1555c62f1cccSMitsuru IWASAKI {
15567e2cc014SDon Lewis 	char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
15577e2cc014SDon Lewis 	const char *iname = "/acpdump.din";
15587e2cc014SDon Lewis 	const char *oname = "/acpdump.dsl";
155999065116SJung-uk Kim 	const char *tmpdir;
1560945137d9SNate Lawson 	FILE *fp;
156199065116SJung-uk Kim 	size_t len;
15627e2cc014SDon Lewis 	int fd, status;
15637e2cc014SDon Lewis 	pid_t pid;
1564945137d9SNate Lawson 
156599065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
156699065116SJung-uk Kim 	if (tmpdir == NULL)
156799065116SJung-uk Kim 		tmpdir = _PATH_TMP;
15687e2cc014SDon Lewis 	if (realpath(tmpdir, buf) == NULL) {
1569d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
157099065116SJung-uk Kim 		return;
157199065116SJung-uk Kim 	}
15727e2cc014SDon Lewis 	len = sizeof(wrkdir) - strlen(iname);
15737e2cc014SDon Lewis 	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
15747e2cc014SDon Lewis 		fprintf(stderr, "$TMPDIR too long\n");
15757e2cc014SDon Lewis 		return;
15767e2cc014SDon Lewis 	}
15777e2cc014SDon Lewis 	if  (mkdtemp(wrkdir) == NULL) {
15787e2cc014SDon Lewis 		perror("mkdtemp tmp working dir");
15797e2cc014SDon Lewis 		return;
15807e2cc014SDon Lewis 	}
158130bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
158230bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
15837e2cc014SDon Lewis 	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1584945137d9SNate Lawson 	if (fd < 0) {
1585945137d9SNate Lawson 		perror("iasl tmp file");
1586945137d9SNate Lawson 		return;
1587c62f1cccSMitsuru IWASAKI 	}
1588bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1589945137d9SNate Lawson 	close(fd);
1590945137d9SNate Lawson 
1591945137d9SNate Lawson 	/* Run iasl -d on the temp file */
15927e2cc014SDon Lewis 	if ((pid = fork()) == 0) {
1593945137d9SNate Lawson 		close(STDOUT_FILENO);
1594945137d9SNate Lawson 		if (vflag == 0)
1595945137d9SNate Lawson 			close(STDERR_FILENO);
159699065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1597945137d9SNate Lawson 		err(1, "exec");
1598c62f1cccSMitsuru IWASAKI 	}
15997e2cc014SDon Lewis 	if (pid > 0)
16007e2cc014SDon Lewis 		wait(&status);
16017e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
16027e2cc014SDon Lewis 		perror("unlink");
16037e2cc014SDon Lewis 		goto out;
16047e2cc014SDon Lewis 	}
16057e2cc014SDon Lewis 	if (pid < 0) {
16067e2cc014SDon Lewis 		perror("fork");
16077e2cc014SDon Lewis 		goto out;
16087e2cc014SDon Lewis 	}
16097e2cc014SDon Lewis 	if (status != 0) {
16107e2cc014SDon Lewis 		fprintf(stderr, "iast exit status = %d\n", status);
16117e2cc014SDon Lewis 	}
1612945137d9SNate Lawson 
1613945137d9SNate Lawson 	/* Dump iasl's output to stdout */
161430bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
161530bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
161699065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
16177e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
16187e2cc014SDon Lewis 		perror("unlink");
16197e2cc014SDon Lewis 		goto out;
16207e2cc014SDon Lewis 	}
1621945137d9SNate Lawson 	if (fp == NULL) {
1622945137d9SNate Lawson 		perror("iasl tmp file (read)");
16237e2cc014SDon Lewis 		goto out;
1624945137d9SNate Lawson 	}
1625945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1626945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1627945137d9SNate Lawson 	fclose(fp);
16287e2cc014SDon Lewis 
16297e2cc014SDon Lewis     out:
16307e2cc014SDon Lewis 	if (rmdir(wrkdir) < 0)
16317e2cc014SDon Lewis 		perror("rmdir");
1632c62f1cccSMitsuru IWASAKI }
1633c62f1cccSMitsuru IWASAKI 
1634945137d9SNate Lawson void
1635986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1636c62f1cccSMitsuru IWASAKI {
1637945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1638c62f1cccSMitsuru IWASAKI }
1639c62f1cccSMitsuru IWASAKI 
1640bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1641986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1642986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1643c62f1cccSMitsuru IWASAKI {
1644986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1645986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1646986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1647a74172abSNate Lawson 	vm_offset_t addr;
1648a74172abSNate Lawson 	int entries, i;
1649945137d9SNate Lawson 
1650986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1651986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1652986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1653945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1654fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1655986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1656fe1d0c2dSJung-uk Kim 		else
1657986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1658fe1d0c2dSJung-uk Kim 		if (addr == 0)
1659fe1d0c2dSJung-uk Kim 			continue;
1660986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1661bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1662bfa3f012SMarcel Moolenaar 			if (sdt == last)
1663bfa3f012SMarcel Moolenaar 				last = NULL;
1664bfa3f012SMarcel Moolenaar 			continue;
1665bfa3f012SMarcel Moolenaar 		}
1666986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1667a74172abSNate Lawson 			continue;
1668986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1669945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1670945137d9SNate Lawson 		return (sdt);
1671c62f1cccSMitsuru IWASAKI 	}
1672c62f1cccSMitsuru IWASAKI 
1673945137d9SNate Lawson 	return (NULL);
1674c62f1cccSMitsuru IWASAKI }
1675c62f1cccSMitsuru IWASAKI 
1676986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1677986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1678c62f1cccSMitsuru IWASAKI {
1679986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1680c62f1cccSMitsuru IWASAKI 
1681986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1682c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1683986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
16842e71eb12SNate Lawson 	else
1685986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1686986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1687945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1688945137d9SNate Lawson 	return (sdt);
1689c62f1cccSMitsuru IWASAKI }
1690