xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision ed26c389bfc6bbbb55e57d078258a8ae35883dc6)
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>
43340c0022SEd Maste #include <uuid.h>
44e1e9a4bfSMitsuru IWASAKI 
45e1e9a4bfSMitsuru IWASAKI #include "acpidump.h"
46e1e9a4bfSMitsuru IWASAKI 
47c62f1cccSMitsuru IWASAKI #define BEGIN_COMMENT	"/*\n"
48c62f1cccSMitsuru IWASAKI #define END_COMMENT	" */\n"
49c62f1cccSMitsuru IWASAKI 
50945137d9SNate Lawson static void	acpi_print_string(char *s, size_t length);
51986dffafSJohn Baldwin static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
52986dffafSJohn Baldwin static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
53986dffafSJohn Baldwin static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
54945137d9SNate Lawson static void	acpi_print_cpu(u_char cpu_id);
55986dffafSJohn Baldwin static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
56986dffafSJohn Baldwin static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
57986dffafSJohn Baldwin static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
58986dffafSJohn Baldwin 		    uint64_t apic_addr);
59986dffafSJohn Baldwin static void	acpi_print_mps_flags(uint16_t flags);
60986dffafSJohn Baldwin static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
61986dffafSJohn Baldwin static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
62986dffafSJohn Baldwin static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
63986dffafSJohn Baldwin static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
64986dffafSJohn Baldwin static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
65986dffafSJohn Baldwin static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
66986dffafSJohn Baldwin static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
6733866658SJohn Baldwin static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
68*ed26c389SScott Long static void	acpi_handle_wddt(ACPI_TABLE_HEADER *sdp);
69a0333ad1SJohn Baldwin static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
70a0333ad1SJohn Baldwin 		    uint32_t flags);
71986dffafSJohn Baldwin static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
72986dffafSJohn Baldwin static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
73986dffafSJohn Baldwin static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
74c031c93bSTakanori Watanabe static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
75340c0022SEd Maste static void	acpi_print_nfit(ACPI_NFIT_HEADER *nfit);
76340c0022SEd Maste static void	acpi_handle_nfit(ACPI_TABLE_HEADER *sdp);
77986dffafSJohn Baldwin static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
78986dffafSJohn Baldwin static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
79986dffafSJohn Baldwin static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
80986dffafSJohn Baldwin static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
81986dffafSJohn Baldwin static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
82986dffafSJohn Baldwin static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
83986dffafSJohn Baldwin static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
84986dffafSJohn Baldwin static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
85986dffafSJohn Baldwin 		    void (*action)(ACPI_SUBTABLE_HEADER *));
86340c0022SEd Maste static void	acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
87340c0022SEd Maste 		    void (*action)(ACPI_NFIT_HEADER *));
88c62f1cccSMitsuru IWASAKI 
89773b6454SNate Lawson /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
90a74172abSNate Lawson static int addr_size;
91a74172abSNate Lawson 
92c031c93bSTakanori Watanabe /* Strings used in the TCPA table */
93c031c93bSTakanori Watanabe static const char *tcpa_event_type_strings[] = {
94c031c93bSTakanori Watanabe 	"PREBOOT Certificate",
95c031c93bSTakanori Watanabe 	"POST Code",
96c031c93bSTakanori Watanabe 	"Unused",
97c031c93bSTakanori Watanabe 	"No Action",
98c031c93bSTakanori Watanabe 	"Separator",
99c031c93bSTakanori Watanabe 	"Action",
100c031c93bSTakanori Watanabe 	"Event Tag",
101c031c93bSTakanori Watanabe 	"S-CRTM Contents",
102c031c93bSTakanori Watanabe 	"S-CRTM Version",
103c031c93bSTakanori Watanabe 	"CPU Microcode",
104c031c93bSTakanori Watanabe 	"Platform Config Flags",
105c031c93bSTakanori Watanabe 	"Table of Devices",
106c031c93bSTakanori Watanabe 	"Compact Hash",
107c031c93bSTakanori Watanabe 	"IPL",
108c031c93bSTakanori Watanabe 	"IPL Partition Data",
109c031c93bSTakanori Watanabe 	"Non-Host Code",
110c031c93bSTakanori Watanabe 	"Non-Host Config",
111c031c93bSTakanori Watanabe 	"Non-Host Info"
112c031c93bSTakanori Watanabe };
113c031c93bSTakanori Watanabe 
114c031c93bSTakanori Watanabe static const char *TCPA_pcclient_strings[] = {
115c031c93bSTakanori Watanabe 	"<undefined>",
116c031c93bSTakanori Watanabe 	"SMBIOS",
117c031c93bSTakanori Watanabe 	"BIS Certificate",
118c031c93bSTakanori Watanabe 	"POST BIOS ROM Strings",
119c031c93bSTakanori Watanabe 	"ESCD",
120c031c93bSTakanori Watanabe 	"CMOS",
121c031c93bSTakanori Watanabe 	"NVRAM",
122c031c93bSTakanori Watanabe 	"Option ROM Execute",
123c031c93bSTakanori Watanabe 	"Option ROM Configurateion",
124c031c93bSTakanori Watanabe 	"<undefined>",
125c031c93bSTakanori Watanabe 	"Option ROM Microcode Update ",
126c031c93bSTakanori Watanabe 	"S-CRTM Version String",
127c031c93bSTakanori Watanabe 	"S-CRTM Contents",
128c031c93bSTakanori Watanabe 	"POST Contents",
129c031c93bSTakanori Watanabe 	"Table of Devices",
130c031c93bSTakanori Watanabe };
131c031c93bSTakanori Watanabe 
132ec650989SNeel Natu #define	PRINTFLAG_END()		printflag_end()
133ec650989SNeel Natu 
134ec650989SNeel Natu static char pf_sep = '{';
135ec650989SNeel Natu 
136ec650989SNeel Natu static void
137ec650989SNeel Natu printflag_end(void)
138ec650989SNeel Natu {
139ec650989SNeel Natu 
140ec650989SNeel Natu 	if (pf_sep != '{') {
141ec650989SNeel Natu 		printf("}");
142ec650989SNeel Natu 		pf_sep = '{';
143ec650989SNeel Natu 	}
144ec650989SNeel Natu 	printf("\n");
145ec650989SNeel Natu }
146ec650989SNeel Natu 
147ec650989SNeel Natu static void
148ec650989SNeel Natu printflag(uint64_t var, uint64_t mask, const char *name)
149ec650989SNeel Natu {
150ec650989SNeel Natu 
151ec650989SNeel Natu 	if (var & mask) {
152ec650989SNeel Natu 		printf("%c%s", pf_sep, name);
153ec650989SNeel Natu 		pf_sep = ',';
154ec650989SNeel Natu 	}
155ec650989SNeel Natu }
156ec650989SNeel Natu 
157e1e9a4bfSMitsuru IWASAKI static void
158e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
159e1e9a4bfSMitsuru IWASAKI {
160e1e9a4bfSMitsuru IWASAKI 	int	c;
161e1e9a4bfSMitsuru IWASAKI 
162e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
163e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
164e1e9a4bfSMitsuru IWASAKI 		length--;
165e1e9a4bfSMitsuru IWASAKI 
166e1e9a4bfSMitsuru IWASAKI 	while (length--) {
167e1e9a4bfSMitsuru IWASAKI 		c = *s++;
168e1e9a4bfSMitsuru IWASAKI 		putchar(c);
169e1e9a4bfSMitsuru IWASAKI 	}
170e1e9a4bfSMitsuru IWASAKI }
171e1e9a4bfSMitsuru IWASAKI 
172e1e9a4bfSMitsuru IWASAKI static void
173986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1748e6a8737SNate Lawson {
175986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1768e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
1777d369c6eSJung-uk Kim 		if (gas->BitWidth <= 32)
1787d369c6eSJung-uk Kim 			printf("0x%08x:%u[%u] (Memory)",
1797d369c6eSJung-uk Kim 			    (u_int)gas->Address, gas->BitOffset,
1807d369c6eSJung-uk Kim 			    gas->BitWidth);
1817d369c6eSJung-uk Kim 		else
1827d369c6eSJung-uk Kim 			printf("0x%016jx:%u[%u] (Memory)",
1837d369c6eSJung-uk Kim 			    (uintmax_t)gas->Address, gas->BitOffset,
1847d369c6eSJung-uk Kim 			    gas->BitWidth);
1858e6a8737SNate Lawson 		break;
1868e6a8737SNate Lawson 	case ACPI_GAS_IO:
1877d369c6eSJung-uk Kim 		printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
188986dffafSJohn Baldwin 		    gas->BitOffset, gas->BitWidth);
1898e6a8737SNate Lawson 		break;
1908e6a8737SNate Lawson 	case ACPI_GAS_PCI:
191986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
192986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
193986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1948e6a8737SNate Lawson 		break;
1958e6a8737SNate Lawson 	/* XXX How to handle these below? */
1968e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
197986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
198986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1998e6a8737SNate Lawson 		break;
2008e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
201986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
202986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
2038e6a8737SNate Lawson 		break;
204986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
205986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
206986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
2078e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
2088e6a8737SNate Lawson 	default:
2097d369c6eSJung-uk Kim 		printf("0x%016jx (?)", (uintmax_t)gas->Address);
2108e6a8737SNate Lawson 		break;
2118e6a8737SNate Lawson 	}
2128e6a8737SNate Lawson }
2138e6a8737SNate Lawson 
214c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
215c2962974SNate Lawson static int
216986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
217e1e9a4bfSMitsuru IWASAKI {
218c2962974SNate Lawson 	int fadt_revision;
219e1e9a4bfSMitsuru IWASAKI 
220c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
221c83f0f99SNate Lawson 	if (addr_size == 8) {
222c83f0f99SNate Lawson 		fadt_revision = 2;
2238e6a8737SNate Lawson 
224773b6454SNate Lawson 		/*
225c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
226c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
227c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
228c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
229c83f0f99SNate Lawson 		 * version for all subsequent tables.
230773b6454SNate Lawson 		 */
231986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
232986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
233c83f0f99SNate Lawson 			fadt_revision = 1;
234c2962974SNate Lawson 	} else
235c83f0f99SNate Lawson 		fadt_revision = 1;
236c2962974SNate Lawson 	return (fadt_revision);
237c83f0f99SNate Lawson }
238c2962974SNate Lawson 
239c2962974SNate Lawson static void
240986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
241c2962974SNate Lawson {
242986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
243986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
244986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
245c2962974SNate Lawson 	int		fadt_revision;
246c2962974SNate Lawson 
247986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2482177d4e6SNate Lawson 	acpi_print_fadt(sdp);
249c83f0f99SNate Lawson 
250c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
251c83f0f99SNate Lawson 	if (fadt_revision == 1)
252986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
253773b6454SNate Lawson 	else
254986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
255986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2568e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2578e6a8737SNate Lawson 	acpi_print_facs(facs);
2588e6a8737SNate Lawson 
259c83f0f99SNate Lawson 	if (fadt_revision == 1)
260986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
261773b6454SNate Lawson 	else
262986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
263986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
264945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
265945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
266c62f1cccSMitsuru IWASAKI }
267c62f1cccSMitsuru IWASAKI 
268c62f1cccSMitsuru IWASAKI static void
269986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
270986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
271986dffafSJohn Baldwin {
272986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
273986dffafSJohn Baldwin 	char *end;
274986dffafSJohn Baldwin 
275986dffafSJohn Baldwin 	subtable = first;
276986dffafSJohn Baldwin 	end = (char *)table + table->Length;
277986dffafSJohn Baldwin 	while ((char *)subtable < end) {
278986dffafSJohn Baldwin 		printf("\n");
279f5d0a8f7SEd Maste 		if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
280f5d0a8f7SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
281f5d0a8f7SEd Maste 			return;
282f5d0a8f7SEd Maste 		}
283986dffafSJohn Baldwin 		action(subtable);
284986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
285986dffafSJohn Baldwin 		    subtable->Length);
286986dffafSJohn Baldwin 	}
287986dffafSJohn Baldwin }
288986dffafSJohn Baldwin 
289986dffafSJohn Baldwin static void
290340c0022SEd Maste acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
291340c0022SEd Maste     void (*action)(ACPI_NFIT_HEADER *))
292340c0022SEd Maste {
293340c0022SEd Maste 	ACPI_NFIT_HEADER *subtable;
294340c0022SEd Maste 	char *end;
295340c0022SEd Maste 
296340c0022SEd Maste 	subtable = first;
297340c0022SEd Maste 	end = (char *)table + table->Length;
298340c0022SEd Maste 	while ((char *)subtable < end) {
299340c0022SEd Maste 		printf("\n");
300340c0022SEd Maste 		if (subtable->Length < sizeof(ACPI_NFIT_HEADER)) {
301340c0022SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
302340c0022SEd Maste 			return;
303340c0022SEd Maste 		}
304340c0022SEd Maste 		action(subtable);
305340c0022SEd Maste 		subtable = (ACPI_NFIT_HEADER *)((char *)subtable +
306340c0022SEd Maste 		    subtable->Length);
307340c0022SEd Maste 	}
308340c0022SEd Maste }
309340c0022SEd Maste 
310340c0022SEd Maste static void
3110a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
3120a473124SJohn Baldwin {
3130a473124SJohn Baldwin 
3140a473124SJohn Baldwin 	printf("\tACPI CPU=");
3150a473124SJohn Baldwin 	if (cpu_id == 0xff)
3160a473124SJohn Baldwin 		printf("ALL\n");
3170a473124SJohn Baldwin 	else
3180a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
3190a473124SJohn Baldwin }
3200a473124SJohn Baldwin 
3210a473124SJohn Baldwin static void
322986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
3230a473124SJohn Baldwin {
324986dffafSJohn Baldwin 
325986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
326986dffafSJohn Baldwin 	if (uid_string != NULL)
327986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
328986dffafSJohn Baldwin 	printf("\n");
329986dffafSJohn Baldwin }
330986dffafSJohn Baldwin 
331986dffafSJohn Baldwin static void
332986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
333986dffafSJohn Baldwin {
334986dffafSJohn Baldwin 
3350a473124SJohn Baldwin 	printf("\tFlags={");
336986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
3370a473124SJohn Baldwin 		printf("ENABLED");
3380a473124SJohn Baldwin 	else
3390a473124SJohn Baldwin 		printf("DISABLED");
3400a473124SJohn Baldwin 	printf("}\n");
341986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3420a473124SJohn Baldwin }
3430a473124SJohn Baldwin 
3440a473124SJohn Baldwin static void
345986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
3460a473124SJohn Baldwin {
347986dffafSJohn Baldwin 
348986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3490a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
350986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
3510a473124SJohn Baldwin }
3520a473124SJohn Baldwin 
3530a473124SJohn Baldwin static void
354986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
3550a473124SJohn Baldwin {
3560a473124SJohn Baldwin 
3570a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
358986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
359986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
3600a473124SJohn Baldwin 		printf("conforming");
3610a473124SJohn Baldwin 		break;
362986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3630a473124SJohn Baldwin 		printf("active-hi");
3640a473124SJohn Baldwin 		break;
365986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3660a473124SJohn Baldwin 		printf("active-lo");
3670a473124SJohn Baldwin 		break;
3680a473124SJohn Baldwin 	default:
369986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3700a473124SJohn Baldwin 		break;
3710a473124SJohn Baldwin 	}
3720a473124SJohn Baldwin 	printf(", Trigger=");
373986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
374986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3750a473124SJohn Baldwin 		printf("conforming");
3760a473124SJohn Baldwin 		break;
377986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3780a473124SJohn Baldwin 		printf("edge");
3790a473124SJohn Baldwin 		break;
380986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3810a473124SJohn Baldwin 		printf("level");
3820a473124SJohn Baldwin 		break;
3830a473124SJohn Baldwin 	default:
384986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3850a473124SJohn Baldwin 	}
3860a473124SJohn Baldwin 	printf("}\n");
3870a473124SJohn Baldwin }
3880a473124SJohn Baldwin 
3890a473124SJohn Baldwin static void
3902b2b1f42SAndrew Turner acpi_print_gicc_flags(uint32_t flags)
3912b2b1f42SAndrew Turner {
3922b2b1f42SAndrew Turner 
3932b2b1f42SAndrew Turner 	printf("\tFlags={Performance intr=");
3942b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
3952b2b1f42SAndrew Turner 		printf("edge");
3962b2b1f42SAndrew Turner 	else
3972b2b1f42SAndrew Turner 		printf("level");
3982b2b1f42SAndrew Turner 	printf(", VGIC intr=");
3992b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_VGIC_IRQ_MODE)
4002b2b1f42SAndrew Turner 		printf("edge");
4012b2b1f42SAndrew Turner 	else
4022b2b1f42SAndrew Turner 		printf("level");
4032b2b1f42SAndrew Turner 	printf("}\n");
4042b2b1f42SAndrew Turner }
4052b2b1f42SAndrew Turner 
4062b2b1f42SAndrew Turner static void
407986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
4080a473124SJohn Baldwin {
4090a473124SJohn Baldwin 
410986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
411986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
412986dffafSJohn Baldwin }
413986dffafSJohn Baldwin 
414986dffafSJohn Baldwin static void
415986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
416986dffafSJohn Baldwin {
417986dffafSJohn Baldwin 
418986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
4190a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
4200a473124SJohn Baldwin }
4210a473124SJohn Baldwin 
42227941afaSEd Maste static const char *apic_types[] = {
42327941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
42427941afaSEd Maste     [ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
42527941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
42627941afaSEd Maste     [ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
42727941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
42827941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
42927941afaSEd Maste     [ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
43027941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
43127941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
43227941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
43327941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
43427941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
43527941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
43627941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
43727941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
43827941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
43927941afaSEd Maste };
44027941afaSEd Maste 
441bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
4420a473124SJohn Baldwin 					    "Corrected Platform Error" };
4430a473124SJohn Baldwin 
4440a473124SJohn Baldwin static void
445986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
4460a473124SJohn Baldwin {
447986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
448986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
449986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
450986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
451986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
452986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
453986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
454986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
455986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
456986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
457986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
4582b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_INTERRUPT *gicc;
4592b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
4602b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
4612b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_TRANSLATOR *gict;
4620a473124SJohn Baldwin 
463c86932b6SMarcelo Araujo 	if (mp->Type < nitems(apic_types))
464986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
465a0333ad1SJohn Baldwin 	else
466986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
467986dffafSJohn Baldwin 	switch (mp->Type) {
468986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
469986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
470986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
471986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4720a473124SJohn Baldwin 		break;
473986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
474986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
475986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
476986dffafSJohn Baldwin 		    ioapic->Address);
4770a473124SJohn Baldwin 		break;
478986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
479986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
480986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
481986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
482986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
4830a473124SJohn Baldwin 		break;
484986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
485986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
486986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
4870a473124SJohn Baldwin 		break;
488986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
489986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
490986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
491986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
4920a473124SJohn Baldwin 		break;
493986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
494986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
495945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
496986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
4970a473124SJohn Baldwin 		break;
498986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
499986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
500986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
501986dffafSJohn Baldwin 		    iosapic->Address);
5020a473124SJohn Baldwin 		break;
503986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
504986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
505986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
506986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
507986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
508986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
509986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
5100a473124SJohn Baldwin 		break;
511986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
512986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
513c86932b6SMarcelo Araujo 		if (isrc->Type < nitems(platform_int_types))
514986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
515986dffafSJohn Baldwin 		else
516986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
517986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
518986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
519986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
520986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
521986dffafSJohn Baldwin 		break;
522986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
523986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
524986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
525986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
526986dffafSJohn Baldwin 		break;
527986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
528986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
529986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
530986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
5310a473124SJohn Baldwin 		break;
5322b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
5332b2b1f42SAndrew Turner 		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
5342b2b1f42SAndrew Turner 		acpi_print_cpu_uid(gicc->Uid, NULL);
5352b2b1f42SAndrew Turner 		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
5362b2b1f42SAndrew Turner 		acpi_print_gicc_flags(gicc->Flags);
5372b2b1f42SAndrew Turner 		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
5382b2b1f42SAndrew Turner 		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
5392b2b1f42SAndrew Turner 		printf("\tParked ADDR=%016jx\n",
5402b2b1f42SAndrew Turner 		    (uintmax_t)gicc->ParkedAddress);
5412b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
5422b2b1f42SAndrew Turner 		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
5432b2b1f42SAndrew Turner 		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
5442b2b1f42SAndrew Turner 		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
5452b2b1f42SAndrew Turner 		printf("\tGICR ADDR=%016jx\n",
5462b2b1f42SAndrew Turner 		    (uintmax_t)gicc->GicrBaseAddress);
5472b2b1f42SAndrew Turner 		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
5482b2b1f42SAndrew Turner 		printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass);
5492b2b1f42SAndrew Turner 		break;
5502b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
5512b2b1f42SAndrew Turner 		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
5522b2b1f42SAndrew Turner 		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
5532b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
5542b2b1f42SAndrew Turner 		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
5552b2b1f42SAndrew Turner 		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
5562b2b1f42SAndrew Turner 		break;
5572b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
5582b2b1f42SAndrew Turner 		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
5592b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
5602b2b1f42SAndrew Turner 		printf("\tLength=%08x\n", gicr->Length);
5612b2b1f42SAndrew Turner 		break;
5622b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
5632b2b1f42SAndrew Turner 		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
5642b2b1f42SAndrew Turner 		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
5652b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
5662b2b1f42SAndrew Turner 		break;
5670a473124SJohn Baldwin 	}
5680a473124SJohn Baldwin }
5690a473124SJohn Baldwin 
5700a473124SJohn Baldwin static void
571986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
5720a473124SJohn Baldwin {
573986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
5740a473124SJohn Baldwin 
575773b6454SNate Lawson 	printf(BEGIN_COMMENT);
576773b6454SNate Lawson 	acpi_print_sdt(sdp);
577986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
578986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
5790a473124SJohn Baldwin 	printf("\tFlags={");
580986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
5810a473124SJohn Baldwin 		printf("PC-AT");
5820a473124SJohn Baldwin 	printf("}\n");
583986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
5840a473124SJohn Baldwin 	printf(END_COMMENT);
5850a473124SJohn Baldwin }
5860a473124SJohn Baldwin 
5870a473124SJohn Baldwin static void
588986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
58979d7565cSPeter Wemm {
590986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
59179d7565cSPeter Wemm 
592773b6454SNate Lawson 	printf(BEGIN_COMMENT);
593773b6454SNate Lawson 	acpi_print_sdt(sdp);
594986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
595986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
59687f9f09aSTakanori Watanabe 	printf("\tADDR=");
597986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
598986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
599986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
600986dffafSJohn Baldwin 	    8);
601986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
602986dffafSJohn Baldwin 	    1 : 0);
60379d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
604986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
60579d7565cSPeter Wemm 		printf("TRUE}\n");
60679d7565cSPeter Wemm 	else
60779d7565cSPeter Wemm 		printf("FALSE}\n");
608986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
609986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
6109785e979SNeel Natu 	printf("\tFlags=0x%02x\n", hpet->Flags);
61179d7565cSPeter Wemm 	printf(END_COMMENT);
61279d7565cSPeter Wemm }
61379d7565cSPeter Wemm 
61479d7565cSPeter Wemm static void
615986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
61655d7ff9eSNate Lawson {
617986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
61855d7ff9eSNate Lawson 
61955d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
62055d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
621986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
62255d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
623986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
62455d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
625986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
626986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
627986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
628986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
62955d7ff9eSNate Lawson 	printf(END_COMMENT);
63055d7ff9eSNate Lawson }
63155d7ff9eSNate Lawson 
63255d7ff9eSNate Lawson static void
633986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
634a47e681bSScott Long {
635986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
636986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
637986dffafSJohn Baldwin 	u_int i, entries;
638a47e681bSScott Long 
639a47e681bSScott Long 	printf(BEGIN_COMMENT);
640a47e681bSScott Long 	acpi_print_sdt(sdp);
641986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
642986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
643986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
644986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
645986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
646a47e681bSScott Long 		printf("\n");
6470c10b85aSJung-uk Kim 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
648986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
649986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
650986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
651a47e681bSScott Long 	}
652a47e681bSScott Long 	printf(END_COMMENT);
653a47e681bSScott Long }
654a47e681bSScott Long 
655a47e681bSScott Long static void
65633866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
65733866658SJohn Baldwin {
65833866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
65933866658SJohn Baldwin 	UINT64 i, j;
66033866658SJohn Baldwin 
66133866658SJohn Baldwin 	printf(BEGIN_COMMENT);
66233866658SJohn Baldwin 	acpi_print_sdt(sdp);
66333866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
6640c10b85aSJung-uk Kim 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
66533866658SJohn Baldwin 	printf("\n\t      ");
66633866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
6670c10b85aSJung-uk Kim 		printf(" %3ju", (uintmax_t)i);
66833866658SJohn Baldwin 	printf("\n\t     +");
66933866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
67033866658SJohn Baldwin 		printf("----");
67133866658SJohn Baldwin 	printf("\n");
67233866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
6730c10b85aSJung-uk Kim 		printf("\t %3ju |", (uintmax_t)i);
67433866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
67533866658SJohn Baldwin 			printf(" %3d",
67633866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
67733866658SJohn Baldwin 		printf("\n");
67833866658SJohn Baldwin 	}
67933866658SJohn Baldwin 	printf(END_COMMENT);
68033866658SJohn Baldwin }
68133866658SJohn Baldwin 
68233866658SJohn Baldwin static void
683*ed26c389SScott Long acpi_handle_wddt(ACPI_TABLE_HEADER *sdp)
684*ed26c389SScott Long {
685*ed26c389SScott Long 	ACPI_TABLE_WDDT *wddt;
686*ed26c389SScott Long 
687*ed26c389SScott Long 	printf(BEGIN_COMMENT);
688*ed26c389SScott Long 	acpi_print_sdt(sdp);
689*ed26c389SScott Long 	wddt = (ACPI_TABLE_WDDT *)sdp;
690*ed26c389SScott Long 	printf("\tSpecVersion=0x%04x, TableVersion=0x%04x\n",
691*ed26c389SScott Long 	    wddt->SpecVersion, wddt->TableVersion);
692*ed26c389SScott Long 	printf("\tPciVendorId=0x%04x, Address=", wddt->PciVendorId);
693*ed26c389SScott Long 	acpi_print_gas(&wddt->Address);
694*ed26c389SScott Long 	printf("\n\tMaxCount=%u, MinCount=%u, Period=%ums\n",
695*ed26c389SScott Long 	    wddt->MaxCount, wddt->MinCount, wddt->Period);
696*ed26c389SScott Long 
697*ed26c389SScott Long #define	PRINTFLAG(var, flag)	printflag((var), ACPI_WDDT_## flag, #flag)
698*ed26c389SScott Long 	printf("\tStatus=");
699*ed26c389SScott Long 	PRINTFLAG(wddt->Status, AVAILABLE);
700*ed26c389SScott Long 	PRINTFLAG(wddt->Status, ACTIVE);
701*ed26c389SScott Long 	PRINTFLAG(wddt->Status, TCO_OS_OWNED);
702*ed26c389SScott Long 	PRINTFLAG(wddt->Status, USER_RESET);
703*ed26c389SScott Long 	PRINTFLAG(wddt->Status, WDT_RESET);
704*ed26c389SScott Long 	PRINTFLAG(wddt->Status, POWER_FAIL);
705*ed26c389SScott Long 	PRINTFLAG(wddt->Status, UNKNOWN_RESET);
706*ed26c389SScott Long 	PRINTFLAG_END();
707*ed26c389SScott Long 	printf("\tCapability=");
708*ed26c389SScott Long 	PRINTFLAG(wddt->Capability, AUTO_RESET);
709*ed26c389SScott Long 	PRINTFLAG(wddt->Capability, ALERT_SUPPORT);
710*ed26c389SScott Long 	PRINTFLAG_END();
711*ed26c389SScott Long #undef PRINTFLAG
712*ed26c389SScott Long 
713*ed26c389SScott Long 	printf(END_COMMENT);
714*ed26c389SScott Long }
715*ed26c389SScott Long 
716*ed26c389SScott Long static void
717a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
718a0333ad1SJohn Baldwin     uint32_t flags)
719a0333ad1SJohn Baldwin {
720a0333ad1SJohn Baldwin 
721a0333ad1SJohn Baldwin 	printf("\tFlags={");
722a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
723a0333ad1SJohn Baldwin 		printf("ENABLED");
724a0333ad1SJohn Baldwin 	else
725a0333ad1SJohn Baldwin 		printf("DISABLED");
726a0333ad1SJohn Baldwin 	printf("}\n");
727a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
728a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
729a0333ad1SJohn Baldwin }
730a0333ad1SJohn Baldwin 
731c031c93bSTakanori Watanabe static char *
732c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
733c031c93bSTakanori Watanabe {
734c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
735c031c93bSTakanori Watanabe 	char *eventname = NULL;
736c031c93bSTakanori Watanabe 
737c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
738c031c93bSTakanori Watanabe 
739c031c93bSTakanori Watanabe 	switch(event->event_type) {
740c031c93bSTakanori Watanabe 	case PREBOOT:
741c031c93bSTakanori Watanabe 	case POST_CODE:
742c031c93bSTakanori Watanabe 	case UNUSED:
743c031c93bSTakanori Watanabe 	case NO_ACTION:
744c031c93bSTakanori Watanabe 	case SEPARATOR:
745c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
746c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
747c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
748c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
749c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
750c031c93bSTakanori Watanabe 	case COMPACT_HASH:
751c031c93bSTakanori Watanabe 	case IPL:
752c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
753c031c93bSTakanori Watanabe 	case NONHOST_CODE:
754c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
755c031c93bSTakanori Watanabe 	case NONHOST_INFO:
756c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
757c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
758c031c93bSTakanori Watanabe 		break;
759c031c93bSTakanori Watanabe 
760c031c93bSTakanori Watanabe 	case ACTION:
761c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
762c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
763c031c93bSTakanori Watanabe 		break;
764c031c93bSTakanori Watanabe 
765c031c93bSTakanori Watanabe 	case EVENT_TAG:
766c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
767c031c93bSTakanori Watanabe 		case SMBIOS:
768c031c93bSTakanori Watanabe 		case BIS_CERT:
769c031c93bSTakanori Watanabe 		case CMOS:
770c031c93bSTakanori Watanabe 		case NVRAM:
771c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
772c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
773c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
774c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
775c031c93bSTakanori Watanabe 		case ESCD:
776c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
777c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
778c031c93bSTakanori Watanabe 		case POST_CONTENTS:
779c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
780c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
781c031c93bSTakanori Watanabe 			break;
782c031c93bSTakanori Watanabe 
783c031c93bSTakanori Watanabe 		default:
784c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
785c031c93bSTakanori Watanabe 			    pc_event->event_id);
786c031c93bSTakanori Watanabe 			break;
787c031c93bSTakanori Watanabe 		}
788c031c93bSTakanori Watanabe 		break;
789c031c93bSTakanori Watanabe 
790c031c93bSTakanori Watanabe 	default:
791c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
792c031c93bSTakanori Watanabe 		break;
793c031c93bSTakanori Watanabe 	}
794c031c93bSTakanori Watanabe 
795c031c93bSTakanori Watanabe 	return eventname;
796c031c93bSTakanori Watanabe }
797c031c93bSTakanori Watanabe 
798c031c93bSTakanori Watanabe static void
799c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
800c031c93bSTakanori Watanabe {
801c031c93bSTakanori Watanabe 	int i;
802c031c93bSTakanori Watanabe 	char *eventname;
803c031c93bSTakanori Watanabe 
804c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
805c031c93bSTakanori Watanabe 
806c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
807c031c93bSTakanori Watanabe 	printf(" 0x");
808c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
809c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
810c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
811c031c93bSTakanori Watanabe 
812c031c93bSTakanori Watanabe 	free(eventname);
813c031c93bSTakanori Watanabe }
814c031c93bSTakanori Watanabe 
815c031c93bSTakanori Watanabe static void
816c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
817c031c93bSTakanori Watanabe {
818c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
819c031c93bSTakanori Watanabe 	struct TCPAevent *event;
820977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
821c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
822c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
823c031c93bSTakanori Watanabe 
824c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
825c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
826c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
827c031c93bSTakanori Watanabe 
828c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
829c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
830c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
831c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
832c031c93bSTakanori Watanabe 		break;
833c031c93bSTakanori Watanabe 
834c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
835c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
836c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
837c031c93bSTakanori Watanabe 		break;
838c031c93bSTakanori Watanabe 
839c031c93bSTakanori Watanabe 	default:
840c031c93bSTakanori Watanabe 		printf("XXX");
841c031c93bSTakanori Watanabe 		printf(END_COMMENT);
842c031c93bSTakanori Watanabe 		return;
843c031c93bSTakanori Watanabe 	}
8440e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
845c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
846c031c93bSTakanori Watanabe 
847c031c93bSTakanori Watanabe 	if (len == 0) {
848c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
849c031c93bSTakanori Watanabe 		printf(END_COMMENT);
850c031c93bSTakanori Watanabe 		return;
851c031c93bSTakanori Watanabe 	}
8522ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
8532ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
8542ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
8552ef23c6dSTakanori Watanabe 		return;
8562ef23c6dSTakanori Watanabe 	}
857c031c93bSTakanori Watanabe 
858c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
859c031c93bSTakanori Watanabe 	vend = vaddr + len;
860c031c93bSTakanori Watanabe 
861c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
8622ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
8632ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
864c031c93bSTakanori Watanabe 			break;
8650e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
866c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
867c031c93bSTakanori Watanabe 			break;
8682ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
8692ef23c6dSTakanori Watanabe 			break;
870c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
871c031c93bSTakanori Watanabe 			break;
872c031c93bSTakanori Watanabe #if 0
873c031c93bSTakanori Watanabe 		{
874c031c93bSTakanori Watanabe 		unsigned int i, j, k;
875c031c93bSTakanori Watanabe 
876c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
877c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
878c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
879c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
880c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
881c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
882c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
883c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
884c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
885c031c93bSTakanori Watanabe 				j = i + 1;
886c031c93bSTakanori Watanabe 			}
887c031c93bSTakanori Watanabe 		}
888c031c93bSTakanori Watanabe 		printf("\n"); }
889c031c93bSTakanori Watanabe #endif
890c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
891c031c93bSTakanori Watanabe 
892c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
893c031c93bSTakanori Watanabe 	}
894c031c93bSTakanori Watanabe 
895c031c93bSTakanori Watanabe 	printf(END_COMMENT);
896c031c93bSTakanori Watanabe }
897c031c93bSTakanori Watanabe 
898ec650989SNeel Natu static const char *
899ec650989SNeel Natu devscope_type2str(int type)
900ec650989SNeel Natu {
901ec650989SNeel Natu 	static char typebuf[16];
902ec650989SNeel Natu 
903ec650989SNeel Natu 	switch (type) {
904ec650989SNeel Natu 	case 1:
905ec650989SNeel Natu 		return ("PCI Endpoint Device");
906ec650989SNeel Natu 	case 2:
907ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
908ec650989SNeel Natu 	case 3:
909ec650989SNeel Natu 		return ("IOAPIC");
910ec650989SNeel Natu 	case 4:
911ec650989SNeel Natu 		return ("HPET");
912ec650989SNeel Natu 	default:
913ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
914ec650989SNeel Natu 		return (typebuf);
915ec650989SNeel Natu 	}
916ec650989SNeel Natu }
917ec650989SNeel Natu 
918ec650989SNeel Natu static int
919ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
920ec650989SNeel Natu {
921ec650989SNeel Natu 	char sep;
922ec650989SNeel Natu 	int pathlen;
923ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
924ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
925ec650989SNeel Natu 
926ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
927ec650989SNeel Natu 		return (-1);
928ec650989SNeel Natu 
929ec650989SNeel Natu 	if (remaining < devscope->Length)
930ec650989SNeel Natu 		return (-1);
931ec650989SNeel Natu 
932ec650989SNeel Natu 	printf("\n");
933ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
934ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
935ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
936ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
937ec650989SNeel Natu 
938ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
939ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
940ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
941ec650989SNeel Natu 	if (path < pathend) {
942ec650989SNeel Natu 		sep = '{';
943ec650989SNeel Natu 		printf("\t\tPath=");
944ec650989SNeel Natu 		do {
945ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
946ec650989SNeel Natu 			sep=',';
947ec650989SNeel Natu 			path++;
948ec650989SNeel Natu 		} while (path < pathend);
949ec650989SNeel Natu 		printf("}\n");
950ec650989SNeel Natu 	}
951ec650989SNeel Natu 
952ec650989SNeel Natu 	return (devscope->Length);
953ec650989SNeel Natu }
954ec650989SNeel Natu 
955ec650989SNeel Natu static void
956ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
957ec650989SNeel Natu {
958ec650989SNeel Natu 	char *cp;
959ec650989SNeel Natu 	int remaining, consumed;
960ec650989SNeel Natu 
961ec650989SNeel Natu 	printf("\n");
962ec650989SNeel Natu 	printf("\tType=DRHD\n");
963ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
964ec650989SNeel Natu 
965ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
966ec650989SNeel Natu 
967ec650989SNeel Natu 	printf("\tFlags=");
968ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
969ec650989SNeel Natu 	PRINTFLAG_END();
970ec650989SNeel Natu 
971ec650989SNeel Natu #undef PRINTFLAG
972ec650989SNeel Natu 
973ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
9747d369c6eSJung-uk Kim 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
975ec650989SNeel Natu 
976ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
977ec650989SNeel Natu 	if (remaining > 0)
978ec650989SNeel Natu 		printf("\tDevice Scope:");
979ec650989SNeel Natu 	while (remaining > 0) {
980ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
981ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
982ec650989SNeel Natu 		if (consumed <= 0)
983ec650989SNeel Natu 			break;
984ec650989SNeel Natu 		else
985ec650989SNeel Natu 			remaining -= consumed;
986ec650989SNeel Natu 	}
987ec650989SNeel Natu }
988ec650989SNeel Natu 
989ec650989SNeel Natu static void
990ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
991ec650989SNeel Natu {
992ec650989SNeel Natu 	char *cp;
993ec650989SNeel Natu 	int remaining, consumed;
994ec650989SNeel Natu 
995ec650989SNeel Natu 	printf("\n");
996ec650989SNeel Natu 	printf("\tType=RMRR\n");
997ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
998ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
9997d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
10007d369c6eSJung-uk Kim 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
1001ec650989SNeel Natu 
1002ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
1003ec650989SNeel Natu 	if (remaining > 0)
1004ec650989SNeel Natu 		printf("\tDevice Scope:");
1005ec650989SNeel Natu 	while (remaining > 0) {
1006ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
1007ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1008ec650989SNeel Natu 		if (consumed <= 0)
1009ec650989SNeel Natu 			break;
1010ec650989SNeel Natu 		else
1011ec650989SNeel Natu 			remaining -= consumed;
1012ec650989SNeel Natu 	}
1013ec650989SNeel Natu }
1014ec650989SNeel Natu 
1015ec650989SNeel Natu static void
1016ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
1017ec650989SNeel Natu {
1018ec650989SNeel Natu 	char *cp;
1019ec650989SNeel Natu 	int remaining, consumed;
1020ec650989SNeel Natu 
1021ec650989SNeel Natu 	printf("\n");
1022ec650989SNeel Natu 	printf("\tType=ATSR\n");
1023ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
1024ec650989SNeel Natu 
1025ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1026ec650989SNeel Natu 
1027ec650989SNeel Natu 	printf("\tFlags=");
1028ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
1029ec650989SNeel Natu 	PRINTFLAG_END();
1030ec650989SNeel Natu 
1031ec650989SNeel Natu #undef PRINTFLAG
1032ec650989SNeel Natu 
1033ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
1034ec650989SNeel Natu 
1035ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
1036ec650989SNeel Natu 	if (remaining > 0)
1037ec650989SNeel Natu 		printf("\tDevice Scope:");
1038ec650989SNeel Natu 	while (remaining > 0) {
1039ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
1040ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1041ec650989SNeel Natu 		if (consumed <= 0)
1042ec650989SNeel Natu 			break;
1043ec650989SNeel Natu 		else
1044ec650989SNeel Natu 			remaining -= consumed;
1045ec650989SNeel Natu 	}
1046ec650989SNeel Natu }
1047ec650989SNeel Natu 
1048ec650989SNeel Natu static void
1049ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
1050ec650989SNeel Natu {
1051ec650989SNeel Natu 
1052ec650989SNeel Natu 	printf("\n");
1053ec650989SNeel Natu 	printf("\tType=RHSA\n");
1054ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
10557d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
1056ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
1057ec650989SNeel Natu }
1058ec650989SNeel Natu 
1059ec650989SNeel Natu static int
1060ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
1061ec650989SNeel Natu {
1062ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
1063ec650989SNeel Natu 
1064ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
1065ec650989SNeel Natu 		return (-1);
1066ec650989SNeel Natu 
1067ec650989SNeel Natu 	if (remaining < hdr->Length)
1068ec650989SNeel Natu 		return (-1);
1069ec650989SNeel Natu 
1070ec650989SNeel Natu 	switch (hdr->Type) {
1071ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1072ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
1073ec650989SNeel Natu 		break;
1074ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1075ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
1076ec650989SNeel Natu 		break;
1077313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_ROOT_ATS:
1078ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
1079ec650989SNeel Natu 		break;
1080313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1081ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
1082ec650989SNeel Natu 		break;
1083ec650989SNeel Natu 	default:
1084ec650989SNeel Natu 		printf("\n");
1085ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
1086ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
1087ec650989SNeel Natu 		break;
1088ec650989SNeel Natu 	}
1089ec650989SNeel Natu 	return (hdr->Length);
1090ec650989SNeel Natu }
1091ec650989SNeel Natu 
1092ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1093ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
1094ec650989SNeel Natu #endif
1095ec650989SNeel Natu 
1096ec650989SNeel Natu static void
1097ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1098ec650989SNeel Natu {
1099ec650989SNeel Natu 	char *cp;
1100ec650989SNeel Natu 	int remaining, consumed;
1101ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
1102ec650989SNeel Natu 
1103ec650989SNeel Natu 	printf(BEGIN_COMMENT);
1104ec650989SNeel Natu 	acpi_print_sdt(sdp);
1105ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
1106ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
1107ec650989SNeel Natu 
1108ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1109ec650989SNeel Natu 
1110ec650989SNeel Natu 	printf("\tFlags=");
1111ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
1112ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1113ec650989SNeel Natu 	PRINTFLAG_END();
1114ec650989SNeel Natu 
1115ec650989SNeel Natu #undef PRINTFLAG
1116ec650989SNeel Natu 
1117ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1118ec650989SNeel Natu 	while (remaining > 0) {
1119ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
1120ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1121ec650989SNeel Natu 		if (consumed <= 0)
1122ec650989SNeel Natu 			break;
1123ec650989SNeel Natu 		else
1124ec650989SNeel Natu 			remaining -= consumed;
1125ec650989SNeel Natu 	}
1126ec650989SNeel Natu 
1127ec650989SNeel Natu 	printf(END_COMMENT);
1128ec650989SNeel Natu }
1129ec650989SNeel Natu 
1130a0333ad1SJohn Baldwin static void
1131986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1132a0333ad1SJohn Baldwin {
1133a0333ad1SJohn Baldwin 
1134a0333ad1SJohn Baldwin 	printf("\tFlags={");
1135986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1136a0333ad1SJohn Baldwin 		printf("ENABLED");
1137a0333ad1SJohn Baldwin 	else
1138a0333ad1SJohn Baldwin 		printf("DISABLED");
1139986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1140a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1141986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1142a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1143a0333ad1SJohn Baldwin 	printf("}\n");
1144986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1145986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1146986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1147a0333ad1SJohn Baldwin }
1148a0333ad1SJohn Baldwin 
114927941afaSEd Maste static const char *srat_types[] = {
115027941afaSEd Maste     [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
115127941afaSEd Maste     [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
115227941afaSEd Maste     [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
1153cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
1154cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GIC_ITS_AFFINITY] = "GIC ITS",
115527941afaSEd Maste };
1156a0333ad1SJohn Baldwin 
1157a0333ad1SJohn Baldwin static void
1158986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1159a0333ad1SJohn Baldwin {
1160986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1161986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
11622b2b1f42SAndrew Turner 	ACPI_SRAT_GICC_AFFINITY *gic;
1163a0333ad1SJohn Baldwin 
1164c86932b6SMarcelo Araujo 	if (srat->Type < nitems(srat_types))
1165986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1166a0333ad1SJohn Baldwin 	else
1167986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1168986dffafSJohn Baldwin 	switch (srat->Type) {
1169a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1170986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1171986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1172986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1173986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1174986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1175986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1176a0333ad1SJohn Baldwin 		break;
1177a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1178986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1179a0333ad1SJohn Baldwin 		break;
1180a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1181986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1182986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1183986dffafSJohn Baldwin 		    x2apic->Flags);
1184a0333ad1SJohn Baldwin 		break;
11852b2b1f42SAndrew Turner 	case ACPI_SRAT_TYPE_GICC_AFFINITY:
11862b2b1f42SAndrew Turner 		gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
11872b2b1f42SAndrew Turner 		acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
11882b2b1f42SAndrew Turner 		    gic->Flags);
11892b2b1f42SAndrew Turner 		break;
1190a0333ad1SJohn Baldwin 	}
1191a0333ad1SJohn Baldwin }
1192a0333ad1SJohn Baldwin 
1193a0333ad1SJohn Baldwin static void
1194986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1195a0333ad1SJohn Baldwin {
1196986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1197a0333ad1SJohn Baldwin 
1198a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1199a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1200986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1201986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1202986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1203a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1204a0333ad1SJohn Baldwin }
1205a0333ad1SJohn Baldwin 
1206340c0022SEd Maste static const char *nfit_types[] = {
1207340c0022SEd Maste     [ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
1208340c0022SEd Maste     [ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
1209340c0022SEd Maste     [ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
1210340c0022SEd Maste     [ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
1211340c0022SEd Maste     [ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
1212340c0022SEd Maste     [ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
1213340c0022SEd Maste     [ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address"
1214340c0022SEd Maste };
1215340c0022SEd Maste 
1216340c0022SEd Maste 
1217340c0022SEd Maste static void
1218340c0022SEd Maste acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
1219340c0022SEd Maste {
1220340c0022SEd Maste 	char *uuidstr;
1221340c0022SEd Maste 	uint32_t status;
1222340c0022SEd Maste 
1223340c0022SEd Maste 	ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
1224340c0022SEd Maste 	ACPI_NFIT_MEMORY_MAP *mmap;
1225340c0022SEd Maste 	ACPI_NFIT_INTERLEAVE *ileave;
1226340c0022SEd Maste 	ACPI_NFIT_SMBIOS *smbios;
1227340c0022SEd Maste 	ACPI_NFIT_CONTROL_REGION *ctlreg;
1228340c0022SEd Maste 	ACPI_NFIT_DATA_REGION *datareg;
1229340c0022SEd Maste 	ACPI_NFIT_FLUSH_ADDRESS *fladdr;
1230340c0022SEd Maste 
1231340c0022SEd Maste 	if (nfit->Type < nitems(nfit_types))
1232340c0022SEd Maste 		printf("\tType=%s\n", nfit_types[nfit->Type]);
1233340c0022SEd Maste 	else
1234340c0022SEd Maste 		printf("\tType=%u (unknown)\n", nfit->Type);
1235340c0022SEd Maste 	switch (nfit->Type) {
1236340c0022SEd Maste 	case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
1237340c0022SEd Maste 		sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
1238340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
1239340c0022SEd Maste 		printf("\tProximityDomain=%u\n",
1240340c0022SEd Maste 		    (u_int)sysaddr->ProximityDomain);
1241340c0022SEd Maste 		uuid_to_string((uuid_t *)(sysaddr->RangeGuid),
1242340c0022SEd Maste 		    &uuidstr, &status);
1243340c0022SEd Maste 		if (status != uuid_s_ok)
1244340c0022SEd Maste 			errx(1, "uuid_to_string: status=%u", status);
1245340c0022SEd Maste 		printf("\tRangeGuid=%s\n", uuidstr);
1246340c0022SEd Maste 		free(uuidstr);
1247340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
1248340c0022SEd Maste 		printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
1249340c0022SEd Maste 		printf("\tMemoryMapping=0x%016jx\n",
1250340c0022SEd Maste 		    (uintmax_t)sysaddr->MemoryMapping);
1251340c0022SEd Maste 
1252340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1253340c0022SEd Maste 
1254340c0022SEd Maste 		printf("\tFlags=");
1255340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
1256340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
1257340c0022SEd Maste 		PRINTFLAG_END();
1258340c0022SEd Maste 
1259340c0022SEd Maste #undef PRINTFLAG
1260340c0022SEd Maste 
1261340c0022SEd Maste 		break;
1262340c0022SEd Maste 	case ACPI_NFIT_TYPE_MEMORY_MAP:
1263340c0022SEd Maste 		mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
1264340c0022SEd Maste 		printf("\tDeviceHandle=%u\n", (u_int)mmap->DeviceHandle);
1265340c0022SEd Maste 		printf("\tPhysicalId=%u\n", (u_int)mmap->PhysicalId);
1266340c0022SEd Maste 		printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
1267340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
1268340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
1269340c0022SEd Maste 		printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
1270340c0022SEd Maste 		printf("\tRegionOffset=0x%016jx\n",
1271340c0022SEd Maste 		    (uintmax_t)mmap->RegionOffset);
1272340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
1273340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
1274fb1cf2a9SAlexander Motin 		printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
1275340c0022SEd Maste 
1276340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_MEM_## flag, #flag)
1277340c0022SEd Maste 
1278340c0022SEd Maste 		printf("\tFlags=");
1279340c0022SEd Maste 		PRINTFLAG(mmap->Flags, SAVE_FAILED);
1280340c0022SEd Maste 		PRINTFLAG(mmap->Flags, RESTORE_FAILED);
1281340c0022SEd Maste 		PRINTFLAG(mmap->Flags, FLUSH_FAILED);
1282340c0022SEd Maste 		PRINTFLAG(mmap->Flags, NOT_ARMED);
1283340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
1284340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
1285340c0022SEd Maste 		PRINTFLAG(mmap->Flags, MAP_FAILED);
1286340c0022SEd Maste 		PRINTFLAG_END();
1287340c0022SEd Maste 
1288340c0022SEd Maste #undef PRINTFLAG
1289340c0022SEd Maste 
1290340c0022SEd Maste 		break;
1291340c0022SEd Maste 	case ACPI_NFIT_TYPE_INTERLEAVE:
1292340c0022SEd Maste 		ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
1293340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n",
1294340c0022SEd Maste 		    (u_int)ileave->InterleaveIndex);
1295340c0022SEd Maste 		printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
1296340c0022SEd Maste 		printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
1297340c0022SEd Maste 		/* XXX ileave->LineOffset[i] output is not supported */
1298340c0022SEd Maste 		break;
1299340c0022SEd Maste 	case ACPI_NFIT_TYPE_SMBIOS:
1300340c0022SEd Maste 		smbios = (ACPI_NFIT_SMBIOS *)nfit;
1301340c0022SEd Maste 		/* XXX smbios->Data[x] output is not supported */
1302340c0022SEd Maste 		break;
1303340c0022SEd Maste 	case ACPI_NFIT_TYPE_CONTROL_REGION:
1304340c0022SEd Maste 		ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
1305340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
1306340c0022SEd Maste 		printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
1307340c0022SEd Maste 		printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
1308340c0022SEd Maste 		printf("\tRevisionId=%u\n", (u_int)ctlreg->RevisionId);
1309340c0022SEd Maste 		printf("\tSubsystemVendorId=0x%04x\n",
1310340c0022SEd Maste 		    (u_int)ctlreg->SubsystemVendorId);
1311340c0022SEd Maste 		printf("\tSubsystemDeviceId=0x%04x\n",
1312340c0022SEd Maste 		    (u_int)ctlreg->SubsystemDeviceId);
1313340c0022SEd Maste 		printf("\tSubsystemRevisionId=%u\n",
1314340c0022SEd Maste 		    (u_int)ctlreg->SubsystemRevisionId);
1315d4c2de2eSAlexander Motin 		printf("\tValidFields=0x%02x\n", (u_int)ctlreg->ValidFields);
1316340c0022SEd Maste 		printf("\tManufacturingLocation=%u\n",
1317340c0022SEd Maste 		    (u_int)ctlreg->ManufacturingLocation);
1318340c0022SEd Maste 		printf("\tManufacturingDate=%u\n",
1319340c0022SEd Maste 		    (u_int)ctlreg->ManufacturingDate);
1320340c0022SEd Maste 		printf("\tSerialNumber=%u\n",
1321340c0022SEd Maste 		    (u_int)ctlreg->SerialNumber);
1322fb1cf2a9SAlexander Motin 		printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
1323340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
1324340c0022SEd Maste 		printf("\tWindowSize=0x%016jx\n",
1325340c0022SEd Maste 		    (uintmax_t)ctlreg->WindowSize);
1326340c0022SEd Maste 		printf("\tCommandOffset=0x%016jx\n",
1327340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandOffset);
1328340c0022SEd Maste 		printf("\tCommandSize=0x%016jx\n",
1329340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandSize);
1330340c0022SEd Maste 		printf("\tStatusOffset=0x%016jx\n",
1331340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusOffset);
1332340c0022SEd Maste 		printf("\tStatusSize=0x%016jx\n",
1333340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusSize);
1334340c0022SEd Maste 
1335340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1336340c0022SEd Maste 
1337340c0022SEd Maste 		printf("\tFlags=");
1338d4c2de2eSAlexander Motin 		PRINTFLAG(ctlreg->Flags, CONTROL_BUFFERED);
1339340c0022SEd Maste 		PRINTFLAG_END();
1340340c0022SEd Maste 
1341340c0022SEd Maste #undef PRINTFLAG
1342340c0022SEd Maste 
1343340c0022SEd Maste 		break;
1344340c0022SEd Maste 	case ACPI_NFIT_TYPE_DATA_REGION:
1345340c0022SEd Maste 		datareg = (ACPI_NFIT_DATA_REGION *)nfit;
1346340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
1347340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)datareg->Windows);
1348340c0022SEd Maste 		printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
1349340c0022SEd Maste 		printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
1350340c0022SEd Maste 		printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
1351340c0022SEd Maste 		printf("\tStartAddress=0x%016jx\n",
1352340c0022SEd Maste 		    (uintmax_t)datareg->StartAddress);
1353340c0022SEd Maste 		break;
1354340c0022SEd Maste 	case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
1355340c0022SEd Maste 		fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
1356340c0022SEd Maste 		printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
1357340c0022SEd Maste 		printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
1358340c0022SEd Maste 		/* XXX fladdr->HintAddress[i] output is not supported */
1359340c0022SEd Maste 		break;
1360340c0022SEd Maste 	}
1361340c0022SEd Maste }
1362340c0022SEd Maste 
1363340c0022SEd Maste static void
1364340c0022SEd Maste acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
1365340c0022SEd Maste {
1366340c0022SEd Maste 	ACPI_TABLE_NFIT *nfit;
1367340c0022SEd Maste 
1368340c0022SEd Maste 	printf(BEGIN_COMMENT);
1369340c0022SEd Maste 	acpi_print_sdt(sdp);
1370340c0022SEd Maste 	nfit = (ACPI_TABLE_NFIT *)sdp;
1371340c0022SEd Maste 	acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
1372340c0022SEd Maste 	printf(END_COMMENT);
1373340c0022SEd Maste }
1374340c0022SEd Maste 
1375a0333ad1SJohn Baldwin static void
1376986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1377c62f1cccSMitsuru IWASAKI {
1378773b6454SNate Lawson 	printf("  ");
1379986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
1380c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1381986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1382e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1383986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1384e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1385986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1386986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1387e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1388986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
1389986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1390e1e9a4bfSMitsuru IWASAKI }
1391e1e9a4bfSMitsuru IWASAKI 
1392945137d9SNate Lawson static void
1393986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1394e1e9a4bfSMitsuru IWASAKI {
1395986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1396986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1397e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1398e1e9a4bfSMitsuru IWASAKI 
1399986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1400986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1401773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1402773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1403986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1404e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1405e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1406e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1407e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1408fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
14097d369c6eSJung-uk Kim 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1410fe1d0c2dSJung-uk Kim 		else
14117d369c6eSJung-uk Kim 			printf("0x%016jx",
14127d369c6eSJung-uk Kim 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1413e1e9a4bfSMitsuru IWASAKI 	}
1414e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1415c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1416e1e9a4bfSMitsuru IWASAKI }
1417e1e9a4bfSMitsuru IWASAKI 
14188e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
14198e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
14208e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
14218e6a8737SNate Lawson };
14228e6a8737SNate Lawson 
1423945137d9SNate Lawson static void
1424986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1425e1e9a4bfSMitsuru IWASAKI {
1426986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
14278e6a8737SNate Lawson 	const char *pm;
1428e1e9a4bfSMitsuru IWASAKI 
1429986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1430c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
14312177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1432986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1433986dffafSJohn Baldwin 	       fadt->Dsdt);
1434986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1435986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
14368e6a8737SNate Lawson 		pm = "Reserved";
14378e6a8737SNate Lawson 	else
1438986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1439986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1440986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1441986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1442986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1443986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1444986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1445986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1446e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1447986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1448986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1449986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1450e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1451986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1452986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1453e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1454986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1455986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1456986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1457e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1458986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1459986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1460986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1461e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1462986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1463986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1464c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1465986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1466986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1467986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
14688e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1469986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1470986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1471986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
14728e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1473986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1474986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1475986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1476986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1477986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
147851c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1479986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1480e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1481986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1482e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1483986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1484e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1485986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1486e1e9a4bfSMitsuru IWASAKI 
1487ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1488e1e9a4bfSMitsuru IWASAKI 
14898e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1490986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1491986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1492986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1493986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1494986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1495f6469ce1SAndrew Turner 	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1496ec650989SNeel Natu 	PRINTFLAG_END();
14978e6a8737SNate Lawson 
14988e6a8737SNate Lawson 	printf("\tFlags=");
1499986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1500986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1501986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1502986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1503986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1504986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1505986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1506986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1507986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1508986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1509986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1510986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1511986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1512986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1513986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1514986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1515986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1516986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1517986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1518986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1519f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, HW_REDUCED);
1520f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1521ec650989SNeel Natu 	PRINTFLAG_END();
1522e1e9a4bfSMitsuru IWASAKI 
1523e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1524e1e9a4bfSMitsuru IWASAKI 
1525986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
15268e6a8737SNate Lawson 		printf("\tRESET_REG=");
1527986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1528986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
15298e6a8737SNate Lawson 	}
1530c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
15317d369c6eSJung-uk Kim 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
15327d369c6eSJung-uk Kim 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1533c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1534986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1535986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1536c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1537986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1538c08c4e81SNate Lawson 		}
1539c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1540986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1541986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1542c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1543986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1544c08c4e81SNate Lawson 		}
1545986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1546773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1547986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1548c08c4e81SNate Lawson 		}
1549773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1550986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1551986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1552773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1553986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1554c08c4e81SNate Lawson 		}
1555986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1556773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1557986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1558c08c4e81SNate Lawson 		}
1559773b6454SNate Lawson 		printf("\n");
1560773b6454SNate Lawson 	}
15618e6a8737SNate Lawson 
15628e6a8737SNate Lawson 	printf(END_COMMENT);
15638e6a8737SNate Lawson }
15648e6a8737SNate Lawson 
15658e6a8737SNate Lawson static void
1566986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
15678e6a8737SNate Lawson {
15688e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1569986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1570986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1571986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
15728e6a8737SNate Lawson 
1573773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1574986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1575986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
15768e6a8737SNate Lawson 			printf("PENDING,");
1577986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
15788e6a8737SNate Lawson 			printf("OWNED");
15798e6a8737SNate Lawson 	}
1580773b6454SNate Lawson 	printf("\n");
15818e6a8737SNate Lawson 
1582773b6454SNate Lawson 	printf("\tFlags=");
1583986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
15848e6a8737SNate Lawson 		printf("S4BIOS");
1585773b6454SNate Lawson 	printf("\n");
15868e6a8737SNate Lawson 
15877d369c6eSJung-uk Kim 	if (facs->XFirmwareWakingVector != 0)
15887d369c6eSJung-uk Kim 		printf("\tX_Firm_Wake_Vec=%016jx\n",
15897d369c6eSJung-uk Kim 		    (uintmax_t)facs->XFirmwareWakingVector);
1590986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
15918e6a8737SNate Lawson 
1592c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1593e1e9a4bfSMitsuru IWASAKI }
1594e1e9a4bfSMitsuru IWASAKI 
1595945137d9SNate Lawson static void
1596986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1597e1e9a4bfSMitsuru IWASAKI {
1598773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1599773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1600773b6454SNate Lawson 	printf(END_COMMENT);
1601e1e9a4bfSMitsuru IWASAKI }
1602e1e9a4bfSMitsuru IWASAKI 
1603e1e9a4bfSMitsuru IWASAKI int
1604e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1605e1e9a4bfSMitsuru IWASAKI {
1606986dffafSJohn Baldwin 	uint8_t *bp;
1607986dffafSJohn Baldwin 	uint8_t sum;
1608e1e9a4bfSMitsuru IWASAKI 
1609e1e9a4bfSMitsuru IWASAKI 	bp = p;
1610e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1611e1e9a4bfSMitsuru IWASAKI 	while (length--)
1612e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1613e1e9a4bfSMitsuru IWASAKI 
1614e1e9a4bfSMitsuru IWASAKI 	return (sum);
1615e1e9a4bfSMitsuru IWASAKI }
1616e1e9a4bfSMitsuru IWASAKI 
1617986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1618e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1619e1e9a4bfSMitsuru IWASAKI {
1620986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1621e1e9a4bfSMitsuru IWASAKI 
1622986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1623986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1624e1e9a4bfSMitsuru IWASAKI 	return (sp);
1625e1e9a4bfSMitsuru IWASAKI }
1626e1e9a4bfSMitsuru IWASAKI 
1627945137d9SNate Lawson static void
1628986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1629e1e9a4bfSMitsuru IWASAKI {
1630c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1631a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1632986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1633986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1634986dffafSJohn Baldwin 	       rp->Revision);
1635986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1636986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1637986dffafSJohn Baldwin 		    rp->Checksum);
1638a74172abSNate Lawson 	} else {
16397d369c6eSJung-uk Kim 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
16407d369c6eSJung-uk Kim 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
1641986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1642a74172abSNate Lawson 	}
1643c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1644e1e9a4bfSMitsuru IWASAKI }
1645e1e9a4bfSMitsuru IWASAKI 
1646945137d9SNate Lawson static void
1647986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1648e1e9a4bfSMitsuru IWASAKI {
1649986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1650986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1651986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1652a74172abSNate Lawson 	vm_offset_t addr;
1653a74172abSNate Lawson 	int entries, i;
1654e1e9a4bfSMitsuru IWASAKI 
1655e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1656986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1657986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1658986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1659e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1660fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1661986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1662fe1d0c2dSJung-uk Kim 		else
1663986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1664fe1d0c2dSJung-uk Kim 		if (addr == 0)
1665fe1d0c2dSJung-uk Kim 			continue;
1666986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1667986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
16685cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1669986dffafSJohn Baldwin 			    sdp->Signature);
16705cf6d493SNate Lawson 			continue;
16715cf6d493SNate Lawson 		}
1672986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
16732177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1674986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1675986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1676986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
167779d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1678986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
167955d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1680986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1681a47e681bSScott Long 			acpi_handle_mcfg(sdp);
168233866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
168333866658SJohn Baldwin 			acpi_handle_slit(sdp);
1684986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1685a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1686c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1687c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1688ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1689ec650989SNeel Natu 			acpi_handle_dmar(sdp);
1690340c0022SEd Maste 		else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
1691340c0022SEd Maste 			acpi_handle_nfit(sdp);
1692*ed26c389SScott Long 		else if (!memcmp(sdp->Signature, ACPI_SIG_WDDT, 4))
1693*ed26c389SScott Long 			acpi_handle_wddt(sdp);
1694773b6454SNate Lawson 		else {
1695773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1696773b6454SNate Lawson 			acpi_print_sdt(sdp);
1697773b6454SNate Lawson 			printf(END_COMMENT);
1698773b6454SNate Lawson 		}
1699e1e9a4bfSMitsuru IWASAKI 	}
1700e1e9a4bfSMitsuru IWASAKI }
1701c62f1cccSMitsuru IWASAKI 
1702986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1703476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1704945137d9SNate Lawson {
1705986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1706986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1707945137d9SNate Lawson 
1708945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1709945137d9SNate Lawson 	if (!rp)
1710945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1711945137d9SNate Lawson 
1712945137d9SNate Lawson 	if (tflag)
1713945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1714986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1715986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1716986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1717986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1718945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1719a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1720a74172abSNate Lawson 	} else {
1721986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1722986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1723986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1724a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1725a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1726a74172abSNate Lawson 	}
1727945137d9SNate Lawson 	return (rsdp);
1728945137d9SNate Lawson }
1729c62f1cccSMitsuru IWASAKI 
173062c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1731bfa3f012SMarcel Moolenaar static int
1732986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1733bfa3f012SMarcel Moolenaar {
1734986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1735986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1736bfa3f012SMarcel Moolenaar 	uint8_t sum;
1737bfa3f012SMarcel Moolenaar 
173862c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1739bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1740bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1741986dffafSJohn Baldwin 		sdt.Checksum = 0;
1742986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1743986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1744986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1745f7675a56SNate Lawson 		while (ssdt != NULL) {
1746986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1747986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1748986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1749986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1750bfa3f012SMarcel Moolenaar 		}
1751986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1752986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1753bfa3f012SMarcel Moolenaar 	}
175462c7bde1SNate Lawson 
175562c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1756986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1757986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
175862c7bde1SNate Lawson 
1759b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1760f7675a56SNate Lawson 	if (rsdt != NULL) {
1761bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1762bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1763986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1764986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1765bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1766bfa3f012SMarcel Moolenaar 		}
1767bfa3f012SMarcel Moolenaar 	}
1768bfa3f012SMarcel Moolenaar 	return (0);
1769bfa3f012SMarcel Moolenaar }
1770bfa3f012SMarcel Moolenaar 
1771c62f1cccSMitsuru IWASAKI void
1772986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1773c62f1cccSMitsuru IWASAKI {
1774945137d9SNate Lawson 	int	fd;
1775945137d9SNate Lawson 	mode_t	mode;
1776945137d9SNate Lawson 
1777945137d9SNate Lawson 	assert(outfile != NULL);
1778945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1779945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1780945137d9SNate Lawson 	if (fd == -1) {
1781945137d9SNate Lawson 		perror("dsdt_save_file");
1782945137d9SNate Lawson 		return;
1783945137d9SNate Lawson 	}
1784bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1785945137d9SNate Lawson 	close(fd);
1786c62f1cccSMitsuru IWASAKI }
1787c62f1cccSMitsuru IWASAKI 
1788945137d9SNate Lawson void
1789986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1790c62f1cccSMitsuru IWASAKI {
17917e2cc014SDon Lewis 	char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
17927e2cc014SDon Lewis 	const char *iname = "/acpdump.din";
17937e2cc014SDon Lewis 	const char *oname = "/acpdump.dsl";
179499065116SJung-uk Kim 	const char *tmpdir;
1795945137d9SNate Lawson 	FILE *fp;
179699065116SJung-uk Kim 	size_t len;
17977e2cc014SDon Lewis 	int fd, status;
17987e2cc014SDon Lewis 	pid_t pid;
1799945137d9SNate Lawson 
180099065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
180199065116SJung-uk Kim 	if (tmpdir == NULL)
180299065116SJung-uk Kim 		tmpdir = _PATH_TMP;
18037e2cc014SDon Lewis 	if (realpath(tmpdir, buf) == NULL) {
1804d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
180599065116SJung-uk Kim 		return;
180699065116SJung-uk Kim 	}
18077e2cc014SDon Lewis 	len = sizeof(wrkdir) - strlen(iname);
18087e2cc014SDon Lewis 	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
18097e2cc014SDon Lewis 		fprintf(stderr, "$TMPDIR too long\n");
18107e2cc014SDon Lewis 		return;
18117e2cc014SDon Lewis 	}
18127e2cc014SDon Lewis 	if  (mkdtemp(wrkdir) == NULL) {
18137e2cc014SDon Lewis 		perror("mkdtemp tmp working dir");
18147e2cc014SDon Lewis 		return;
18157e2cc014SDon Lewis 	}
181630bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
181730bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
18187e2cc014SDon Lewis 	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1819945137d9SNate Lawson 	if (fd < 0) {
1820945137d9SNate Lawson 		perror("iasl tmp file");
1821945137d9SNate Lawson 		return;
1822c62f1cccSMitsuru IWASAKI 	}
1823bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1824945137d9SNate Lawson 	close(fd);
1825945137d9SNate Lawson 
1826945137d9SNate Lawson 	/* Run iasl -d on the temp file */
18277e2cc014SDon Lewis 	if ((pid = fork()) == 0) {
1828945137d9SNate Lawson 		close(STDOUT_FILENO);
1829945137d9SNate Lawson 		if (vflag == 0)
1830945137d9SNate Lawson 			close(STDERR_FILENO);
183199065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1832945137d9SNate Lawson 		err(1, "exec");
1833c62f1cccSMitsuru IWASAKI 	}
18347e2cc014SDon Lewis 	if (pid > 0)
18357e2cc014SDon Lewis 		wait(&status);
18367e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
18377e2cc014SDon Lewis 		perror("unlink");
18387e2cc014SDon Lewis 		goto out;
18397e2cc014SDon Lewis 	}
18407e2cc014SDon Lewis 	if (pid < 0) {
18417e2cc014SDon Lewis 		perror("fork");
18427e2cc014SDon Lewis 		goto out;
18437e2cc014SDon Lewis 	}
18447e2cc014SDon Lewis 	if (status != 0) {
18457e2cc014SDon Lewis 		fprintf(stderr, "iast exit status = %d\n", status);
18467e2cc014SDon Lewis 	}
1847945137d9SNate Lawson 
1848945137d9SNate Lawson 	/* Dump iasl's output to stdout */
184930bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
185030bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
185199065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
18527e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
18537e2cc014SDon Lewis 		perror("unlink");
18547e2cc014SDon Lewis 		goto out;
18557e2cc014SDon Lewis 	}
1856945137d9SNate Lawson 	if (fp == NULL) {
1857945137d9SNate Lawson 		perror("iasl tmp file (read)");
18587e2cc014SDon Lewis 		goto out;
1859945137d9SNate Lawson 	}
1860945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1861945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1862945137d9SNate Lawson 	fclose(fp);
18637e2cc014SDon Lewis 
18647e2cc014SDon Lewis     out:
18657e2cc014SDon Lewis 	if (rmdir(wrkdir) < 0)
18667e2cc014SDon Lewis 		perror("rmdir");
1867c62f1cccSMitsuru IWASAKI }
1868c62f1cccSMitsuru IWASAKI 
1869945137d9SNate Lawson void
1870986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1871c62f1cccSMitsuru IWASAKI {
1872945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1873c62f1cccSMitsuru IWASAKI }
1874c62f1cccSMitsuru IWASAKI 
1875bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1876986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1877986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1878c62f1cccSMitsuru IWASAKI {
1879986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1880986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1881986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1882a74172abSNate Lawson 	vm_offset_t addr;
1883a74172abSNate Lawson 	int entries, i;
1884945137d9SNate Lawson 
1885986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1886986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1887986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1888945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1889fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1890986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1891fe1d0c2dSJung-uk Kim 		else
1892986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1893fe1d0c2dSJung-uk Kim 		if (addr == 0)
1894fe1d0c2dSJung-uk Kim 			continue;
1895986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1896bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1897bfa3f012SMarcel Moolenaar 			if (sdt == last)
1898bfa3f012SMarcel Moolenaar 				last = NULL;
1899bfa3f012SMarcel Moolenaar 			continue;
1900bfa3f012SMarcel Moolenaar 		}
1901986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1902a74172abSNate Lawson 			continue;
1903986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1904945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1905945137d9SNate Lawson 		return (sdt);
1906c62f1cccSMitsuru IWASAKI 	}
1907c62f1cccSMitsuru IWASAKI 
1908945137d9SNate Lawson 	return (NULL);
1909c62f1cccSMitsuru IWASAKI }
1910c62f1cccSMitsuru IWASAKI 
1911986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1912986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1913c62f1cccSMitsuru IWASAKI {
1914986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1915c62f1cccSMitsuru IWASAKI 
1916986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1917c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1918986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
19192e71eb12SNate Lawson 	else
1920986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1921986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1922945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1923945137d9SNate Lawson 	return (sdt);
1924c62f1cccSMitsuru IWASAKI }
1925