xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision f5d0a8f7c7d2ececc8deb790f7a77082fc438b7b)
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");
273*f5d0a8f7SEd Maste 		if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
274*f5d0a8f7SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
275*f5d0a8f7SEd Maste 			return;
276*f5d0a8f7SEd 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 
395bf70beceSEd Schouten static const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override",
396bf70beceSEd Schouten 				    "NMI", "Local APIC NMI",
397bf70beceSEd Schouten 				    "Local APIC Override", "IO SAPIC",
398bf70beceSEd Schouten 				    "Local SAPIC", "Platform Interrupt",
3992b2b1f42SAndrew Turner 				    "Local X2APIC", "Local X2APIC NMI",
4002b2b1f42SAndrew Turner 				    "GIC CPU Interface Structure",
4012b2b1f42SAndrew Turner 				    "GIC Distributor Structure",
4022b2b1f42SAndrew Turner 				    "GICv2m MSI Frame",
4032b2b1f42SAndrew Turner 				    "GIC Redistributor Structure",
4042b2b1f42SAndrew Turner 				    "GIC ITS Structure" };
405bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
4060a473124SJohn Baldwin 					    "Corrected Platform Error" };
4070a473124SJohn Baldwin 
4080a473124SJohn Baldwin static void
409986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
4100a473124SJohn Baldwin {
411986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
412986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
413986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
414986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
415986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
416986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
417986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
418986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
419986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
420986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
421986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
4222b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_INTERRUPT *gicc;
4232b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
4242b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
4252b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_TRANSLATOR *gict;
4260a473124SJohn Baldwin 
427c86932b6SMarcelo Araujo 	if (mp->Type < nitems(apic_types))
428986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
429a0333ad1SJohn Baldwin 	else
430986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
431986dffafSJohn Baldwin 	switch (mp->Type) {
432986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
433986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
434986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
435986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4360a473124SJohn Baldwin 		break;
437986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
438986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
439986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
440986dffafSJohn Baldwin 		    ioapic->Address);
4410a473124SJohn Baldwin 		break;
442986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
443986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
444986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
445986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
446986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
4470a473124SJohn Baldwin 		break;
448986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
449986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
450986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
4510a473124SJohn Baldwin 		break;
452986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
453986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
454986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
455986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
4560a473124SJohn Baldwin 		break;
457986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
458986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
459945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
460986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
4610a473124SJohn Baldwin 		break;
462986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
463986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
464986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
465986dffafSJohn Baldwin 		    iosapic->Address);
4660a473124SJohn Baldwin 		break;
467986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
468986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
469986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
470986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
471986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
472986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
473986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
4740a473124SJohn Baldwin 		break;
475986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
476986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
477c86932b6SMarcelo Araujo 		if (isrc->Type < nitems(platform_int_types))
478986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
479986dffafSJohn Baldwin 		else
480986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
481986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
482986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
483986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
484986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
485986dffafSJohn Baldwin 		break;
486986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
487986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
488986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
489986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
490986dffafSJohn Baldwin 		break;
491986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
492986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
493986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
494986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
4950a473124SJohn Baldwin 		break;
4962b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
4972b2b1f42SAndrew Turner 		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
4982b2b1f42SAndrew Turner 		acpi_print_cpu_uid(gicc->Uid, NULL);
4992b2b1f42SAndrew Turner 		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
5002b2b1f42SAndrew Turner 		acpi_print_gicc_flags(gicc->Flags);
5012b2b1f42SAndrew Turner 		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
5022b2b1f42SAndrew Turner 		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
5032b2b1f42SAndrew Turner 		printf("\tParked ADDR=%016jx\n",
5042b2b1f42SAndrew Turner 		    (uintmax_t)gicc->ParkedAddress);
5052b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
5062b2b1f42SAndrew Turner 		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
5072b2b1f42SAndrew Turner 		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
5082b2b1f42SAndrew Turner 		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
5092b2b1f42SAndrew Turner 		printf("\tGICR ADDR=%016jx\n",
5102b2b1f42SAndrew Turner 		    (uintmax_t)gicc->GicrBaseAddress);
5112b2b1f42SAndrew Turner 		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
5122b2b1f42SAndrew Turner 		printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass);
5132b2b1f42SAndrew Turner 		break;
5142b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
5152b2b1f42SAndrew Turner 		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
5162b2b1f42SAndrew Turner 		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
5172b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
5182b2b1f42SAndrew Turner 		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
5192b2b1f42SAndrew Turner 		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
5202b2b1f42SAndrew Turner 		break;
5212b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
5222b2b1f42SAndrew Turner 		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
5232b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
5242b2b1f42SAndrew Turner 		printf("\tLength=%08x\n", gicr->Length);
5252b2b1f42SAndrew Turner 		break;
5262b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
5272b2b1f42SAndrew Turner 		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
5282b2b1f42SAndrew Turner 		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
5292b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
5302b2b1f42SAndrew Turner 		break;
5310a473124SJohn Baldwin 	}
5320a473124SJohn Baldwin }
5330a473124SJohn Baldwin 
5340a473124SJohn Baldwin static void
535986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
5360a473124SJohn Baldwin {
537986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
5380a473124SJohn Baldwin 
539773b6454SNate Lawson 	printf(BEGIN_COMMENT);
540773b6454SNate Lawson 	acpi_print_sdt(sdp);
541986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
542986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
5430a473124SJohn Baldwin 	printf("\tFlags={");
544986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
5450a473124SJohn Baldwin 		printf("PC-AT");
5460a473124SJohn Baldwin 	printf("}\n");
547986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
5480a473124SJohn Baldwin 	printf(END_COMMENT);
5490a473124SJohn Baldwin }
5500a473124SJohn Baldwin 
5510a473124SJohn Baldwin static void
552986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
55379d7565cSPeter Wemm {
554986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
55579d7565cSPeter Wemm 
556773b6454SNate Lawson 	printf(BEGIN_COMMENT);
557773b6454SNate Lawson 	acpi_print_sdt(sdp);
558986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
559986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
56087f9f09aSTakanori Watanabe 	printf("\tADDR=");
561986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
562986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
563986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
564986dffafSJohn Baldwin 	    8);
565986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
566986dffafSJohn Baldwin 	    1 : 0);
56779d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
568986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
56979d7565cSPeter Wemm 		printf("TRUE}\n");
57079d7565cSPeter Wemm 	else
57179d7565cSPeter Wemm 		printf("FALSE}\n");
572986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
573986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
5749785e979SNeel Natu 	printf("\tFlags=0x%02x\n", hpet->Flags);
57579d7565cSPeter Wemm 	printf(END_COMMENT);
57679d7565cSPeter Wemm }
57779d7565cSPeter Wemm 
57879d7565cSPeter Wemm static void
579986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
58055d7ff9eSNate Lawson {
581986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
58255d7ff9eSNate Lawson 
58355d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
58455d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
585986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
58655d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
587986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
58855d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
589986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
590986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
591986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
592986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
59355d7ff9eSNate Lawson 	printf(END_COMMENT);
59455d7ff9eSNate Lawson }
59555d7ff9eSNate Lawson 
59655d7ff9eSNate Lawson static void
597986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
598a47e681bSScott Long {
599986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
600986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
601986dffafSJohn Baldwin 	u_int i, entries;
602a47e681bSScott Long 
603a47e681bSScott Long 	printf(BEGIN_COMMENT);
604a47e681bSScott Long 	acpi_print_sdt(sdp);
605986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
606986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
607986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
608986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
609986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
610a47e681bSScott Long 		printf("\n");
6110c10b85aSJung-uk Kim 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
612986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
613986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
614986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
615a47e681bSScott Long 	}
616a47e681bSScott Long 	printf(END_COMMENT);
617a47e681bSScott Long }
618a47e681bSScott Long 
619a47e681bSScott Long static void
62033866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
62133866658SJohn Baldwin {
62233866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
62333866658SJohn Baldwin 	UINT64 i, j;
62433866658SJohn Baldwin 
62533866658SJohn Baldwin 	printf(BEGIN_COMMENT);
62633866658SJohn Baldwin 	acpi_print_sdt(sdp);
62733866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
6280c10b85aSJung-uk Kim 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
62933866658SJohn Baldwin 	printf("\n\t      ");
63033866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
6310c10b85aSJung-uk Kim 		printf(" %3ju", (uintmax_t)i);
63233866658SJohn Baldwin 	printf("\n\t     +");
63333866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
63433866658SJohn Baldwin 		printf("----");
63533866658SJohn Baldwin 	printf("\n");
63633866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
6370c10b85aSJung-uk Kim 		printf("\t %3ju |", (uintmax_t)i);
63833866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
63933866658SJohn Baldwin 			printf(" %3d",
64033866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
64133866658SJohn Baldwin 		printf("\n");
64233866658SJohn Baldwin 	}
64333866658SJohn Baldwin 	printf(END_COMMENT);
64433866658SJohn Baldwin }
64533866658SJohn Baldwin 
64633866658SJohn Baldwin static void
647a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
648a0333ad1SJohn Baldwin     uint32_t flags)
649a0333ad1SJohn Baldwin {
650a0333ad1SJohn Baldwin 
651a0333ad1SJohn Baldwin 	printf("\tFlags={");
652a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
653a0333ad1SJohn Baldwin 		printf("ENABLED");
654a0333ad1SJohn Baldwin 	else
655a0333ad1SJohn Baldwin 		printf("DISABLED");
656a0333ad1SJohn Baldwin 	printf("}\n");
657a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
658a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
659a0333ad1SJohn Baldwin }
660a0333ad1SJohn Baldwin 
661c031c93bSTakanori Watanabe static char *
662c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
663c031c93bSTakanori Watanabe {
664c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
665c031c93bSTakanori Watanabe 	char *eventname = NULL;
666c031c93bSTakanori Watanabe 
667c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
668c031c93bSTakanori Watanabe 
669c031c93bSTakanori Watanabe 	switch(event->event_type) {
670c031c93bSTakanori Watanabe 	case PREBOOT:
671c031c93bSTakanori Watanabe 	case POST_CODE:
672c031c93bSTakanori Watanabe 	case UNUSED:
673c031c93bSTakanori Watanabe 	case NO_ACTION:
674c031c93bSTakanori Watanabe 	case SEPARATOR:
675c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
676c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
677c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
678c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
679c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
680c031c93bSTakanori Watanabe 	case COMPACT_HASH:
681c031c93bSTakanori Watanabe 	case IPL:
682c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
683c031c93bSTakanori Watanabe 	case NONHOST_CODE:
684c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
685c031c93bSTakanori Watanabe 	case NONHOST_INFO:
686c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
687c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
688c031c93bSTakanori Watanabe 		break;
689c031c93bSTakanori Watanabe 
690c031c93bSTakanori Watanabe 	case ACTION:
691c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
692c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
693c031c93bSTakanori Watanabe 		break;
694c031c93bSTakanori Watanabe 
695c031c93bSTakanori Watanabe 	case EVENT_TAG:
696c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
697c031c93bSTakanori Watanabe 		case SMBIOS:
698c031c93bSTakanori Watanabe 		case BIS_CERT:
699c031c93bSTakanori Watanabe 		case CMOS:
700c031c93bSTakanori Watanabe 		case NVRAM:
701c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
702c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
703c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
704c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
705c031c93bSTakanori Watanabe 		case ESCD:
706c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
707c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
708c031c93bSTakanori Watanabe 		case POST_CONTENTS:
709c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
710c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
711c031c93bSTakanori Watanabe 			break;
712c031c93bSTakanori Watanabe 
713c031c93bSTakanori Watanabe 		default:
714c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
715c031c93bSTakanori Watanabe 			    pc_event->event_id);
716c031c93bSTakanori Watanabe 			break;
717c031c93bSTakanori Watanabe 		}
718c031c93bSTakanori Watanabe 		break;
719c031c93bSTakanori Watanabe 
720c031c93bSTakanori Watanabe 	default:
721c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
722c031c93bSTakanori Watanabe 		break;
723c031c93bSTakanori Watanabe 	}
724c031c93bSTakanori Watanabe 
725c031c93bSTakanori Watanabe 	return eventname;
726c031c93bSTakanori Watanabe }
727c031c93bSTakanori Watanabe 
728c031c93bSTakanori Watanabe static void
729c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
730c031c93bSTakanori Watanabe {
731c031c93bSTakanori Watanabe 	int i;
732c031c93bSTakanori Watanabe 	char *eventname;
733c031c93bSTakanori Watanabe 
734c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
735c031c93bSTakanori Watanabe 
736c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
737c031c93bSTakanori Watanabe 	printf(" 0x");
738c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
739c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
740c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
741c031c93bSTakanori Watanabe 
742c031c93bSTakanori Watanabe 	free(eventname);
743c031c93bSTakanori Watanabe }
744c031c93bSTakanori Watanabe 
745c031c93bSTakanori Watanabe static void
746c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
747c031c93bSTakanori Watanabe {
748c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
749c031c93bSTakanori Watanabe 	struct TCPAevent *event;
750977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
751c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
752c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
753c031c93bSTakanori Watanabe 
754c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
755c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
756c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
757c031c93bSTakanori Watanabe 
758c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
759c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
760c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
761c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
762c031c93bSTakanori Watanabe 		break;
763c031c93bSTakanori Watanabe 
764c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
765c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
766c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
767c031c93bSTakanori Watanabe 		break;
768c031c93bSTakanori Watanabe 
769c031c93bSTakanori Watanabe 	default:
770c031c93bSTakanori Watanabe 		printf("XXX");
771c031c93bSTakanori Watanabe 		printf(END_COMMENT);
772c031c93bSTakanori Watanabe 		return;
773c031c93bSTakanori Watanabe 	}
7740e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
775c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
776c031c93bSTakanori Watanabe 
777c031c93bSTakanori Watanabe 	if (len == 0) {
778c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
779c031c93bSTakanori Watanabe 		printf(END_COMMENT);
780c031c93bSTakanori Watanabe 		return;
781c031c93bSTakanori Watanabe 	}
7822ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
7832ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
7842ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
7852ef23c6dSTakanori Watanabe 		return;
7862ef23c6dSTakanori Watanabe 	}
787c031c93bSTakanori Watanabe 
788c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
789c031c93bSTakanori Watanabe 	vend = vaddr + len;
790c031c93bSTakanori Watanabe 
791c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
7922ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
7932ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
794c031c93bSTakanori Watanabe 			break;
7950e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
796c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
797c031c93bSTakanori Watanabe 			break;
7982ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
7992ef23c6dSTakanori Watanabe 			break;
800c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
801c031c93bSTakanori Watanabe 			break;
802c031c93bSTakanori Watanabe #if 0
803c031c93bSTakanori Watanabe 		{
804c031c93bSTakanori Watanabe 		unsigned int i, j, k;
805c031c93bSTakanori Watanabe 
806c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
807c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
808c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
809c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
810c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
811c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
812c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
813c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
814c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
815c031c93bSTakanori Watanabe 				j = i + 1;
816c031c93bSTakanori Watanabe 			}
817c031c93bSTakanori Watanabe 		}
818c031c93bSTakanori Watanabe 		printf("\n"); }
819c031c93bSTakanori Watanabe #endif
820c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
821c031c93bSTakanori Watanabe 
822c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
823c031c93bSTakanori Watanabe 	}
824c031c93bSTakanori Watanabe 
825c031c93bSTakanori Watanabe 	printf(END_COMMENT);
826c031c93bSTakanori Watanabe }
827c031c93bSTakanori Watanabe 
828ec650989SNeel Natu static const char *
829ec650989SNeel Natu devscope_type2str(int type)
830ec650989SNeel Natu {
831ec650989SNeel Natu 	static char typebuf[16];
832ec650989SNeel Natu 
833ec650989SNeel Natu 	switch (type) {
834ec650989SNeel Natu 	case 1:
835ec650989SNeel Natu 		return ("PCI Endpoint Device");
836ec650989SNeel Natu 	case 2:
837ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
838ec650989SNeel Natu 	case 3:
839ec650989SNeel Natu 		return ("IOAPIC");
840ec650989SNeel Natu 	case 4:
841ec650989SNeel Natu 		return ("HPET");
842ec650989SNeel Natu 	default:
843ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
844ec650989SNeel Natu 		return (typebuf);
845ec650989SNeel Natu 	}
846ec650989SNeel Natu }
847ec650989SNeel Natu 
848ec650989SNeel Natu static int
849ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
850ec650989SNeel Natu {
851ec650989SNeel Natu 	char sep;
852ec650989SNeel Natu 	int pathlen;
853ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
854ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
855ec650989SNeel Natu 
856ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
857ec650989SNeel Natu 		return (-1);
858ec650989SNeel Natu 
859ec650989SNeel Natu 	if (remaining < devscope->Length)
860ec650989SNeel Natu 		return (-1);
861ec650989SNeel Natu 
862ec650989SNeel Natu 	printf("\n");
863ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
864ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
865ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
866ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
867ec650989SNeel Natu 
868ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
869ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
870ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
871ec650989SNeel Natu 	if (path < pathend) {
872ec650989SNeel Natu 		sep = '{';
873ec650989SNeel Natu 		printf("\t\tPath=");
874ec650989SNeel Natu 		do {
875ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
876ec650989SNeel Natu 			sep=',';
877ec650989SNeel Natu 			path++;
878ec650989SNeel Natu 		} while (path < pathend);
879ec650989SNeel Natu 		printf("}\n");
880ec650989SNeel Natu 	}
881ec650989SNeel Natu 
882ec650989SNeel Natu 	return (devscope->Length);
883ec650989SNeel Natu }
884ec650989SNeel Natu 
885ec650989SNeel Natu static void
886ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
887ec650989SNeel Natu {
888ec650989SNeel Natu 	char *cp;
889ec650989SNeel Natu 	int remaining, consumed;
890ec650989SNeel Natu 
891ec650989SNeel Natu 	printf("\n");
892ec650989SNeel Natu 	printf("\tType=DRHD\n");
893ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
894ec650989SNeel Natu 
895ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
896ec650989SNeel Natu 
897ec650989SNeel Natu 	printf("\tFlags=");
898ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
899ec650989SNeel Natu 	PRINTFLAG_END();
900ec650989SNeel Natu 
901ec650989SNeel Natu #undef PRINTFLAG
902ec650989SNeel Natu 
903ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
9047d369c6eSJung-uk Kim 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
905ec650989SNeel Natu 
906ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
907ec650989SNeel Natu 	if (remaining > 0)
908ec650989SNeel Natu 		printf("\tDevice Scope:");
909ec650989SNeel Natu 	while (remaining > 0) {
910ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
911ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
912ec650989SNeel Natu 		if (consumed <= 0)
913ec650989SNeel Natu 			break;
914ec650989SNeel Natu 		else
915ec650989SNeel Natu 			remaining -= consumed;
916ec650989SNeel Natu 	}
917ec650989SNeel Natu }
918ec650989SNeel Natu 
919ec650989SNeel Natu static void
920ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
921ec650989SNeel Natu {
922ec650989SNeel Natu 	char *cp;
923ec650989SNeel Natu 	int remaining, consumed;
924ec650989SNeel Natu 
925ec650989SNeel Natu 	printf("\n");
926ec650989SNeel Natu 	printf("\tType=RMRR\n");
927ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
928ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
9297d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
9307d369c6eSJung-uk Kim 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
931ec650989SNeel Natu 
932ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
933ec650989SNeel Natu 	if (remaining > 0)
934ec650989SNeel Natu 		printf("\tDevice Scope:");
935ec650989SNeel Natu 	while (remaining > 0) {
936ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
937ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
938ec650989SNeel Natu 		if (consumed <= 0)
939ec650989SNeel Natu 			break;
940ec650989SNeel Natu 		else
941ec650989SNeel Natu 			remaining -= consumed;
942ec650989SNeel Natu 	}
943ec650989SNeel Natu }
944ec650989SNeel Natu 
945ec650989SNeel Natu static void
946ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
947ec650989SNeel Natu {
948ec650989SNeel Natu 	char *cp;
949ec650989SNeel Natu 	int remaining, consumed;
950ec650989SNeel Natu 
951ec650989SNeel Natu 	printf("\n");
952ec650989SNeel Natu 	printf("\tType=ATSR\n");
953ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
954ec650989SNeel Natu 
955ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
956ec650989SNeel Natu 
957ec650989SNeel Natu 	printf("\tFlags=");
958ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
959ec650989SNeel Natu 	PRINTFLAG_END();
960ec650989SNeel Natu 
961ec650989SNeel Natu #undef PRINTFLAG
962ec650989SNeel Natu 
963ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
964ec650989SNeel Natu 
965ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
966ec650989SNeel Natu 	if (remaining > 0)
967ec650989SNeel Natu 		printf("\tDevice Scope:");
968ec650989SNeel Natu 	while (remaining > 0) {
969ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
970ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
971ec650989SNeel Natu 		if (consumed <= 0)
972ec650989SNeel Natu 			break;
973ec650989SNeel Natu 		else
974ec650989SNeel Natu 			remaining -= consumed;
975ec650989SNeel Natu 	}
976ec650989SNeel Natu }
977ec650989SNeel Natu 
978ec650989SNeel Natu static void
979ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
980ec650989SNeel Natu {
981ec650989SNeel Natu 
982ec650989SNeel Natu 	printf("\n");
983ec650989SNeel Natu 	printf("\tType=RHSA\n");
984ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
9857d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
986ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
987ec650989SNeel Natu }
988ec650989SNeel Natu 
989ec650989SNeel Natu static int
990ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
991ec650989SNeel Natu {
992ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
993ec650989SNeel Natu 
994ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
995ec650989SNeel Natu 		return (-1);
996ec650989SNeel Natu 
997ec650989SNeel Natu 	if (remaining < hdr->Length)
998ec650989SNeel Natu 		return (-1);
999ec650989SNeel Natu 
1000ec650989SNeel Natu 	switch (hdr->Type) {
1001ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1002ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
1003ec650989SNeel Natu 		break;
1004ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1005ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
1006ec650989SNeel Natu 		break;
1007313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_ROOT_ATS:
1008ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
1009ec650989SNeel Natu 		break;
1010313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1011ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
1012ec650989SNeel Natu 		break;
1013ec650989SNeel Natu 	default:
1014ec650989SNeel Natu 		printf("\n");
1015ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
1016ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
1017ec650989SNeel Natu 		break;
1018ec650989SNeel Natu 	}
1019ec650989SNeel Natu 	return (hdr->Length);
1020ec650989SNeel Natu }
1021ec650989SNeel Natu 
1022ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1023ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
1024ec650989SNeel Natu #endif
1025ec650989SNeel Natu 
1026ec650989SNeel Natu static void
1027ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1028ec650989SNeel Natu {
1029ec650989SNeel Natu 	char *cp;
1030ec650989SNeel Natu 	int remaining, consumed;
1031ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
1032ec650989SNeel Natu 
1033ec650989SNeel Natu 	printf(BEGIN_COMMENT);
1034ec650989SNeel Natu 	acpi_print_sdt(sdp);
1035ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
1036ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
1037ec650989SNeel Natu 
1038ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1039ec650989SNeel Natu 
1040ec650989SNeel Natu 	printf("\tFlags=");
1041ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
1042ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1043ec650989SNeel Natu 	PRINTFLAG_END();
1044ec650989SNeel Natu 
1045ec650989SNeel Natu #undef PRINTFLAG
1046ec650989SNeel Natu 
1047ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1048ec650989SNeel Natu 	while (remaining > 0) {
1049ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
1050ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1051ec650989SNeel Natu 		if (consumed <= 0)
1052ec650989SNeel Natu 			break;
1053ec650989SNeel Natu 		else
1054ec650989SNeel Natu 			remaining -= consumed;
1055ec650989SNeel Natu 	}
1056ec650989SNeel Natu 
1057ec650989SNeel Natu 	printf(END_COMMENT);
1058ec650989SNeel Natu }
1059ec650989SNeel Natu 
1060a0333ad1SJohn Baldwin static void
1061986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1062a0333ad1SJohn Baldwin {
1063a0333ad1SJohn Baldwin 
1064a0333ad1SJohn Baldwin 	printf("\tFlags={");
1065986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1066a0333ad1SJohn Baldwin 		printf("ENABLED");
1067a0333ad1SJohn Baldwin 	else
1068a0333ad1SJohn Baldwin 		printf("DISABLED");
1069986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1070a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1071986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1072a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1073a0333ad1SJohn Baldwin 	printf("}\n");
1074986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1075986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1076986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1077a0333ad1SJohn Baldwin }
1078a0333ad1SJohn Baldwin 
10792b2b1f42SAndrew Turner static const char *srat_types[] = { "CPU", "Memory", "X2APIC", "GICC" };
1080a0333ad1SJohn Baldwin 
1081a0333ad1SJohn Baldwin static void
1082986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1083a0333ad1SJohn Baldwin {
1084986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1085986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
10862b2b1f42SAndrew Turner 	ACPI_SRAT_GICC_AFFINITY *gic;
1087a0333ad1SJohn Baldwin 
1088c86932b6SMarcelo Araujo 	if (srat->Type < nitems(srat_types))
1089986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1090a0333ad1SJohn Baldwin 	else
1091986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1092986dffafSJohn Baldwin 	switch (srat->Type) {
1093a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1094986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1095986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1096986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1097986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1098986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1099986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1100a0333ad1SJohn Baldwin 		break;
1101a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1102986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1103a0333ad1SJohn Baldwin 		break;
1104a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1105986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1106986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1107986dffafSJohn Baldwin 		    x2apic->Flags);
1108a0333ad1SJohn Baldwin 		break;
11092b2b1f42SAndrew Turner 	case ACPI_SRAT_TYPE_GICC_AFFINITY:
11102b2b1f42SAndrew Turner 		gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
11112b2b1f42SAndrew Turner 		acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
11122b2b1f42SAndrew Turner 		    gic->Flags);
11132b2b1f42SAndrew Turner 		break;
1114a0333ad1SJohn Baldwin 	}
1115a0333ad1SJohn Baldwin }
1116a0333ad1SJohn Baldwin 
1117a0333ad1SJohn Baldwin static void
1118986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1119a0333ad1SJohn Baldwin {
1120986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1121a0333ad1SJohn Baldwin 
1122a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1123a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1124986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1125986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1126986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1127a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1128a0333ad1SJohn Baldwin }
1129a0333ad1SJohn Baldwin 
1130a0333ad1SJohn Baldwin static void
1131986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1132c62f1cccSMitsuru IWASAKI {
1133773b6454SNate Lawson 	printf("  ");
1134986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
1135c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1136986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1137e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1138986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1139e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1140986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1141986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1142e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1143986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
1144986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1145e1e9a4bfSMitsuru IWASAKI }
1146e1e9a4bfSMitsuru IWASAKI 
1147945137d9SNate Lawson static void
1148986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1149e1e9a4bfSMitsuru IWASAKI {
1150986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1151986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1152e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1153e1e9a4bfSMitsuru IWASAKI 
1154986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1155986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1156773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1157773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1158986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1159e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1160e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1161e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1162e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1163fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
11647d369c6eSJung-uk Kim 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1165fe1d0c2dSJung-uk Kim 		else
11667d369c6eSJung-uk Kim 			printf("0x%016jx",
11677d369c6eSJung-uk Kim 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1168e1e9a4bfSMitsuru IWASAKI 	}
1169e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1170c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1171e1e9a4bfSMitsuru IWASAKI }
1172e1e9a4bfSMitsuru IWASAKI 
11738e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
11748e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
11758e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
11768e6a8737SNate Lawson };
11778e6a8737SNate Lawson 
1178945137d9SNate Lawson static void
1179986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1180e1e9a4bfSMitsuru IWASAKI {
1181986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
11828e6a8737SNate Lawson 	const char *pm;
1183e1e9a4bfSMitsuru IWASAKI 
1184986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1185c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
11862177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1187986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1188986dffafSJohn Baldwin 	       fadt->Dsdt);
1189986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1190986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
11918e6a8737SNate Lawson 		pm = "Reserved";
11928e6a8737SNate Lawson 	else
1193986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1194986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1195986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1196986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1197986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1198986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1199986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1200986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1201e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1202986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1203986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1204986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1205e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1206986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1207986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1208e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1209986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1210986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1211986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1212e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1213986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1214986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1215986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1216e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1217986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1218986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1219c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1220986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1221986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1222986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
12238e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1224986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1225986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1226986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
12278e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1228986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1229986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1230986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1231986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1232986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
123351c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1234986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1235e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1236986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1237e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1238986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1239e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1240986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1241e1e9a4bfSMitsuru IWASAKI 
1242ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1243e1e9a4bfSMitsuru IWASAKI 
12448e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1245986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1246986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1247986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1248986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1249986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1250f6469ce1SAndrew Turner 	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1251ec650989SNeel Natu 	PRINTFLAG_END();
12528e6a8737SNate Lawson 
12538e6a8737SNate Lawson 	printf("\tFlags=");
1254986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1255986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1256986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1257986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1258986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1259986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1260986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1261986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1262986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1263986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1264986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1265986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1266986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1267986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1268986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1269986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1270986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1271986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1272986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1273986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1274f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, HW_REDUCED);
1275f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1276ec650989SNeel Natu 	PRINTFLAG_END();
1277e1e9a4bfSMitsuru IWASAKI 
1278e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1279e1e9a4bfSMitsuru IWASAKI 
1280986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
12818e6a8737SNate Lawson 		printf("\tRESET_REG=");
1282986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1283986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
12848e6a8737SNate Lawson 	}
1285c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
12867d369c6eSJung-uk Kim 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
12877d369c6eSJung-uk Kim 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1288c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1289986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1290986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1291c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1292986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1293c08c4e81SNate Lawson 		}
1294c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1295986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1296986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1297c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1298986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1299c08c4e81SNate Lawson 		}
1300986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1301773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1302986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1303c08c4e81SNate Lawson 		}
1304773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1305986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1306986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1307773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1308986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1309c08c4e81SNate Lawson 		}
1310986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1311773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1312986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1313c08c4e81SNate Lawson 		}
1314773b6454SNate Lawson 		printf("\n");
1315773b6454SNate Lawson 	}
13168e6a8737SNate Lawson 
13178e6a8737SNate Lawson 	printf(END_COMMENT);
13188e6a8737SNate Lawson }
13198e6a8737SNate Lawson 
13208e6a8737SNate Lawson static void
1321986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
13228e6a8737SNate Lawson {
13238e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1324986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1325986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1326986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
13278e6a8737SNate Lawson 
1328773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1329986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1330986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
13318e6a8737SNate Lawson 			printf("PENDING,");
1332986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
13338e6a8737SNate Lawson 			printf("OWNED");
13348e6a8737SNate Lawson 	}
1335773b6454SNate Lawson 	printf("\n");
13368e6a8737SNate Lawson 
1337773b6454SNate Lawson 	printf("\tFlags=");
1338986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
13398e6a8737SNate Lawson 		printf("S4BIOS");
1340773b6454SNate Lawson 	printf("\n");
13418e6a8737SNate Lawson 
13427d369c6eSJung-uk Kim 	if (facs->XFirmwareWakingVector != 0)
13437d369c6eSJung-uk Kim 		printf("\tX_Firm_Wake_Vec=%016jx\n",
13447d369c6eSJung-uk Kim 		    (uintmax_t)facs->XFirmwareWakingVector);
1345986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
13468e6a8737SNate Lawson 
1347c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1348e1e9a4bfSMitsuru IWASAKI }
1349e1e9a4bfSMitsuru IWASAKI 
1350945137d9SNate Lawson static void
1351986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1352e1e9a4bfSMitsuru IWASAKI {
1353773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1354773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1355773b6454SNate Lawson 	printf(END_COMMENT);
1356e1e9a4bfSMitsuru IWASAKI }
1357e1e9a4bfSMitsuru IWASAKI 
1358e1e9a4bfSMitsuru IWASAKI int
1359e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1360e1e9a4bfSMitsuru IWASAKI {
1361986dffafSJohn Baldwin 	uint8_t *bp;
1362986dffafSJohn Baldwin 	uint8_t sum;
1363e1e9a4bfSMitsuru IWASAKI 
1364e1e9a4bfSMitsuru IWASAKI 	bp = p;
1365e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1366e1e9a4bfSMitsuru IWASAKI 	while (length--)
1367e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1368e1e9a4bfSMitsuru IWASAKI 
1369e1e9a4bfSMitsuru IWASAKI 	return (sum);
1370e1e9a4bfSMitsuru IWASAKI }
1371e1e9a4bfSMitsuru IWASAKI 
1372986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1373e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1374e1e9a4bfSMitsuru IWASAKI {
1375986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1376e1e9a4bfSMitsuru IWASAKI 
1377986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1378986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1379e1e9a4bfSMitsuru IWASAKI 	return (sp);
1380e1e9a4bfSMitsuru IWASAKI }
1381e1e9a4bfSMitsuru IWASAKI 
1382945137d9SNate Lawson static void
1383986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1384e1e9a4bfSMitsuru IWASAKI {
1385c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1386a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1387986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1388986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1389986dffafSJohn Baldwin 	       rp->Revision);
1390986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1391986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1392986dffafSJohn Baldwin 		    rp->Checksum);
1393a74172abSNate Lawson 	} else {
13947d369c6eSJung-uk Kim 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
13957d369c6eSJung-uk Kim 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
1396986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1397a74172abSNate Lawson 	}
1398c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1399e1e9a4bfSMitsuru IWASAKI }
1400e1e9a4bfSMitsuru IWASAKI 
1401945137d9SNate Lawson static void
1402986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1403e1e9a4bfSMitsuru IWASAKI {
1404986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1405986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1406986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1407a74172abSNate Lawson 	vm_offset_t addr;
1408a74172abSNate Lawson 	int entries, i;
1409e1e9a4bfSMitsuru IWASAKI 
1410e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1411986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1412986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1413986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1414e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1415fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1416986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1417fe1d0c2dSJung-uk Kim 		else
1418986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1419fe1d0c2dSJung-uk Kim 		if (addr == 0)
1420fe1d0c2dSJung-uk Kim 			continue;
1421986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1422986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
14235cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1424986dffafSJohn Baldwin 			    sdp->Signature);
14255cf6d493SNate Lawson 			continue;
14265cf6d493SNate Lawson 		}
1427986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
14282177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1429986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1430986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1431986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
143279d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1433986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
143455d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1435986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1436a47e681bSScott Long 			acpi_handle_mcfg(sdp);
143733866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
143833866658SJohn Baldwin 			acpi_handle_slit(sdp);
1439986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1440a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1441c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1442c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1443ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1444ec650989SNeel Natu 			acpi_handle_dmar(sdp);
1445773b6454SNate Lawson 		else {
1446773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1447773b6454SNate Lawson 			acpi_print_sdt(sdp);
1448773b6454SNate Lawson 			printf(END_COMMENT);
1449773b6454SNate Lawson 		}
1450e1e9a4bfSMitsuru IWASAKI 	}
1451e1e9a4bfSMitsuru IWASAKI }
1452c62f1cccSMitsuru IWASAKI 
1453986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1454476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1455945137d9SNate Lawson {
1456986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1457986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1458945137d9SNate Lawson 
1459945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1460945137d9SNate Lawson 	if (!rp)
1461945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1462945137d9SNate Lawson 
1463945137d9SNate Lawson 	if (tflag)
1464945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1465986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1466986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1467986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1468986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1469945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1470a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1471a74172abSNate Lawson 	} else {
1472986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1473986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1474986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1475a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1476a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1477a74172abSNate Lawson 	}
1478945137d9SNate Lawson 	return (rsdp);
1479945137d9SNate Lawson }
1480c62f1cccSMitsuru IWASAKI 
148162c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1482bfa3f012SMarcel Moolenaar static int
1483986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1484bfa3f012SMarcel Moolenaar {
1485986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1486986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1487bfa3f012SMarcel Moolenaar 	uint8_t sum;
1488bfa3f012SMarcel Moolenaar 
148962c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1490bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1491bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1492986dffafSJohn Baldwin 		sdt.Checksum = 0;
1493986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1494986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1495986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1496f7675a56SNate Lawson 		while (ssdt != NULL) {
1497986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1498986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1499986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1500986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1501bfa3f012SMarcel Moolenaar 		}
1502986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1503986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1504bfa3f012SMarcel Moolenaar 	}
150562c7bde1SNate Lawson 
150662c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1507986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1508986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
150962c7bde1SNate Lawson 
1510b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1511f7675a56SNate Lawson 	if (rsdt != NULL) {
1512bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1513bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1514986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1515986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1516bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1517bfa3f012SMarcel Moolenaar 		}
1518bfa3f012SMarcel Moolenaar 	}
1519bfa3f012SMarcel Moolenaar 	return (0);
1520bfa3f012SMarcel Moolenaar }
1521bfa3f012SMarcel Moolenaar 
1522c62f1cccSMitsuru IWASAKI void
1523986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1524c62f1cccSMitsuru IWASAKI {
1525945137d9SNate Lawson 	int	fd;
1526945137d9SNate Lawson 	mode_t	mode;
1527945137d9SNate Lawson 
1528945137d9SNate Lawson 	assert(outfile != NULL);
1529945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1530945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1531945137d9SNate Lawson 	if (fd == -1) {
1532945137d9SNate Lawson 		perror("dsdt_save_file");
1533945137d9SNate Lawson 		return;
1534945137d9SNate Lawson 	}
1535bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1536945137d9SNate Lawson 	close(fd);
1537c62f1cccSMitsuru IWASAKI }
1538c62f1cccSMitsuru IWASAKI 
1539945137d9SNate Lawson void
1540986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1541c62f1cccSMitsuru IWASAKI {
15427e2cc014SDon Lewis 	char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
15437e2cc014SDon Lewis 	const char *iname = "/acpdump.din";
15447e2cc014SDon Lewis 	const char *oname = "/acpdump.dsl";
154599065116SJung-uk Kim 	const char *tmpdir;
1546945137d9SNate Lawson 	FILE *fp;
154799065116SJung-uk Kim 	size_t len;
15487e2cc014SDon Lewis 	int fd, status;
15497e2cc014SDon Lewis 	pid_t pid;
1550945137d9SNate Lawson 
155199065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
155299065116SJung-uk Kim 	if (tmpdir == NULL)
155399065116SJung-uk Kim 		tmpdir = _PATH_TMP;
15547e2cc014SDon Lewis 	if (realpath(tmpdir, buf) == NULL) {
1555d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
155699065116SJung-uk Kim 		return;
155799065116SJung-uk Kim 	}
15587e2cc014SDon Lewis 	len = sizeof(wrkdir) - strlen(iname);
15597e2cc014SDon Lewis 	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
15607e2cc014SDon Lewis 		fprintf(stderr, "$TMPDIR too long\n");
15617e2cc014SDon Lewis 		return;
15627e2cc014SDon Lewis 	}
15637e2cc014SDon Lewis 	if  (mkdtemp(wrkdir) == NULL) {
15647e2cc014SDon Lewis 		perror("mkdtemp tmp working dir");
15657e2cc014SDon Lewis 		return;
15667e2cc014SDon Lewis 	}
156730bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
156830bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
15697e2cc014SDon Lewis 	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1570945137d9SNate Lawson 	if (fd < 0) {
1571945137d9SNate Lawson 		perror("iasl tmp file");
1572945137d9SNate Lawson 		return;
1573c62f1cccSMitsuru IWASAKI 	}
1574bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1575945137d9SNate Lawson 	close(fd);
1576945137d9SNate Lawson 
1577945137d9SNate Lawson 	/* Run iasl -d on the temp file */
15787e2cc014SDon Lewis 	if ((pid = fork()) == 0) {
1579945137d9SNate Lawson 		close(STDOUT_FILENO);
1580945137d9SNate Lawson 		if (vflag == 0)
1581945137d9SNate Lawson 			close(STDERR_FILENO);
158299065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1583945137d9SNate Lawson 		err(1, "exec");
1584c62f1cccSMitsuru IWASAKI 	}
15857e2cc014SDon Lewis 	if (pid > 0)
15867e2cc014SDon Lewis 		wait(&status);
15877e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
15887e2cc014SDon Lewis 		perror("unlink");
15897e2cc014SDon Lewis 		goto out;
15907e2cc014SDon Lewis 	}
15917e2cc014SDon Lewis 	if (pid < 0) {
15927e2cc014SDon Lewis 		perror("fork");
15937e2cc014SDon Lewis 		goto out;
15947e2cc014SDon Lewis 	}
15957e2cc014SDon Lewis 	if (status != 0) {
15967e2cc014SDon Lewis 		fprintf(stderr, "iast exit status = %d\n", status);
15977e2cc014SDon Lewis 	}
1598945137d9SNate Lawson 
1599945137d9SNate Lawson 	/* Dump iasl's output to stdout */
160030bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
160130bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
160299065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
16037e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
16047e2cc014SDon Lewis 		perror("unlink");
16057e2cc014SDon Lewis 		goto out;
16067e2cc014SDon Lewis 	}
1607945137d9SNate Lawson 	if (fp == NULL) {
1608945137d9SNate Lawson 		perror("iasl tmp file (read)");
16097e2cc014SDon Lewis 		goto out;
1610945137d9SNate Lawson 	}
1611945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1612945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1613945137d9SNate Lawson 	fclose(fp);
16147e2cc014SDon Lewis 
16157e2cc014SDon Lewis     out:
16167e2cc014SDon Lewis 	if (rmdir(wrkdir) < 0)
16177e2cc014SDon Lewis 		perror("rmdir");
1618c62f1cccSMitsuru IWASAKI }
1619c62f1cccSMitsuru IWASAKI 
1620945137d9SNate Lawson void
1621986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1622c62f1cccSMitsuru IWASAKI {
1623945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1624c62f1cccSMitsuru IWASAKI }
1625c62f1cccSMitsuru IWASAKI 
1626bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1627986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1628986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1629c62f1cccSMitsuru IWASAKI {
1630986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1631986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1632986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1633a74172abSNate Lawson 	vm_offset_t addr;
1634a74172abSNate Lawson 	int entries, i;
1635945137d9SNate Lawson 
1636986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1637986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1638986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1639945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1640fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1641986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1642fe1d0c2dSJung-uk Kim 		else
1643986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1644fe1d0c2dSJung-uk Kim 		if (addr == 0)
1645fe1d0c2dSJung-uk Kim 			continue;
1646986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1647bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1648bfa3f012SMarcel Moolenaar 			if (sdt == last)
1649bfa3f012SMarcel Moolenaar 				last = NULL;
1650bfa3f012SMarcel Moolenaar 			continue;
1651bfa3f012SMarcel Moolenaar 		}
1652986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1653a74172abSNate Lawson 			continue;
1654986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1655945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1656945137d9SNate Lawson 		return (sdt);
1657c62f1cccSMitsuru IWASAKI 	}
1658c62f1cccSMitsuru IWASAKI 
1659945137d9SNate Lawson 	return (NULL);
1660c62f1cccSMitsuru IWASAKI }
1661c62f1cccSMitsuru IWASAKI 
1662986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1663986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1664c62f1cccSMitsuru IWASAKI {
1665986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1666c62f1cccSMitsuru IWASAKI 
1667986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1668c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1669986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
16702e71eb12SNate Lawson 	else
1671986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1672986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1673945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1674945137d9SNate Lawson 	return (sdt);
1675c62f1cccSMitsuru IWASAKI }
1676