xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision 1de7b4b805ddbf2429da511c053686ac4591ed89)
1e1e9a4bfSMitsuru IWASAKI /*-
2*1de7b4b8SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*1de7b4b8SPedro F. Giffuni  *
4e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 1998 Doug Rabson
5e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6e1e9a4bfSMitsuru IWASAKI  * All rights reserved.
7e1e9a4bfSMitsuru IWASAKI  *
8e1e9a4bfSMitsuru IWASAKI  * Redistribution and use in source and binary forms, with or without
9e1e9a4bfSMitsuru IWASAKI  * modification, are permitted provided that the following conditions
10e1e9a4bfSMitsuru IWASAKI  * are met:
11e1e9a4bfSMitsuru IWASAKI  * 1. Redistributions of source code must retain the above copyright
12e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer.
13e1e9a4bfSMitsuru IWASAKI  * 2. Redistributions in binary form must reproduce the above copyright
14e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer in the
15e1e9a4bfSMitsuru IWASAKI  *    documentation and/or other materials provided with the distribution.
16e1e9a4bfSMitsuru IWASAKI  *
17e1e9a4bfSMitsuru IWASAKI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18e1e9a4bfSMitsuru IWASAKI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19e1e9a4bfSMitsuru IWASAKI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20e1e9a4bfSMitsuru IWASAKI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21e1e9a4bfSMitsuru IWASAKI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22e1e9a4bfSMitsuru IWASAKI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23e1e9a4bfSMitsuru IWASAKI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24e1e9a4bfSMitsuru IWASAKI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25e1e9a4bfSMitsuru IWASAKI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26e1e9a4bfSMitsuru IWASAKI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27e1e9a4bfSMitsuru IWASAKI  * SUCH DAMAGE.
28e1e9a4bfSMitsuru IWASAKI  *
29e1e9a4bfSMitsuru IWASAKI  *	$FreeBSD$
30e1e9a4bfSMitsuru IWASAKI  */
31e1e9a4bfSMitsuru IWASAKI 
32e1e9a4bfSMitsuru IWASAKI #include <sys/param.h>
33a74172abSNate Lawson #include <sys/endian.h>
34e1e9a4bfSMitsuru IWASAKI #include <sys/stat.h>
35945137d9SNate Lawson #include <sys/wait.h>
36e1e9a4bfSMitsuru IWASAKI #include <assert.h>
37e1e9a4bfSMitsuru IWASAKI #include <err.h>
38e1e9a4bfSMitsuru IWASAKI #include <fcntl.h>
3999065116SJung-uk Kim #include <paths.h>
40e1e9a4bfSMitsuru IWASAKI #include <stdio.h>
41a0333ad1SJohn Baldwin #include <stdint.h>
4299065116SJung-uk Kim #include <stdlib.h>
43945137d9SNate Lawson #include <string.h>
44e1e9a4bfSMitsuru IWASAKI #include <unistd.h>
45340c0022SEd Maste #include <uuid.h>
46e1e9a4bfSMitsuru IWASAKI 
47e1e9a4bfSMitsuru IWASAKI #include "acpidump.h"
48e1e9a4bfSMitsuru IWASAKI 
49c62f1cccSMitsuru IWASAKI #define BEGIN_COMMENT	"/*\n"
50c62f1cccSMitsuru IWASAKI #define END_COMMENT	" */\n"
51c62f1cccSMitsuru IWASAKI 
52945137d9SNate Lawson static void	acpi_print_string(char *s, size_t length);
53986dffafSJohn Baldwin static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
54986dffafSJohn Baldwin static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
55986dffafSJohn Baldwin static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
56945137d9SNate Lawson static void	acpi_print_cpu(u_char cpu_id);
57986dffafSJohn Baldwin static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
58986dffafSJohn Baldwin static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
59986dffafSJohn Baldwin static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
60986dffafSJohn Baldwin 		    uint64_t apic_addr);
61986dffafSJohn Baldwin static void	acpi_print_mps_flags(uint16_t flags);
62986dffafSJohn Baldwin static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
63986dffafSJohn Baldwin static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
64986dffafSJohn Baldwin static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
65986dffafSJohn Baldwin static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
66986dffafSJohn Baldwin static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
67986dffafSJohn Baldwin static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
68986dffafSJohn Baldwin static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
6933866658SJohn Baldwin static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
70ed26c389SScott Long static void	acpi_handle_wddt(ACPI_TABLE_HEADER *sdp);
71a0333ad1SJohn Baldwin static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
72a0333ad1SJohn Baldwin 		    uint32_t flags);
73986dffafSJohn Baldwin static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
74986dffafSJohn Baldwin static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
75986dffafSJohn Baldwin static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
76c031c93bSTakanori Watanabe static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
77340c0022SEd Maste static void	acpi_print_nfit(ACPI_NFIT_HEADER *nfit);
78340c0022SEd Maste static void	acpi_handle_nfit(ACPI_TABLE_HEADER *sdp);
79986dffafSJohn Baldwin static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
80986dffafSJohn Baldwin static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
81986dffafSJohn Baldwin static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
82986dffafSJohn Baldwin static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
83986dffafSJohn Baldwin static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
84986dffafSJohn Baldwin static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
85986dffafSJohn Baldwin static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
86986dffafSJohn Baldwin static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
87986dffafSJohn Baldwin 		    void (*action)(ACPI_SUBTABLE_HEADER *));
88340c0022SEd Maste static void	acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
89340c0022SEd Maste 		    void (*action)(ACPI_NFIT_HEADER *));
90c62f1cccSMitsuru IWASAKI 
91773b6454SNate Lawson /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
92a74172abSNate Lawson static int addr_size;
93a74172abSNate Lawson 
94c031c93bSTakanori Watanabe /* Strings used in the TCPA table */
95c031c93bSTakanori Watanabe static const char *tcpa_event_type_strings[] = {
96c031c93bSTakanori Watanabe 	"PREBOOT Certificate",
97c031c93bSTakanori Watanabe 	"POST Code",
98c031c93bSTakanori Watanabe 	"Unused",
99c031c93bSTakanori Watanabe 	"No Action",
100c031c93bSTakanori Watanabe 	"Separator",
101c031c93bSTakanori Watanabe 	"Action",
102c031c93bSTakanori Watanabe 	"Event Tag",
103c031c93bSTakanori Watanabe 	"S-CRTM Contents",
104c031c93bSTakanori Watanabe 	"S-CRTM Version",
105c031c93bSTakanori Watanabe 	"CPU Microcode",
106c031c93bSTakanori Watanabe 	"Platform Config Flags",
107c031c93bSTakanori Watanabe 	"Table of Devices",
108c031c93bSTakanori Watanabe 	"Compact Hash",
109c031c93bSTakanori Watanabe 	"IPL",
110c031c93bSTakanori Watanabe 	"IPL Partition Data",
111c031c93bSTakanori Watanabe 	"Non-Host Code",
112c031c93bSTakanori Watanabe 	"Non-Host Config",
113c031c93bSTakanori Watanabe 	"Non-Host Info"
114c031c93bSTakanori Watanabe };
115c031c93bSTakanori Watanabe 
116c031c93bSTakanori Watanabe static const char *TCPA_pcclient_strings[] = {
117c031c93bSTakanori Watanabe 	"<undefined>",
118c031c93bSTakanori Watanabe 	"SMBIOS",
119c031c93bSTakanori Watanabe 	"BIS Certificate",
120c031c93bSTakanori Watanabe 	"POST BIOS ROM Strings",
121c031c93bSTakanori Watanabe 	"ESCD",
122c031c93bSTakanori Watanabe 	"CMOS",
123c031c93bSTakanori Watanabe 	"NVRAM",
124c031c93bSTakanori Watanabe 	"Option ROM Execute",
125c031c93bSTakanori Watanabe 	"Option ROM Configurateion",
126c031c93bSTakanori Watanabe 	"<undefined>",
127c031c93bSTakanori Watanabe 	"Option ROM Microcode Update ",
128c031c93bSTakanori Watanabe 	"S-CRTM Version String",
129c031c93bSTakanori Watanabe 	"S-CRTM Contents",
130c031c93bSTakanori Watanabe 	"POST Contents",
131c031c93bSTakanori Watanabe 	"Table of Devices",
132c031c93bSTakanori Watanabe };
133c031c93bSTakanori Watanabe 
134ec650989SNeel Natu #define	PRINTFLAG_END()		printflag_end()
135ec650989SNeel Natu 
136ec650989SNeel Natu static char pf_sep = '{';
137ec650989SNeel Natu 
138ec650989SNeel Natu static void
139ec650989SNeel Natu printflag_end(void)
140ec650989SNeel Natu {
141ec650989SNeel Natu 
142ec650989SNeel Natu 	if (pf_sep != '{') {
143ec650989SNeel Natu 		printf("}");
144ec650989SNeel Natu 		pf_sep = '{';
145ec650989SNeel Natu 	}
146ec650989SNeel Natu 	printf("\n");
147ec650989SNeel Natu }
148ec650989SNeel Natu 
149ec650989SNeel Natu static void
150ec650989SNeel Natu printflag(uint64_t var, uint64_t mask, const char *name)
151ec650989SNeel Natu {
152ec650989SNeel Natu 
153ec650989SNeel Natu 	if (var & mask) {
154ec650989SNeel Natu 		printf("%c%s", pf_sep, name);
155ec650989SNeel Natu 		pf_sep = ',';
156ec650989SNeel Natu 	}
157ec650989SNeel Natu }
158ec650989SNeel Natu 
159e1e9a4bfSMitsuru IWASAKI static void
160e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
161e1e9a4bfSMitsuru IWASAKI {
162e1e9a4bfSMitsuru IWASAKI 	int	c;
163e1e9a4bfSMitsuru IWASAKI 
164e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
165e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
166e1e9a4bfSMitsuru IWASAKI 		length--;
167e1e9a4bfSMitsuru IWASAKI 
168e1e9a4bfSMitsuru IWASAKI 	while (length--) {
169e1e9a4bfSMitsuru IWASAKI 		c = *s++;
170e1e9a4bfSMitsuru IWASAKI 		putchar(c);
171e1e9a4bfSMitsuru IWASAKI 	}
172e1e9a4bfSMitsuru IWASAKI }
173e1e9a4bfSMitsuru IWASAKI 
174e1e9a4bfSMitsuru IWASAKI static void
175986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1768e6a8737SNate Lawson {
177986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1788e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
1797d369c6eSJung-uk Kim 		if (gas->BitWidth <= 32)
1807d369c6eSJung-uk Kim 			printf("0x%08x:%u[%u] (Memory)",
1817d369c6eSJung-uk Kim 			    (u_int)gas->Address, gas->BitOffset,
1827d369c6eSJung-uk Kim 			    gas->BitWidth);
1837d369c6eSJung-uk Kim 		else
1847d369c6eSJung-uk Kim 			printf("0x%016jx:%u[%u] (Memory)",
1857d369c6eSJung-uk Kim 			    (uintmax_t)gas->Address, gas->BitOffset,
1867d369c6eSJung-uk Kim 			    gas->BitWidth);
1878e6a8737SNate Lawson 		break;
1888e6a8737SNate Lawson 	case ACPI_GAS_IO:
1897d369c6eSJung-uk Kim 		printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
190986dffafSJohn Baldwin 		    gas->BitOffset, gas->BitWidth);
1918e6a8737SNate Lawson 		break;
1928e6a8737SNate Lawson 	case ACPI_GAS_PCI:
193986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
194986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
195986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1968e6a8737SNate Lawson 		break;
1978e6a8737SNate Lawson 	/* XXX How to handle these below? */
1988e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
199986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
200986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
2018e6a8737SNate Lawson 		break;
2028e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
203986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
204986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
2058e6a8737SNate Lawson 		break;
206986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
207986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
208986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
2098e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
2108e6a8737SNate Lawson 	default:
2117d369c6eSJung-uk Kim 		printf("0x%016jx (?)", (uintmax_t)gas->Address);
2128e6a8737SNate Lawson 		break;
2138e6a8737SNate Lawson 	}
2148e6a8737SNate Lawson }
2158e6a8737SNate Lawson 
216c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
217c2962974SNate Lawson static int
218986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
219e1e9a4bfSMitsuru IWASAKI {
220c2962974SNate Lawson 	int fadt_revision;
221e1e9a4bfSMitsuru IWASAKI 
222c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
223c83f0f99SNate Lawson 	if (addr_size == 8) {
224c83f0f99SNate Lawson 		fadt_revision = 2;
2258e6a8737SNate Lawson 
226773b6454SNate Lawson 		/*
227c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
228c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
229c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
230c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
231c83f0f99SNate Lawson 		 * version for all subsequent tables.
232773b6454SNate Lawson 		 */
233986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
234986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
235c83f0f99SNate Lawson 			fadt_revision = 1;
236c2962974SNate Lawson 	} else
237c83f0f99SNate Lawson 		fadt_revision = 1;
238c2962974SNate Lawson 	return (fadt_revision);
239c83f0f99SNate Lawson }
240c2962974SNate Lawson 
241c2962974SNate Lawson static void
242986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
243c2962974SNate Lawson {
244986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
245986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
246986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
247c2962974SNate Lawson 	int		fadt_revision;
248c2962974SNate Lawson 
249986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2502177d4e6SNate Lawson 	acpi_print_fadt(sdp);
251c83f0f99SNate Lawson 
252c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
253c83f0f99SNate Lawson 	if (fadt_revision == 1)
254986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
255773b6454SNate Lawson 	else
256986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
257986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2588e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2598e6a8737SNate Lawson 	acpi_print_facs(facs);
2608e6a8737SNate Lawson 
261c83f0f99SNate Lawson 	if (fadt_revision == 1)
262986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
263773b6454SNate Lawson 	else
264986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
265986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
266945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
267945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
268c62f1cccSMitsuru IWASAKI }
269c62f1cccSMitsuru IWASAKI 
270c62f1cccSMitsuru IWASAKI static void
271986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
272986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
273986dffafSJohn Baldwin {
274986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
275986dffafSJohn Baldwin 	char *end;
276986dffafSJohn Baldwin 
277986dffafSJohn Baldwin 	subtable = first;
278986dffafSJohn Baldwin 	end = (char *)table + table->Length;
279986dffafSJohn Baldwin 	while ((char *)subtable < end) {
280986dffafSJohn Baldwin 		printf("\n");
281f5d0a8f7SEd Maste 		if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
282f5d0a8f7SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
283f5d0a8f7SEd Maste 			return;
284f5d0a8f7SEd Maste 		}
285986dffafSJohn Baldwin 		action(subtable);
286986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
287986dffafSJohn Baldwin 		    subtable->Length);
288986dffafSJohn Baldwin 	}
289986dffafSJohn Baldwin }
290986dffafSJohn Baldwin 
291986dffafSJohn Baldwin static void
292340c0022SEd Maste acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
293340c0022SEd Maste     void (*action)(ACPI_NFIT_HEADER *))
294340c0022SEd Maste {
295340c0022SEd Maste 	ACPI_NFIT_HEADER *subtable;
296340c0022SEd Maste 	char *end;
297340c0022SEd Maste 
298340c0022SEd Maste 	subtable = first;
299340c0022SEd Maste 	end = (char *)table + table->Length;
300340c0022SEd Maste 	while ((char *)subtable < end) {
301340c0022SEd Maste 		printf("\n");
302340c0022SEd Maste 		if (subtable->Length < sizeof(ACPI_NFIT_HEADER)) {
303340c0022SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
304340c0022SEd Maste 			return;
305340c0022SEd Maste 		}
306340c0022SEd Maste 		action(subtable);
307340c0022SEd Maste 		subtable = (ACPI_NFIT_HEADER *)((char *)subtable +
308340c0022SEd Maste 		    subtable->Length);
309340c0022SEd Maste 	}
310340c0022SEd Maste }
311340c0022SEd Maste 
312340c0022SEd Maste static void
3130a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
3140a473124SJohn Baldwin {
3150a473124SJohn Baldwin 
3160a473124SJohn Baldwin 	printf("\tACPI CPU=");
3170a473124SJohn Baldwin 	if (cpu_id == 0xff)
3180a473124SJohn Baldwin 		printf("ALL\n");
3190a473124SJohn Baldwin 	else
3200a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
3210a473124SJohn Baldwin }
3220a473124SJohn Baldwin 
3230a473124SJohn Baldwin static void
324986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
3250a473124SJohn Baldwin {
326986dffafSJohn Baldwin 
327986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
328986dffafSJohn Baldwin 	if (uid_string != NULL)
329986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
330986dffafSJohn Baldwin 	printf("\n");
331986dffafSJohn Baldwin }
332986dffafSJohn Baldwin 
333986dffafSJohn Baldwin static void
334986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
335986dffafSJohn Baldwin {
336986dffafSJohn Baldwin 
3370a473124SJohn Baldwin 	printf("\tFlags={");
338986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
3390a473124SJohn Baldwin 		printf("ENABLED");
3400a473124SJohn Baldwin 	else
3410a473124SJohn Baldwin 		printf("DISABLED");
3420a473124SJohn Baldwin 	printf("}\n");
343986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3440a473124SJohn Baldwin }
3450a473124SJohn Baldwin 
3460a473124SJohn Baldwin static void
347986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
3480a473124SJohn Baldwin {
349986dffafSJohn Baldwin 
350986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3510a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
352986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
3530a473124SJohn Baldwin }
3540a473124SJohn Baldwin 
3550a473124SJohn Baldwin static void
356986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
3570a473124SJohn Baldwin {
3580a473124SJohn Baldwin 
3590a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
360986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
361986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
3620a473124SJohn Baldwin 		printf("conforming");
3630a473124SJohn Baldwin 		break;
364986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3650a473124SJohn Baldwin 		printf("active-hi");
3660a473124SJohn Baldwin 		break;
367986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3680a473124SJohn Baldwin 		printf("active-lo");
3690a473124SJohn Baldwin 		break;
3700a473124SJohn Baldwin 	default:
371986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3720a473124SJohn Baldwin 		break;
3730a473124SJohn Baldwin 	}
3740a473124SJohn Baldwin 	printf(", Trigger=");
375986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
376986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3770a473124SJohn Baldwin 		printf("conforming");
3780a473124SJohn Baldwin 		break;
379986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3800a473124SJohn Baldwin 		printf("edge");
3810a473124SJohn Baldwin 		break;
382986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3830a473124SJohn Baldwin 		printf("level");
3840a473124SJohn Baldwin 		break;
3850a473124SJohn Baldwin 	default:
386986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3870a473124SJohn Baldwin 	}
3880a473124SJohn Baldwin 	printf("}\n");
3890a473124SJohn Baldwin }
3900a473124SJohn Baldwin 
3910a473124SJohn Baldwin static void
3922b2b1f42SAndrew Turner acpi_print_gicc_flags(uint32_t flags)
3932b2b1f42SAndrew Turner {
3942b2b1f42SAndrew Turner 
3952b2b1f42SAndrew Turner 	printf("\tFlags={Performance intr=");
3962b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
3972b2b1f42SAndrew Turner 		printf("edge");
3982b2b1f42SAndrew Turner 	else
3992b2b1f42SAndrew Turner 		printf("level");
4002b2b1f42SAndrew Turner 	printf(", VGIC intr=");
4012b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_VGIC_IRQ_MODE)
4022b2b1f42SAndrew Turner 		printf("edge");
4032b2b1f42SAndrew Turner 	else
4042b2b1f42SAndrew Turner 		printf("level");
4052b2b1f42SAndrew Turner 	printf("}\n");
4062b2b1f42SAndrew Turner }
4072b2b1f42SAndrew Turner 
4082b2b1f42SAndrew Turner static void
409986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
4100a473124SJohn Baldwin {
4110a473124SJohn Baldwin 
412986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
413986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
414986dffafSJohn Baldwin }
415986dffafSJohn Baldwin 
416986dffafSJohn Baldwin static void
417986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
418986dffafSJohn Baldwin {
419986dffafSJohn Baldwin 
420986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
4210a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
4220a473124SJohn Baldwin }
4230a473124SJohn Baldwin 
42427941afaSEd Maste static const char *apic_types[] = {
42527941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
42627941afaSEd Maste     [ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
42727941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
42827941afaSEd Maste     [ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
42927941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
43027941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
43127941afaSEd Maste     [ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
43227941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
43327941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
43427941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
43527941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
43627941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
43727941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
43827941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
43927941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
44027941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
44127941afaSEd Maste };
44227941afaSEd Maste 
443bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
4440a473124SJohn Baldwin 					    "Corrected Platform Error" };
4450a473124SJohn Baldwin 
4460a473124SJohn Baldwin static void
447986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
4480a473124SJohn Baldwin {
449986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
450986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
451986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
452986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
453986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
454986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
455986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
456986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
457986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
458986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
459986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
4602b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_INTERRUPT *gicc;
4612b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
4622b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
4632b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_TRANSLATOR *gict;
4640a473124SJohn Baldwin 
465c86932b6SMarcelo Araujo 	if (mp->Type < nitems(apic_types))
466986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
467a0333ad1SJohn Baldwin 	else
468986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
469986dffafSJohn Baldwin 	switch (mp->Type) {
470986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
471986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
472986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
473986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4740a473124SJohn Baldwin 		break;
475986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
476986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
477986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
478986dffafSJohn Baldwin 		    ioapic->Address);
4790a473124SJohn Baldwin 		break;
480986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
481986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
482986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
483986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
484986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
4850a473124SJohn Baldwin 		break;
486986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
487986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
488986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
4890a473124SJohn Baldwin 		break;
490986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
491986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
492986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
493986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
4940a473124SJohn Baldwin 		break;
495986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
496986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
497945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
498986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
4990a473124SJohn Baldwin 		break;
500986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
501986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
502986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
503986dffafSJohn Baldwin 		    iosapic->Address);
5040a473124SJohn Baldwin 		break;
505986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
506986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
507986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
508986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
509986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
510986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
511986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
5120a473124SJohn Baldwin 		break;
513986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
514986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
515c86932b6SMarcelo Araujo 		if (isrc->Type < nitems(platform_int_types))
516986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
517986dffafSJohn Baldwin 		else
518986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
519986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
520986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
521986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
522986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
523986dffafSJohn Baldwin 		break;
524986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
525986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
526986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
527986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
528986dffafSJohn Baldwin 		break;
529986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
530986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
531986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
532986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
5330a473124SJohn Baldwin 		break;
5342b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
5352b2b1f42SAndrew Turner 		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
5362b2b1f42SAndrew Turner 		acpi_print_cpu_uid(gicc->Uid, NULL);
5372b2b1f42SAndrew Turner 		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
5382b2b1f42SAndrew Turner 		acpi_print_gicc_flags(gicc->Flags);
5392b2b1f42SAndrew Turner 		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
5402b2b1f42SAndrew Turner 		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
5412b2b1f42SAndrew Turner 		printf("\tParked ADDR=%016jx\n",
5422b2b1f42SAndrew Turner 		    (uintmax_t)gicc->ParkedAddress);
5432b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
5442b2b1f42SAndrew Turner 		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
5452b2b1f42SAndrew Turner 		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
5462b2b1f42SAndrew Turner 		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
5472b2b1f42SAndrew Turner 		printf("\tGICR ADDR=%016jx\n",
5482b2b1f42SAndrew Turner 		    (uintmax_t)gicc->GicrBaseAddress);
5492b2b1f42SAndrew Turner 		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
5502b2b1f42SAndrew Turner 		printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass);
5512b2b1f42SAndrew Turner 		break;
5522b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
5532b2b1f42SAndrew Turner 		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
5542b2b1f42SAndrew Turner 		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
5552b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
5562b2b1f42SAndrew Turner 		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
5572b2b1f42SAndrew Turner 		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
5582b2b1f42SAndrew Turner 		break;
5592b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
5602b2b1f42SAndrew Turner 		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
5612b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
5622b2b1f42SAndrew Turner 		printf("\tLength=%08x\n", gicr->Length);
5632b2b1f42SAndrew Turner 		break;
5642b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
5652b2b1f42SAndrew Turner 		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
5662b2b1f42SAndrew Turner 		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
5672b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
5682b2b1f42SAndrew Turner 		break;
5690a473124SJohn Baldwin 	}
5700a473124SJohn Baldwin }
5710a473124SJohn Baldwin 
5720a473124SJohn Baldwin static void
573986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
5740a473124SJohn Baldwin {
575986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
5760a473124SJohn Baldwin 
577773b6454SNate Lawson 	printf(BEGIN_COMMENT);
578773b6454SNate Lawson 	acpi_print_sdt(sdp);
579986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
580986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
5810a473124SJohn Baldwin 	printf("\tFlags={");
582986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
5830a473124SJohn Baldwin 		printf("PC-AT");
5840a473124SJohn Baldwin 	printf("}\n");
585986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
5860a473124SJohn Baldwin 	printf(END_COMMENT);
5870a473124SJohn Baldwin }
5880a473124SJohn Baldwin 
5890a473124SJohn Baldwin static void
590986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
59179d7565cSPeter Wemm {
592986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
59379d7565cSPeter Wemm 
594773b6454SNate Lawson 	printf(BEGIN_COMMENT);
595773b6454SNate Lawson 	acpi_print_sdt(sdp);
596986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
597986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
59887f9f09aSTakanori Watanabe 	printf("\tADDR=");
599986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
600986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
601986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
602986dffafSJohn Baldwin 	    8);
603986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
604986dffafSJohn Baldwin 	    1 : 0);
60579d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
606986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
60779d7565cSPeter Wemm 		printf("TRUE}\n");
60879d7565cSPeter Wemm 	else
60979d7565cSPeter Wemm 		printf("FALSE}\n");
610986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
611986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
6129785e979SNeel Natu 	printf("\tFlags=0x%02x\n", hpet->Flags);
61379d7565cSPeter Wemm 	printf(END_COMMENT);
61479d7565cSPeter Wemm }
61579d7565cSPeter Wemm 
61679d7565cSPeter Wemm static void
617986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
61855d7ff9eSNate Lawson {
619986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
62055d7ff9eSNate Lawson 
62155d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
62255d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
623986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
62455d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
625986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
62655d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
627986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
628986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
629986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
630986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
63155d7ff9eSNate Lawson 	printf(END_COMMENT);
63255d7ff9eSNate Lawson }
63355d7ff9eSNate Lawson 
63455d7ff9eSNate Lawson static void
635986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
636a47e681bSScott Long {
637986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
638986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
639986dffafSJohn Baldwin 	u_int i, entries;
640a47e681bSScott Long 
641a47e681bSScott Long 	printf(BEGIN_COMMENT);
642a47e681bSScott Long 	acpi_print_sdt(sdp);
643986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
644986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
645986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
646986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
647986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
648a47e681bSScott Long 		printf("\n");
6490c10b85aSJung-uk Kim 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
650986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
651986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
652986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
653a47e681bSScott Long 	}
654a47e681bSScott Long 	printf(END_COMMENT);
655a47e681bSScott Long }
656a47e681bSScott Long 
657a47e681bSScott Long static void
65833866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
65933866658SJohn Baldwin {
66033866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
66133866658SJohn Baldwin 	UINT64 i, j;
66233866658SJohn Baldwin 
66333866658SJohn Baldwin 	printf(BEGIN_COMMENT);
66433866658SJohn Baldwin 	acpi_print_sdt(sdp);
66533866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
6660c10b85aSJung-uk Kim 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
66733866658SJohn Baldwin 	printf("\n\t      ");
66833866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
6690c10b85aSJung-uk Kim 		printf(" %3ju", (uintmax_t)i);
67033866658SJohn Baldwin 	printf("\n\t     +");
67133866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
67233866658SJohn Baldwin 		printf("----");
67333866658SJohn Baldwin 	printf("\n");
67433866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
6750c10b85aSJung-uk Kim 		printf("\t %3ju |", (uintmax_t)i);
67633866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
67733866658SJohn Baldwin 			printf(" %3d",
67833866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
67933866658SJohn Baldwin 		printf("\n");
68033866658SJohn Baldwin 	}
68133866658SJohn Baldwin 	printf(END_COMMENT);
68233866658SJohn Baldwin }
68333866658SJohn Baldwin 
68433866658SJohn Baldwin static void
685ed26c389SScott Long acpi_handle_wddt(ACPI_TABLE_HEADER *sdp)
686ed26c389SScott Long {
687ed26c389SScott Long 	ACPI_TABLE_WDDT *wddt;
688ed26c389SScott Long 
689ed26c389SScott Long 	printf(BEGIN_COMMENT);
690ed26c389SScott Long 	acpi_print_sdt(sdp);
691ed26c389SScott Long 	wddt = (ACPI_TABLE_WDDT *)sdp;
692ed26c389SScott Long 	printf("\tSpecVersion=0x%04x, TableVersion=0x%04x\n",
693ed26c389SScott Long 	    wddt->SpecVersion, wddt->TableVersion);
694ed26c389SScott Long 	printf("\tPciVendorId=0x%04x, Address=", wddt->PciVendorId);
695ed26c389SScott Long 	acpi_print_gas(&wddt->Address);
696ed26c389SScott Long 	printf("\n\tMaxCount=%u, MinCount=%u, Period=%ums\n",
697ed26c389SScott Long 	    wddt->MaxCount, wddt->MinCount, wddt->Period);
698ed26c389SScott Long 
699ed26c389SScott Long #define	PRINTFLAG(var, flag)	printflag((var), ACPI_WDDT_## flag, #flag)
700ed26c389SScott Long 	printf("\tStatus=");
701ed26c389SScott Long 	PRINTFLAG(wddt->Status, AVAILABLE);
702ed26c389SScott Long 	PRINTFLAG(wddt->Status, ACTIVE);
703ed26c389SScott Long 	PRINTFLAG(wddt->Status, TCO_OS_OWNED);
704ed26c389SScott Long 	PRINTFLAG(wddt->Status, USER_RESET);
705ed26c389SScott Long 	PRINTFLAG(wddt->Status, WDT_RESET);
706ed26c389SScott Long 	PRINTFLAG(wddt->Status, POWER_FAIL);
707ed26c389SScott Long 	PRINTFLAG(wddt->Status, UNKNOWN_RESET);
708ed26c389SScott Long 	PRINTFLAG_END();
709ed26c389SScott Long 	printf("\tCapability=");
710ed26c389SScott Long 	PRINTFLAG(wddt->Capability, AUTO_RESET);
711ed26c389SScott Long 	PRINTFLAG(wddt->Capability, ALERT_SUPPORT);
712ed26c389SScott Long 	PRINTFLAG_END();
713ed26c389SScott Long #undef PRINTFLAG
714ed26c389SScott Long 
715ed26c389SScott Long 	printf(END_COMMENT);
716ed26c389SScott Long }
717ed26c389SScott Long 
718ed26c389SScott Long static void
719a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
720a0333ad1SJohn Baldwin     uint32_t flags)
721a0333ad1SJohn Baldwin {
722a0333ad1SJohn Baldwin 
723a0333ad1SJohn Baldwin 	printf("\tFlags={");
724a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
725a0333ad1SJohn Baldwin 		printf("ENABLED");
726a0333ad1SJohn Baldwin 	else
727a0333ad1SJohn Baldwin 		printf("DISABLED");
728a0333ad1SJohn Baldwin 	printf("}\n");
729a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
730a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
731a0333ad1SJohn Baldwin }
732a0333ad1SJohn Baldwin 
733c031c93bSTakanori Watanabe static char *
734c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
735c031c93bSTakanori Watanabe {
736c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
737c031c93bSTakanori Watanabe 	char *eventname = NULL;
738c031c93bSTakanori Watanabe 
739c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
740c031c93bSTakanori Watanabe 
741c031c93bSTakanori Watanabe 	switch(event->event_type) {
742c031c93bSTakanori Watanabe 	case PREBOOT:
743c031c93bSTakanori Watanabe 	case POST_CODE:
744c031c93bSTakanori Watanabe 	case UNUSED:
745c031c93bSTakanori Watanabe 	case NO_ACTION:
746c031c93bSTakanori Watanabe 	case SEPARATOR:
747c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
748c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
749c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
750c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
751c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
752c031c93bSTakanori Watanabe 	case COMPACT_HASH:
753c031c93bSTakanori Watanabe 	case IPL:
754c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
755c031c93bSTakanori Watanabe 	case NONHOST_CODE:
756c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
757c031c93bSTakanori Watanabe 	case NONHOST_INFO:
758c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
759c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
760c031c93bSTakanori Watanabe 		break;
761c031c93bSTakanori Watanabe 
762c031c93bSTakanori Watanabe 	case ACTION:
763c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
764c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
765c031c93bSTakanori Watanabe 		break;
766c031c93bSTakanori Watanabe 
767c031c93bSTakanori Watanabe 	case EVENT_TAG:
768c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
769c031c93bSTakanori Watanabe 		case SMBIOS:
770c031c93bSTakanori Watanabe 		case BIS_CERT:
771c031c93bSTakanori Watanabe 		case CMOS:
772c031c93bSTakanori Watanabe 		case NVRAM:
773c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
774c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
775c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
776c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
777c031c93bSTakanori Watanabe 		case ESCD:
778c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
779c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
780c031c93bSTakanori Watanabe 		case POST_CONTENTS:
781c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
782c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
783c031c93bSTakanori Watanabe 			break;
784c031c93bSTakanori Watanabe 
785c031c93bSTakanori Watanabe 		default:
786c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
787c031c93bSTakanori Watanabe 			    pc_event->event_id);
788c031c93bSTakanori Watanabe 			break;
789c031c93bSTakanori Watanabe 		}
790c031c93bSTakanori Watanabe 		break;
791c031c93bSTakanori Watanabe 
792c031c93bSTakanori Watanabe 	default:
793c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
794c031c93bSTakanori Watanabe 		break;
795c031c93bSTakanori Watanabe 	}
796c031c93bSTakanori Watanabe 
797c031c93bSTakanori Watanabe 	return eventname;
798c031c93bSTakanori Watanabe }
799c031c93bSTakanori Watanabe 
800c031c93bSTakanori Watanabe static void
801c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
802c031c93bSTakanori Watanabe {
803c031c93bSTakanori Watanabe 	int i;
804c031c93bSTakanori Watanabe 	char *eventname;
805c031c93bSTakanori Watanabe 
806c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
807c031c93bSTakanori Watanabe 
808c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
809c031c93bSTakanori Watanabe 	printf(" 0x");
810c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
811c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
812c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
813c031c93bSTakanori Watanabe 
814c031c93bSTakanori Watanabe 	free(eventname);
815c031c93bSTakanori Watanabe }
816c031c93bSTakanori Watanabe 
817c031c93bSTakanori Watanabe static void
818c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
819c031c93bSTakanori Watanabe {
820c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
821c031c93bSTakanori Watanabe 	struct TCPAevent *event;
822977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
823c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
824c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
825c031c93bSTakanori Watanabe 
826c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
827c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
828c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
829c031c93bSTakanori Watanabe 
830c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
831c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
832c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
833c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
834c031c93bSTakanori Watanabe 		break;
835c031c93bSTakanori Watanabe 
836c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
837c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
838c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
839c031c93bSTakanori Watanabe 		break;
840c031c93bSTakanori Watanabe 
841c031c93bSTakanori Watanabe 	default:
842c031c93bSTakanori Watanabe 		printf("XXX");
843c031c93bSTakanori Watanabe 		printf(END_COMMENT);
844c031c93bSTakanori Watanabe 		return;
845c031c93bSTakanori Watanabe 	}
8460e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
847c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
848c031c93bSTakanori Watanabe 
849c031c93bSTakanori Watanabe 	if (len == 0) {
850c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
851c031c93bSTakanori Watanabe 		printf(END_COMMENT);
852c031c93bSTakanori Watanabe 		return;
853c031c93bSTakanori Watanabe 	}
8542ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
8552ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
8562ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
8572ef23c6dSTakanori Watanabe 		return;
8582ef23c6dSTakanori Watanabe 	}
859c031c93bSTakanori Watanabe 
860c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
861c031c93bSTakanori Watanabe 	vend = vaddr + len;
862c031c93bSTakanori Watanabe 
863c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
8642ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
8652ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
866c031c93bSTakanori Watanabe 			break;
8670e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
868c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
869c031c93bSTakanori Watanabe 			break;
8702ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
8712ef23c6dSTakanori Watanabe 			break;
872c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
873c031c93bSTakanori Watanabe 			break;
874c031c93bSTakanori Watanabe #if 0
875c031c93bSTakanori Watanabe 		{
876c031c93bSTakanori Watanabe 		unsigned int i, j, k;
877c031c93bSTakanori Watanabe 
878c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
879c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
880c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
881c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
882c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
883c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
884c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
885c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
886c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
887c031c93bSTakanori Watanabe 				j = i + 1;
888c031c93bSTakanori Watanabe 			}
889c031c93bSTakanori Watanabe 		}
890c031c93bSTakanori Watanabe 		printf("\n"); }
891c031c93bSTakanori Watanabe #endif
892c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
893c031c93bSTakanori Watanabe 
894c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
895c031c93bSTakanori Watanabe 	}
896c031c93bSTakanori Watanabe 
897c031c93bSTakanori Watanabe 	printf(END_COMMENT);
898c031c93bSTakanori Watanabe }
899c031c93bSTakanori Watanabe 
900ec650989SNeel Natu static const char *
901ec650989SNeel Natu devscope_type2str(int type)
902ec650989SNeel Natu {
903ec650989SNeel Natu 	static char typebuf[16];
904ec650989SNeel Natu 
905ec650989SNeel Natu 	switch (type) {
906ec650989SNeel Natu 	case 1:
907ec650989SNeel Natu 		return ("PCI Endpoint Device");
908ec650989SNeel Natu 	case 2:
909ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
910ec650989SNeel Natu 	case 3:
911ec650989SNeel Natu 		return ("IOAPIC");
912ec650989SNeel Natu 	case 4:
913ec650989SNeel Natu 		return ("HPET");
914ec650989SNeel Natu 	default:
915ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
916ec650989SNeel Natu 		return (typebuf);
917ec650989SNeel Natu 	}
918ec650989SNeel Natu }
919ec650989SNeel Natu 
920ec650989SNeel Natu static int
921ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
922ec650989SNeel Natu {
923ec650989SNeel Natu 	char sep;
924ec650989SNeel Natu 	int pathlen;
925ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
926ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
927ec650989SNeel Natu 
928ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
929ec650989SNeel Natu 		return (-1);
930ec650989SNeel Natu 
931ec650989SNeel Natu 	if (remaining < devscope->Length)
932ec650989SNeel Natu 		return (-1);
933ec650989SNeel Natu 
934ec650989SNeel Natu 	printf("\n");
935ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
936ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
937ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
938ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
939ec650989SNeel Natu 
940ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
941ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
942ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
943ec650989SNeel Natu 	if (path < pathend) {
944ec650989SNeel Natu 		sep = '{';
945ec650989SNeel Natu 		printf("\t\tPath=");
946ec650989SNeel Natu 		do {
947ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
948ec650989SNeel Natu 			sep=',';
949ec650989SNeel Natu 			path++;
950ec650989SNeel Natu 		} while (path < pathend);
951ec650989SNeel Natu 		printf("}\n");
952ec650989SNeel Natu 	}
953ec650989SNeel Natu 
954ec650989SNeel Natu 	return (devscope->Length);
955ec650989SNeel Natu }
956ec650989SNeel Natu 
957ec650989SNeel Natu static void
958ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
959ec650989SNeel Natu {
960ec650989SNeel Natu 	char *cp;
961ec650989SNeel Natu 	int remaining, consumed;
962ec650989SNeel Natu 
963ec650989SNeel Natu 	printf("\n");
964ec650989SNeel Natu 	printf("\tType=DRHD\n");
965ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
966ec650989SNeel Natu 
967ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
968ec650989SNeel Natu 
969ec650989SNeel Natu 	printf("\tFlags=");
970ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
971ec650989SNeel Natu 	PRINTFLAG_END();
972ec650989SNeel Natu 
973ec650989SNeel Natu #undef PRINTFLAG
974ec650989SNeel Natu 
975ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
9767d369c6eSJung-uk Kim 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
977ec650989SNeel Natu 
978ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
979ec650989SNeel Natu 	if (remaining > 0)
980ec650989SNeel Natu 		printf("\tDevice Scope:");
981ec650989SNeel Natu 	while (remaining > 0) {
982ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
983ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
984ec650989SNeel Natu 		if (consumed <= 0)
985ec650989SNeel Natu 			break;
986ec650989SNeel Natu 		else
987ec650989SNeel Natu 			remaining -= consumed;
988ec650989SNeel Natu 	}
989ec650989SNeel Natu }
990ec650989SNeel Natu 
991ec650989SNeel Natu static void
992ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
993ec650989SNeel Natu {
994ec650989SNeel Natu 	char *cp;
995ec650989SNeel Natu 	int remaining, consumed;
996ec650989SNeel Natu 
997ec650989SNeel Natu 	printf("\n");
998ec650989SNeel Natu 	printf("\tType=RMRR\n");
999ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
1000ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
10017d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
10027d369c6eSJung-uk Kim 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
1003ec650989SNeel Natu 
1004ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
1005ec650989SNeel Natu 	if (remaining > 0)
1006ec650989SNeel Natu 		printf("\tDevice Scope:");
1007ec650989SNeel Natu 	while (remaining > 0) {
1008ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
1009ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1010ec650989SNeel Natu 		if (consumed <= 0)
1011ec650989SNeel Natu 			break;
1012ec650989SNeel Natu 		else
1013ec650989SNeel Natu 			remaining -= consumed;
1014ec650989SNeel Natu 	}
1015ec650989SNeel Natu }
1016ec650989SNeel Natu 
1017ec650989SNeel Natu static void
1018ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
1019ec650989SNeel Natu {
1020ec650989SNeel Natu 	char *cp;
1021ec650989SNeel Natu 	int remaining, consumed;
1022ec650989SNeel Natu 
1023ec650989SNeel Natu 	printf("\n");
1024ec650989SNeel Natu 	printf("\tType=ATSR\n");
1025ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
1026ec650989SNeel Natu 
1027ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1028ec650989SNeel Natu 
1029ec650989SNeel Natu 	printf("\tFlags=");
1030ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
1031ec650989SNeel Natu 	PRINTFLAG_END();
1032ec650989SNeel Natu 
1033ec650989SNeel Natu #undef PRINTFLAG
1034ec650989SNeel Natu 
1035ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
1036ec650989SNeel Natu 
1037ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
1038ec650989SNeel Natu 	if (remaining > 0)
1039ec650989SNeel Natu 		printf("\tDevice Scope:");
1040ec650989SNeel Natu 	while (remaining > 0) {
1041ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
1042ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1043ec650989SNeel Natu 		if (consumed <= 0)
1044ec650989SNeel Natu 			break;
1045ec650989SNeel Natu 		else
1046ec650989SNeel Natu 			remaining -= consumed;
1047ec650989SNeel Natu 	}
1048ec650989SNeel Natu }
1049ec650989SNeel Natu 
1050ec650989SNeel Natu static void
1051ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
1052ec650989SNeel Natu {
1053ec650989SNeel Natu 
1054ec650989SNeel Natu 	printf("\n");
1055ec650989SNeel Natu 	printf("\tType=RHSA\n");
1056ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
10577d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
1058ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
1059ec650989SNeel Natu }
1060ec650989SNeel Natu 
1061ec650989SNeel Natu static int
1062ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
1063ec650989SNeel Natu {
1064ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
1065ec650989SNeel Natu 
1066ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
1067ec650989SNeel Natu 		return (-1);
1068ec650989SNeel Natu 
1069ec650989SNeel Natu 	if (remaining < hdr->Length)
1070ec650989SNeel Natu 		return (-1);
1071ec650989SNeel Natu 
1072ec650989SNeel Natu 	switch (hdr->Type) {
1073ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1074ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
1075ec650989SNeel Natu 		break;
1076ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1077ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
1078ec650989SNeel Natu 		break;
1079313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_ROOT_ATS:
1080ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
1081ec650989SNeel Natu 		break;
1082313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1083ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
1084ec650989SNeel Natu 		break;
1085ec650989SNeel Natu 	default:
1086ec650989SNeel Natu 		printf("\n");
1087ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
1088ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
1089ec650989SNeel Natu 		break;
1090ec650989SNeel Natu 	}
1091ec650989SNeel Natu 	return (hdr->Length);
1092ec650989SNeel Natu }
1093ec650989SNeel Natu 
1094ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1095ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
1096ec650989SNeel Natu #endif
1097ec650989SNeel Natu 
1098ec650989SNeel Natu static void
1099ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1100ec650989SNeel Natu {
1101ec650989SNeel Natu 	char *cp;
1102ec650989SNeel Natu 	int remaining, consumed;
1103ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
1104ec650989SNeel Natu 
1105ec650989SNeel Natu 	printf(BEGIN_COMMENT);
1106ec650989SNeel Natu 	acpi_print_sdt(sdp);
1107ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
1108ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
1109ec650989SNeel Natu 
1110ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1111ec650989SNeel Natu 
1112ec650989SNeel Natu 	printf("\tFlags=");
1113ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
1114ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1115ec650989SNeel Natu 	PRINTFLAG_END();
1116ec650989SNeel Natu 
1117ec650989SNeel Natu #undef PRINTFLAG
1118ec650989SNeel Natu 
1119ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1120ec650989SNeel Natu 	while (remaining > 0) {
1121ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
1122ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1123ec650989SNeel Natu 		if (consumed <= 0)
1124ec650989SNeel Natu 			break;
1125ec650989SNeel Natu 		else
1126ec650989SNeel Natu 			remaining -= consumed;
1127ec650989SNeel Natu 	}
1128ec650989SNeel Natu 
1129ec650989SNeel Natu 	printf(END_COMMENT);
1130ec650989SNeel Natu }
1131ec650989SNeel Natu 
1132a0333ad1SJohn Baldwin static void
1133986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1134a0333ad1SJohn Baldwin {
1135a0333ad1SJohn Baldwin 
1136a0333ad1SJohn Baldwin 	printf("\tFlags={");
1137986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1138a0333ad1SJohn Baldwin 		printf("ENABLED");
1139a0333ad1SJohn Baldwin 	else
1140a0333ad1SJohn Baldwin 		printf("DISABLED");
1141986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1142a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1143986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1144a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1145a0333ad1SJohn Baldwin 	printf("}\n");
1146986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1147986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1148986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1149a0333ad1SJohn Baldwin }
1150a0333ad1SJohn Baldwin 
115127941afaSEd Maste static const char *srat_types[] = {
115227941afaSEd Maste     [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
115327941afaSEd Maste     [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
115427941afaSEd Maste     [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
1155cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
1156cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GIC_ITS_AFFINITY] = "GIC ITS",
115727941afaSEd Maste };
1158a0333ad1SJohn Baldwin 
1159a0333ad1SJohn Baldwin static void
1160986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1161a0333ad1SJohn Baldwin {
1162986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1163986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
11642b2b1f42SAndrew Turner 	ACPI_SRAT_GICC_AFFINITY *gic;
1165a0333ad1SJohn Baldwin 
1166c86932b6SMarcelo Araujo 	if (srat->Type < nitems(srat_types))
1167986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1168a0333ad1SJohn Baldwin 	else
1169986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1170986dffafSJohn Baldwin 	switch (srat->Type) {
1171a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1172986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1173986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1174986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1175986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1176986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1177986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1178a0333ad1SJohn Baldwin 		break;
1179a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1180986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1181a0333ad1SJohn Baldwin 		break;
1182a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1183986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1184986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1185986dffafSJohn Baldwin 		    x2apic->Flags);
1186a0333ad1SJohn Baldwin 		break;
11872b2b1f42SAndrew Turner 	case ACPI_SRAT_TYPE_GICC_AFFINITY:
11882b2b1f42SAndrew Turner 		gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
11892b2b1f42SAndrew Turner 		acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
11902b2b1f42SAndrew Turner 		    gic->Flags);
11912b2b1f42SAndrew Turner 		break;
1192a0333ad1SJohn Baldwin 	}
1193a0333ad1SJohn Baldwin }
1194a0333ad1SJohn Baldwin 
1195a0333ad1SJohn Baldwin static void
1196986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1197a0333ad1SJohn Baldwin {
1198986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1199a0333ad1SJohn Baldwin 
1200a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1201a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1202986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1203986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1204986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1205a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1206a0333ad1SJohn Baldwin }
1207a0333ad1SJohn Baldwin 
1208340c0022SEd Maste static const char *nfit_types[] = {
1209340c0022SEd Maste     [ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
1210340c0022SEd Maste     [ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
1211340c0022SEd Maste     [ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
1212340c0022SEd Maste     [ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
1213340c0022SEd Maste     [ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
1214340c0022SEd Maste     [ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
1215340c0022SEd Maste     [ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address"
1216340c0022SEd Maste };
1217340c0022SEd Maste 
1218340c0022SEd Maste 
1219340c0022SEd Maste static void
1220340c0022SEd Maste acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
1221340c0022SEd Maste {
1222340c0022SEd Maste 	char *uuidstr;
1223340c0022SEd Maste 	uint32_t status;
1224340c0022SEd Maste 
1225340c0022SEd Maste 	ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
1226340c0022SEd Maste 	ACPI_NFIT_MEMORY_MAP *mmap;
1227340c0022SEd Maste 	ACPI_NFIT_INTERLEAVE *ileave;
1228340c0022SEd Maste 	ACPI_NFIT_SMBIOS *smbios;
1229340c0022SEd Maste 	ACPI_NFIT_CONTROL_REGION *ctlreg;
1230340c0022SEd Maste 	ACPI_NFIT_DATA_REGION *datareg;
1231340c0022SEd Maste 	ACPI_NFIT_FLUSH_ADDRESS *fladdr;
1232340c0022SEd Maste 
1233340c0022SEd Maste 	if (nfit->Type < nitems(nfit_types))
1234340c0022SEd Maste 		printf("\tType=%s\n", nfit_types[nfit->Type]);
1235340c0022SEd Maste 	else
1236340c0022SEd Maste 		printf("\tType=%u (unknown)\n", nfit->Type);
1237340c0022SEd Maste 	switch (nfit->Type) {
1238340c0022SEd Maste 	case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
1239340c0022SEd Maste 		sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
1240340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
1241340c0022SEd Maste 		printf("\tProximityDomain=%u\n",
1242340c0022SEd Maste 		    (u_int)sysaddr->ProximityDomain);
1243340c0022SEd Maste 		uuid_to_string((uuid_t *)(sysaddr->RangeGuid),
1244340c0022SEd Maste 		    &uuidstr, &status);
1245340c0022SEd Maste 		if (status != uuid_s_ok)
1246340c0022SEd Maste 			errx(1, "uuid_to_string: status=%u", status);
1247340c0022SEd Maste 		printf("\tRangeGuid=%s\n", uuidstr);
1248340c0022SEd Maste 		free(uuidstr);
1249340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
1250340c0022SEd Maste 		printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
1251340c0022SEd Maste 		printf("\tMemoryMapping=0x%016jx\n",
1252340c0022SEd Maste 		    (uintmax_t)sysaddr->MemoryMapping);
1253340c0022SEd Maste 
1254340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1255340c0022SEd Maste 
1256340c0022SEd Maste 		printf("\tFlags=");
1257340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
1258340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
1259340c0022SEd Maste 		PRINTFLAG_END();
1260340c0022SEd Maste 
1261340c0022SEd Maste #undef PRINTFLAG
1262340c0022SEd Maste 
1263340c0022SEd Maste 		break;
1264340c0022SEd Maste 	case ACPI_NFIT_TYPE_MEMORY_MAP:
1265340c0022SEd Maste 		mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
1266340c0022SEd Maste 		printf("\tDeviceHandle=%u\n", (u_int)mmap->DeviceHandle);
1267340c0022SEd Maste 		printf("\tPhysicalId=%u\n", (u_int)mmap->PhysicalId);
1268340c0022SEd Maste 		printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
1269340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
1270340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
1271340c0022SEd Maste 		printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
1272340c0022SEd Maste 		printf("\tRegionOffset=0x%016jx\n",
1273340c0022SEd Maste 		    (uintmax_t)mmap->RegionOffset);
1274340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
1275340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
1276fb1cf2a9SAlexander Motin 		printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
1277340c0022SEd Maste 
1278340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_MEM_## flag, #flag)
1279340c0022SEd Maste 
1280340c0022SEd Maste 		printf("\tFlags=");
1281340c0022SEd Maste 		PRINTFLAG(mmap->Flags, SAVE_FAILED);
1282340c0022SEd Maste 		PRINTFLAG(mmap->Flags, RESTORE_FAILED);
1283340c0022SEd Maste 		PRINTFLAG(mmap->Flags, FLUSH_FAILED);
1284340c0022SEd Maste 		PRINTFLAG(mmap->Flags, NOT_ARMED);
1285340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
1286340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
1287340c0022SEd Maste 		PRINTFLAG(mmap->Flags, MAP_FAILED);
1288340c0022SEd Maste 		PRINTFLAG_END();
1289340c0022SEd Maste 
1290340c0022SEd Maste #undef PRINTFLAG
1291340c0022SEd Maste 
1292340c0022SEd Maste 		break;
1293340c0022SEd Maste 	case ACPI_NFIT_TYPE_INTERLEAVE:
1294340c0022SEd Maste 		ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
1295340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n",
1296340c0022SEd Maste 		    (u_int)ileave->InterleaveIndex);
1297340c0022SEd Maste 		printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
1298340c0022SEd Maste 		printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
1299340c0022SEd Maste 		/* XXX ileave->LineOffset[i] output is not supported */
1300340c0022SEd Maste 		break;
1301340c0022SEd Maste 	case ACPI_NFIT_TYPE_SMBIOS:
1302340c0022SEd Maste 		smbios = (ACPI_NFIT_SMBIOS *)nfit;
1303340c0022SEd Maste 		/* XXX smbios->Data[x] output is not supported */
1304340c0022SEd Maste 		break;
1305340c0022SEd Maste 	case ACPI_NFIT_TYPE_CONTROL_REGION:
1306340c0022SEd Maste 		ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
1307340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
1308340c0022SEd Maste 		printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
1309340c0022SEd Maste 		printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
1310340c0022SEd Maste 		printf("\tRevisionId=%u\n", (u_int)ctlreg->RevisionId);
1311340c0022SEd Maste 		printf("\tSubsystemVendorId=0x%04x\n",
1312340c0022SEd Maste 		    (u_int)ctlreg->SubsystemVendorId);
1313340c0022SEd Maste 		printf("\tSubsystemDeviceId=0x%04x\n",
1314340c0022SEd Maste 		    (u_int)ctlreg->SubsystemDeviceId);
1315340c0022SEd Maste 		printf("\tSubsystemRevisionId=%u\n",
1316340c0022SEd Maste 		    (u_int)ctlreg->SubsystemRevisionId);
1317d4c2de2eSAlexander Motin 		printf("\tValidFields=0x%02x\n", (u_int)ctlreg->ValidFields);
1318340c0022SEd Maste 		printf("\tManufacturingLocation=%u\n",
1319340c0022SEd Maste 		    (u_int)ctlreg->ManufacturingLocation);
1320340c0022SEd Maste 		printf("\tManufacturingDate=%u\n",
1321340c0022SEd Maste 		    (u_int)ctlreg->ManufacturingDate);
1322340c0022SEd Maste 		printf("\tSerialNumber=%u\n",
1323340c0022SEd Maste 		    (u_int)ctlreg->SerialNumber);
1324fb1cf2a9SAlexander Motin 		printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
1325340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
1326340c0022SEd Maste 		printf("\tWindowSize=0x%016jx\n",
1327340c0022SEd Maste 		    (uintmax_t)ctlreg->WindowSize);
1328340c0022SEd Maste 		printf("\tCommandOffset=0x%016jx\n",
1329340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandOffset);
1330340c0022SEd Maste 		printf("\tCommandSize=0x%016jx\n",
1331340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandSize);
1332340c0022SEd Maste 		printf("\tStatusOffset=0x%016jx\n",
1333340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusOffset);
1334340c0022SEd Maste 		printf("\tStatusSize=0x%016jx\n",
1335340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusSize);
1336340c0022SEd Maste 
1337340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1338340c0022SEd Maste 
1339340c0022SEd Maste 		printf("\tFlags=");
1340d4c2de2eSAlexander Motin 		PRINTFLAG(ctlreg->Flags, CONTROL_BUFFERED);
1341340c0022SEd Maste 		PRINTFLAG_END();
1342340c0022SEd Maste 
1343340c0022SEd Maste #undef PRINTFLAG
1344340c0022SEd Maste 
1345340c0022SEd Maste 		break;
1346340c0022SEd Maste 	case ACPI_NFIT_TYPE_DATA_REGION:
1347340c0022SEd Maste 		datareg = (ACPI_NFIT_DATA_REGION *)nfit;
1348340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
1349340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)datareg->Windows);
1350340c0022SEd Maste 		printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
1351340c0022SEd Maste 		printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
1352340c0022SEd Maste 		printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
1353340c0022SEd Maste 		printf("\tStartAddress=0x%016jx\n",
1354340c0022SEd Maste 		    (uintmax_t)datareg->StartAddress);
1355340c0022SEd Maste 		break;
1356340c0022SEd Maste 	case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
1357340c0022SEd Maste 		fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
1358340c0022SEd Maste 		printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
1359340c0022SEd Maste 		printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
1360340c0022SEd Maste 		/* XXX fladdr->HintAddress[i] output is not supported */
1361340c0022SEd Maste 		break;
1362340c0022SEd Maste 	}
1363340c0022SEd Maste }
1364340c0022SEd Maste 
1365340c0022SEd Maste static void
1366340c0022SEd Maste acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
1367340c0022SEd Maste {
1368340c0022SEd Maste 	ACPI_TABLE_NFIT *nfit;
1369340c0022SEd Maste 
1370340c0022SEd Maste 	printf(BEGIN_COMMENT);
1371340c0022SEd Maste 	acpi_print_sdt(sdp);
1372340c0022SEd Maste 	nfit = (ACPI_TABLE_NFIT *)sdp;
1373340c0022SEd Maste 	acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
1374340c0022SEd Maste 	printf(END_COMMENT);
1375340c0022SEd Maste }
1376340c0022SEd Maste 
1377a0333ad1SJohn Baldwin static void
1378986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1379c62f1cccSMitsuru IWASAKI {
1380773b6454SNate Lawson 	printf("  ");
1381986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
1382c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1383986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1384e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1385986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1386e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1387986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1388986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1389e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1390986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
1391986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1392e1e9a4bfSMitsuru IWASAKI }
1393e1e9a4bfSMitsuru IWASAKI 
1394945137d9SNate Lawson static void
1395986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1396e1e9a4bfSMitsuru IWASAKI {
1397986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1398986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1399e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1400e1e9a4bfSMitsuru IWASAKI 
1401986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1402986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1403773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1404773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1405986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1406e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1407e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1408e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1409e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1410fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
14117d369c6eSJung-uk Kim 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1412fe1d0c2dSJung-uk Kim 		else
14137d369c6eSJung-uk Kim 			printf("0x%016jx",
14147d369c6eSJung-uk Kim 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1415e1e9a4bfSMitsuru IWASAKI 	}
1416e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1417c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1418e1e9a4bfSMitsuru IWASAKI }
1419e1e9a4bfSMitsuru IWASAKI 
14208e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
14218e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
14228e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
14238e6a8737SNate Lawson };
14248e6a8737SNate Lawson 
1425945137d9SNate Lawson static void
1426986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1427e1e9a4bfSMitsuru IWASAKI {
1428986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
14298e6a8737SNate Lawson 	const char *pm;
1430e1e9a4bfSMitsuru IWASAKI 
1431986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1432c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
14332177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1434986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1435986dffafSJohn Baldwin 	       fadt->Dsdt);
1436986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1437986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
14388e6a8737SNate Lawson 		pm = "Reserved";
14398e6a8737SNate Lawson 	else
1440986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1441986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1442986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1443986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1444986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1445986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1446986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1447986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1448e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1449986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1450986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1451986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1452e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1453986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1454986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1455e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1456986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1457986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1458986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1459e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1460986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1461986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1462986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1463e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1464986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1465986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1466c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1467986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1468986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1469986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
14708e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1471986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1472986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1473986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
14748e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1475986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1476986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1477986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1478986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1479986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
148051c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1481986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1482e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1483986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1484e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1485986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1486e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1487986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1488e1e9a4bfSMitsuru IWASAKI 
1489ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1490e1e9a4bfSMitsuru IWASAKI 
14918e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1492986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1493986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1494986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1495986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1496986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1497f6469ce1SAndrew Turner 	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1498ec650989SNeel Natu 	PRINTFLAG_END();
14998e6a8737SNate Lawson 
15008e6a8737SNate Lawson 	printf("\tFlags=");
1501986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1502986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1503986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1504986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1505986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1506986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1507986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1508986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1509986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1510986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1511986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1512986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1513986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1514986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1515986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1516986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1517986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1518986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1519986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1520986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1521f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, HW_REDUCED);
1522f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1523ec650989SNeel Natu 	PRINTFLAG_END();
1524e1e9a4bfSMitsuru IWASAKI 
1525e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1526e1e9a4bfSMitsuru IWASAKI 
1527986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
15288e6a8737SNate Lawson 		printf("\tRESET_REG=");
1529986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1530986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
15318e6a8737SNate Lawson 	}
1532c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
15337d369c6eSJung-uk Kim 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
15347d369c6eSJung-uk Kim 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1535c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1536986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1537986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1538c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1539986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1540c08c4e81SNate Lawson 		}
1541c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1542986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1543986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1544c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1545986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1546c08c4e81SNate Lawson 		}
1547986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1548773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1549986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1550c08c4e81SNate Lawson 		}
1551773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1552986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1553986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1554773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1555986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1556c08c4e81SNate Lawson 		}
1557986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1558773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1559986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1560c08c4e81SNate Lawson 		}
1561773b6454SNate Lawson 		printf("\n");
1562773b6454SNate Lawson 	}
15638e6a8737SNate Lawson 
15648e6a8737SNate Lawson 	printf(END_COMMENT);
15658e6a8737SNate Lawson }
15668e6a8737SNate Lawson 
15678e6a8737SNate Lawson static void
1568986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
15698e6a8737SNate Lawson {
15708e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1571986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1572986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1573986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
15748e6a8737SNate Lawson 
1575773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1576986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1577986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
15788e6a8737SNate Lawson 			printf("PENDING,");
1579986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
15808e6a8737SNate Lawson 			printf("OWNED");
15818e6a8737SNate Lawson 	}
1582773b6454SNate Lawson 	printf("\n");
15838e6a8737SNate Lawson 
1584773b6454SNate Lawson 	printf("\tFlags=");
1585986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
15868e6a8737SNate Lawson 		printf("S4BIOS");
1587773b6454SNate Lawson 	printf("\n");
15888e6a8737SNate Lawson 
15897d369c6eSJung-uk Kim 	if (facs->XFirmwareWakingVector != 0)
15907d369c6eSJung-uk Kim 		printf("\tX_Firm_Wake_Vec=%016jx\n",
15917d369c6eSJung-uk Kim 		    (uintmax_t)facs->XFirmwareWakingVector);
1592986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
15938e6a8737SNate Lawson 
1594c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1595e1e9a4bfSMitsuru IWASAKI }
1596e1e9a4bfSMitsuru IWASAKI 
1597945137d9SNate Lawson static void
1598986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1599e1e9a4bfSMitsuru IWASAKI {
1600773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1601773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1602773b6454SNate Lawson 	printf(END_COMMENT);
1603e1e9a4bfSMitsuru IWASAKI }
1604e1e9a4bfSMitsuru IWASAKI 
1605e1e9a4bfSMitsuru IWASAKI int
1606e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1607e1e9a4bfSMitsuru IWASAKI {
1608986dffafSJohn Baldwin 	uint8_t *bp;
1609986dffafSJohn Baldwin 	uint8_t sum;
1610e1e9a4bfSMitsuru IWASAKI 
1611e1e9a4bfSMitsuru IWASAKI 	bp = p;
1612e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1613e1e9a4bfSMitsuru IWASAKI 	while (length--)
1614e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1615e1e9a4bfSMitsuru IWASAKI 
1616e1e9a4bfSMitsuru IWASAKI 	return (sum);
1617e1e9a4bfSMitsuru IWASAKI }
1618e1e9a4bfSMitsuru IWASAKI 
1619986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1620e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1621e1e9a4bfSMitsuru IWASAKI {
1622986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1623e1e9a4bfSMitsuru IWASAKI 
1624986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1625986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1626e1e9a4bfSMitsuru IWASAKI 	return (sp);
1627e1e9a4bfSMitsuru IWASAKI }
1628e1e9a4bfSMitsuru IWASAKI 
1629945137d9SNate Lawson static void
1630986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1631e1e9a4bfSMitsuru IWASAKI {
1632c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1633a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1634986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1635986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1636986dffafSJohn Baldwin 	       rp->Revision);
1637986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1638986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1639986dffafSJohn Baldwin 		    rp->Checksum);
1640a74172abSNate Lawson 	} else {
16417d369c6eSJung-uk Kim 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
16427d369c6eSJung-uk Kim 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
1643986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1644a74172abSNate Lawson 	}
1645c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1646e1e9a4bfSMitsuru IWASAKI }
1647e1e9a4bfSMitsuru IWASAKI 
1648945137d9SNate Lawson static void
1649986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1650e1e9a4bfSMitsuru IWASAKI {
1651986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1652986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1653986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1654a74172abSNate Lawson 	vm_offset_t addr;
1655a74172abSNate Lawson 	int entries, i;
1656e1e9a4bfSMitsuru IWASAKI 
1657e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1658986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1659986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1660986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1661e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1662fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1663986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1664fe1d0c2dSJung-uk Kim 		else
1665986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1666fe1d0c2dSJung-uk Kim 		if (addr == 0)
1667fe1d0c2dSJung-uk Kim 			continue;
1668986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1669986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
16705cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1671986dffafSJohn Baldwin 			    sdp->Signature);
16725cf6d493SNate Lawson 			continue;
16735cf6d493SNate Lawson 		}
1674986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
16752177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1676986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1677986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1678986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
167979d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1680986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
168155d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1682986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1683a47e681bSScott Long 			acpi_handle_mcfg(sdp);
168433866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
168533866658SJohn Baldwin 			acpi_handle_slit(sdp);
1686986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1687a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1688c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1689c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1690ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1691ec650989SNeel Natu 			acpi_handle_dmar(sdp);
1692340c0022SEd Maste 		else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
1693340c0022SEd Maste 			acpi_handle_nfit(sdp);
1694ed26c389SScott Long 		else if (!memcmp(sdp->Signature, ACPI_SIG_WDDT, 4))
1695ed26c389SScott Long 			acpi_handle_wddt(sdp);
1696773b6454SNate Lawson 		else {
1697773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1698773b6454SNate Lawson 			acpi_print_sdt(sdp);
1699773b6454SNate Lawson 			printf(END_COMMENT);
1700773b6454SNate Lawson 		}
1701e1e9a4bfSMitsuru IWASAKI 	}
1702e1e9a4bfSMitsuru IWASAKI }
1703c62f1cccSMitsuru IWASAKI 
1704986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1705476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1706945137d9SNate Lawson {
1707986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1708986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1709945137d9SNate Lawson 
1710945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1711945137d9SNate Lawson 	if (!rp)
1712945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1713945137d9SNate Lawson 
1714945137d9SNate Lawson 	if (tflag)
1715945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1716986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1717986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1718986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1719986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1720945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1721a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1722a74172abSNate Lawson 	} else {
1723986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1724986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1725986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1726a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1727a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1728a74172abSNate Lawson 	}
1729945137d9SNate Lawson 	return (rsdp);
1730945137d9SNate Lawson }
1731c62f1cccSMitsuru IWASAKI 
173262c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1733bfa3f012SMarcel Moolenaar static int
1734986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1735bfa3f012SMarcel Moolenaar {
1736986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1737986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1738bfa3f012SMarcel Moolenaar 	uint8_t sum;
1739bfa3f012SMarcel Moolenaar 
174062c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1741bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1742bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1743986dffafSJohn Baldwin 		sdt.Checksum = 0;
1744986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1745986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1746986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1747f7675a56SNate Lawson 		while (ssdt != NULL) {
1748986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1749986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1750986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1751986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1752bfa3f012SMarcel Moolenaar 		}
1753986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1754986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1755bfa3f012SMarcel Moolenaar 	}
175662c7bde1SNate Lawson 
175762c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1758986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1759986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
176062c7bde1SNate Lawson 
1761b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1762f7675a56SNate Lawson 	if (rsdt != NULL) {
1763bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1764bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1765986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1766986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1767bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1768bfa3f012SMarcel Moolenaar 		}
1769bfa3f012SMarcel Moolenaar 	}
1770bfa3f012SMarcel Moolenaar 	return (0);
1771bfa3f012SMarcel Moolenaar }
1772bfa3f012SMarcel Moolenaar 
1773c62f1cccSMitsuru IWASAKI void
1774986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1775c62f1cccSMitsuru IWASAKI {
1776945137d9SNate Lawson 	int	fd;
1777945137d9SNate Lawson 	mode_t	mode;
1778945137d9SNate Lawson 
1779945137d9SNate Lawson 	assert(outfile != NULL);
1780945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1781945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1782945137d9SNate Lawson 	if (fd == -1) {
1783945137d9SNate Lawson 		perror("dsdt_save_file");
1784945137d9SNate Lawson 		return;
1785945137d9SNate Lawson 	}
1786bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1787945137d9SNate Lawson 	close(fd);
1788c62f1cccSMitsuru IWASAKI }
1789c62f1cccSMitsuru IWASAKI 
1790945137d9SNate Lawson void
1791986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1792c62f1cccSMitsuru IWASAKI {
17937e2cc014SDon Lewis 	char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
17947e2cc014SDon Lewis 	const char *iname = "/acpdump.din";
17957e2cc014SDon Lewis 	const char *oname = "/acpdump.dsl";
179699065116SJung-uk Kim 	const char *tmpdir;
1797945137d9SNate Lawson 	FILE *fp;
179899065116SJung-uk Kim 	size_t len;
17997e2cc014SDon Lewis 	int fd, status;
18007e2cc014SDon Lewis 	pid_t pid;
1801945137d9SNate Lawson 
180299065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
180399065116SJung-uk Kim 	if (tmpdir == NULL)
180499065116SJung-uk Kim 		tmpdir = _PATH_TMP;
18057e2cc014SDon Lewis 	if (realpath(tmpdir, buf) == NULL) {
1806d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
180799065116SJung-uk Kim 		return;
180899065116SJung-uk Kim 	}
18097e2cc014SDon Lewis 	len = sizeof(wrkdir) - strlen(iname);
18107e2cc014SDon Lewis 	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
18117e2cc014SDon Lewis 		fprintf(stderr, "$TMPDIR too long\n");
18127e2cc014SDon Lewis 		return;
18137e2cc014SDon Lewis 	}
18147e2cc014SDon Lewis 	if  (mkdtemp(wrkdir) == NULL) {
18157e2cc014SDon Lewis 		perror("mkdtemp tmp working dir");
18167e2cc014SDon Lewis 		return;
18177e2cc014SDon Lewis 	}
181830bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
181930bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
18207e2cc014SDon Lewis 	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1821945137d9SNate Lawson 	if (fd < 0) {
1822945137d9SNate Lawson 		perror("iasl tmp file");
1823945137d9SNate Lawson 		return;
1824c62f1cccSMitsuru IWASAKI 	}
1825bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1826945137d9SNate Lawson 	close(fd);
1827945137d9SNate Lawson 
1828945137d9SNate Lawson 	/* Run iasl -d on the temp file */
18297e2cc014SDon Lewis 	if ((pid = fork()) == 0) {
1830945137d9SNate Lawson 		close(STDOUT_FILENO);
1831945137d9SNate Lawson 		if (vflag == 0)
1832945137d9SNate Lawson 			close(STDERR_FILENO);
183399065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1834945137d9SNate Lawson 		err(1, "exec");
1835c62f1cccSMitsuru IWASAKI 	}
18367e2cc014SDon Lewis 	if (pid > 0)
18377e2cc014SDon Lewis 		wait(&status);
18387e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
18397e2cc014SDon Lewis 		perror("unlink");
18407e2cc014SDon Lewis 		goto out;
18417e2cc014SDon Lewis 	}
18427e2cc014SDon Lewis 	if (pid < 0) {
18437e2cc014SDon Lewis 		perror("fork");
18447e2cc014SDon Lewis 		goto out;
18457e2cc014SDon Lewis 	}
18467e2cc014SDon Lewis 	if (status != 0) {
18477e2cc014SDon Lewis 		fprintf(stderr, "iast exit status = %d\n", status);
18487e2cc014SDon Lewis 	}
1849945137d9SNate Lawson 
1850945137d9SNate Lawson 	/* Dump iasl's output to stdout */
185130bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
185230bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
185399065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
18547e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
18557e2cc014SDon Lewis 		perror("unlink");
18567e2cc014SDon Lewis 		goto out;
18577e2cc014SDon Lewis 	}
1858945137d9SNate Lawson 	if (fp == NULL) {
1859945137d9SNate Lawson 		perror("iasl tmp file (read)");
18607e2cc014SDon Lewis 		goto out;
1861945137d9SNate Lawson 	}
1862945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1863945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1864945137d9SNate Lawson 	fclose(fp);
18657e2cc014SDon Lewis 
18667e2cc014SDon Lewis     out:
18677e2cc014SDon Lewis 	if (rmdir(wrkdir) < 0)
18687e2cc014SDon Lewis 		perror("rmdir");
1869c62f1cccSMitsuru IWASAKI }
1870c62f1cccSMitsuru IWASAKI 
1871945137d9SNate Lawson void
1872986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1873c62f1cccSMitsuru IWASAKI {
1874945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1875c62f1cccSMitsuru IWASAKI }
1876c62f1cccSMitsuru IWASAKI 
1877bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1878986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1879986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1880c62f1cccSMitsuru IWASAKI {
1881986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1882986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1883986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1884a74172abSNate Lawson 	vm_offset_t addr;
1885a74172abSNate Lawson 	int entries, i;
1886945137d9SNate Lawson 
1887986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1888986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1889986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1890945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1891fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1892986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1893fe1d0c2dSJung-uk Kim 		else
1894986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1895fe1d0c2dSJung-uk Kim 		if (addr == 0)
1896fe1d0c2dSJung-uk Kim 			continue;
1897986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1898bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1899bfa3f012SMarcel Moolenaar 			if (sdt == last)
1900bfa3f012SMarcel Moolenaar 				last = NULL;
1901bfa3f012SMarcel Moolenaar 			continue;
1902bfa3f012SMarcel Moolenaar 		}
1903986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1904a74172abSNate Lawson 			continue;
1905986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1906945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1907945137d9SNate Lawson 		return (sdt);
1908c62f1cccSMitsuru IWASAKI 	}
1909c62f1cccSMitsuru IWASAKI 
1910945137d9SNate Lawson 	return (NULL);
1911c62f1cccSMitsuru IWASAKI }
1912c62f1cccSMitsuru IWASAKI 
1913986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1914986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1915c62f1cccSMitsuru IWASAKI {
1916986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1917c62f1cccSMitsuru IWASAKI 
1918986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1919c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1920986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
19212e71eb12SNate Lawson 	else
1922986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1923986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1924945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1925945137d9SNate Lawson 	return (sdt);
1926c62f1cccSMitsuru IWASAKI }
1927