xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision 969a4b8be5a7d8edf55bd8945a5a071f57386b0e)
1e1e9a4bfSMitsuru IWASAKI /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 1998 Doug Rabson
5e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6ebc22d04SAlexander Motin  * Copyright (c) 2020 Alexander Motin <mav@FreeBSD.org>
7e1e9a4bfSMitsuru IWASAKI  * All rights reserved.
8e1e9a4bfSMitsuru IWASAKI  *
9e1e9a4bfSMitsuru IWASAKI  * Redistribution and use in source and binary forms, with or without
10e1e9a4bfSMitsuru IWASAKI  * modification, are permitted provided that the following conditions
11e1e9a4bfSMitsuru IWASAKI  * are met:
12e1e9a4bfSMitsuru IWASAKI  * 1. Redistributions of source code must retain the above copyright
13e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer.
14e1e9a4bfSMitsuru IWASAKI  * 2. Redistributions in binary form must reproduce the above copyright
15e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer in the
16e1e9a4bfSMitsuru IWASAKI  *    documentation and/or other materials provided with the distribution.
17e1e9a4bfSMitsuru IWASAKI  *
18e1e9a4bfSMitsuru IWASAKI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19e1e9a4bfSMitsuru IWASAKI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20e1e9a4bfSMitsuru IWASAKI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21e1e9a4bfSMitsuru IWASAKI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22e1e9a4bfSMitsuru IWASAKI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23e1e9a4bfSMitsuru IWASAKI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24e1e9a4bfSMitsuru IWASAKI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25e1e9a4bfSMitsuru IWASAKI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26e1e9a4bfSMitsuru IWASAKI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27e1e9a4bfSMitsuru IWASAKI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28e1e9a4bfSMitsuru IWASAKI  * SUCH DAMAGE.
29e1e9a4bfSMitsuru IWASAKI  */
30e1e9a4bfSMitsuru IWASAKI 
31e1e9a4bfSMitsuru IWASAKI #include <sys/param.h>
32a74172abSNate Lawson #include <sys/endian.h>
33e1e9a4bfSMitsuru IWASAKI #include <sys/stat.h>
34945137d9SNate Lawson #include <sys/wait.h>
35e1e9a4bfSMitsuru IWASAKI #include <assert.h>
36e1e9a4bfSMitsuru IWASAKI #include <err.h>
37e1e9a4bfSMitsuru IWASAKI #include <fcntl.h>
3899065116SJung-uk Kim #include <paths.h>
39e1e9a4bfSMitsuru IWASAKI #include <stdio.h>
40a0333ad1SJohn Baldwin #include <stdint.h>
4199065116SJung-uk Kim #include <stdlib.h>
42945137d9SNate Lawson #include <string.h>
43e1e9a4bfSMitsuru IWASAKI #include <unistd.h>
44340c0022SEd Maste #include <uuid.h>
45e1e9a4bfSMitsuru IWASAKI 
46e1e9a4bfSMitsuru IWASAKI #include "acpidump.h"
47e1e9a4bfSMitsuru IWASAKI 
48c62f1cccSMitsuru IWASAKI #define BEGIN_COMMENT	"/*\n"
49c62f1cccSMitsuru IWASAKI #define END_COMMENT	" */\n"
50c62f1cccSMitsuru IWASAKI 
51945137d9SNate Lawson static void	acpi_print_string(char *s, size_t length);
52986dffafSJohn Baldwin static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
53986dffafSJohn Baldwin static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
54986dffafSJohn Baldwin static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
55945137d9SNate Lawson static void	acpi_print_cpu(u_char cpu_id);
56986dffafSJohn Baldwin static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
57986dffafSJohn Baldwin static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
58986dffafSJohn Baldwin static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
59986dffafSJohn Baldwin 		    uint64_t apic_addr);
60986dffafSJohn Baldwin static void	acpi_print_mps_flags(uint16_t flags);
61986dffafSJohn Baldwin static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
62986dffafSJohn Baldwin static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
63986dffafSJohn Baldwin static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
64986dffafSJohn Baldwin static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
65986dffafSJohn Baldwin static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
66986dffafSJohn Baldwin static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
67986dffafSJohn Baldwin static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
6833866658SJohn Baldwin static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
69ed26c389SScott Long static void	acpi_handle_wddt(ACPI_TABLE_HEADER *sdp);
705857fba5SBen Widawsky static void	acpi_handle_lpit(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
160*969a4b8bSKonstantin Belousov printfield(uint64_t var, int lbit, int hbit, const char *name)
161*969a4b8bSKonstantin Belousov {
162*969a4b8bSKonstantin Belousov 	uint64_t mask;
163*969a4b8bSKonstantin Belousov 	int len;
164*969a4b8bSKonstantin Belousov 
165*969a4b8bSKonstantin Belousov 	len = hbit - lbit + 1;
166*969a4b8bSKonstantin Belousov 	mask = ((1 << (len + 1)) - 1) << lbit;
167*969a4b8bSKonstantin Belousov 	printf("%c%s=%#jx", pf_sep, name, (uintmax_t)((var & mask) >> lbit));
168*969a4b8bSKonstantin Belousov 	pf_sep = ',';
169*969a4b8bSKonstantin Belousov }
170*969a4b8bSKonstantin Belousov 
171*969a4b8bSKonstantin Belousov static void
172e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
173e1e9a4bfSMitsuru IWASAKI {
174e1e9a4bfSMitsuru IWASAKI 	int	c;
175e1e9a4bfSMitsuru IWASAKI 
176e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
177e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
178e1e9a4bfSMitsuru IWASAKI 		length--;
179e1e9a4bfSMitsuru IWASAKI 
180e1e9a4bfSMitsuru IWASAKI 	while (length--) {
181e1e9a4bfSMitsuru IWASAKI 		c = *s++;
182e1e9a4bfSMitsuru IWASAKI 		putchar(c);
183e1e9a4bfSMitsuru IWASAKI 	}
184e1e9a4bfSMitsuru IWASAKI }
185e1e9a4bfSMitsuru IWASAKI 
186e1e9a4bfSMitsuru IWASAKI static void
187986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1888e6a8737SNate Lawson {
189986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1908e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
191ebc22d04SAlexander Motin 		printf("0x%016jx:%u[%u] (Memory)", (uintmax_t)gas->Address,
192ebc22d04SAlexander Motin 		    gas->BitOffset, gas->BitWidth);
1938e6a8737SNate Lawson 		break;
1948e6a8737SNate Lawson 	case ACPI_GAS_IO:
195ebc22d04SAlexander Motin 		printf("0x%02jx:%u[%u] (IO)", (uintmax_t)gas->Address,
196986dffafSJohn Baldwin 		    gas->BitOffset, gas->BitWidth);
1978e6a8737SNate Lawson 		break;
1988e6a8737SNate Lawson 	case ACPI_GAS_PCI:
199ebc22d04SAlexander Motin 		printf("%x:%x+0x%x:%u[%u] (PCI)", (uint16_t)(gas->Address >> 32),
200986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
201ebc22d04SAlexander Motin 		       (uint16_t)gas->Address, gas->BitOffset, gas->BitWidth);
2028e6a8737SNate Lawson 		break;
2038e6a8737SNate Lawson 	/* XXX How to handle these below? */
2048e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
205986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
206986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
2078e6a8737SNate Lawson 		break;
2088e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
209986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
210986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
2118e6a8737SNate Lawson 		break;
212986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
213986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
214986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
2158e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
2168e6a8737SNate Lawson 	default:
2177d369c6eSJung-uk Kim 		printf("0x%016jx (?)", (uintmax_t)gas->Address);
2188e6a8737SNate Lawson 		break;
2198e6a8737SNate Lawson 	}
2208e6a8737SNate Lawson }
2218e6a8737SNate Lawson 
222c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
223c2962974SNate Lawson static int
2244262ad56SKonstantin Belousov acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt __unused)
225e1e9a4bfSMitsuru IWASAKI {
226c2962974SNate Lawson 	int fadt_revision;
227e1e9a4bfSMitsuru IWASAKI 
228c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
229c83f0f99SNate Lawson 	if (addr_size == 8) {
230c83f0f99SNate Lawson 		fadt_revision = 2;
2318e6a8737SNate Lawson 
23201593a0fSAndrew Turner #if defined(__i386__)
233773b6454SNate Lawson 		/*
234c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
235c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
236c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
237c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
238c83f0f99SNate Lawson 		 * version for all subsequent tables.
23901593a0fSAndrew Turner 		 *
24001593a0fSAndrew Turner 		 * The only known ACPI systems this affects are early
24101593a0fSAndrew Turner 		 * implementations on 32-bit x86. Because of this limit the
24201593a0fSAndrew Turner 		 * workaround to i386.
243773b6454SNate Lawson 		 */
244986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
245986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
246c83f0f99SNate Lawson 			fadt_revision = 1;
24701593a0fSAndrew Turner #endif
248c2962974SNate Lawson 	} else
249c83f0f99SNate Lawson 		fadt_revision = 1;
250c2962974SNate Lawson 	return (fadt_revision);
251c83f0f99SNate Lawson }
252c2962974SNate Lawson 
253c2962974SNate Lawson static void
254986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
255c2962974SNate Lawson {
256986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
257986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
258986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
259bc711181SAndrew Turner 	vm_offset_t	addr;
260c2962974SNate Lawson 	int		fadt_revision;
261c2962974SNate Lawson 
262986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2632177d4e6SNate Lawson 	acpi_print_fadt(sdp);
264c83f0f99SNate Lawson 
265c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
266c83f0f99SNate Lawson 	if (fadt_revision == 1)
267bc711181SAndrew Turner 		addr = fadt->Facs;
268773b6454SNate Lawson 	else
269bc711181SAndrew Turner 		addr = fadt->XFacs;
270bc711181SAndrew Turner 	if (addr != 0) {
271bc711181SAndrew Turner 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(addr);
272bc711181SAndrew Turner 
273bc711181SAndrew Turner 		if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 ||
274bc711181SAndrew Turner 		    facs->Length < 64)
2758e6a8737SNate Lawson 			errx(1, "FACS is corrupt");
2768e6a8737SNate Lawson 		acpi_print_facs(facs);
277bc711181SAndrew Turner 	}
2788e6a8737SNate Lawson 
279c83f0f99SNate Lawson 	if (fadt_revision == 1)
280986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
281773b6454SNate Lawson 	else
282986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
283986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
284945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
285945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
286c62f1cccSMitsuru IWASAKI }
287c62f1cccSMitsuru IWASAKI 
288c62f1cccSMitsuru IWASAKI static void
289986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
290986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
291986dffafSJohn Baldwin {
292986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
293986dffafSJohn Baldwin 	char *end;
294986dffafSJohn Baldwin 
295986dffafSJohn Baldwin 	subtable = first;
296986dffafSJohn Baldwin 	end = (char *)table + table->Length;
297986dffafSJohn Baldwin 	while ((char *)subtable < end) {
298986dffafSJohn Baldwin 		printf("\n");
299f5d0a8f7SEd Maste 		if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
300f5d0a8f7SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
301f5d0a8f7SEd Maste 			return;
302f5d0a8f7SEd Maste 		}
303986dffafSJohn Baldwin 		action(subtable);
304986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
305986dffafSJohn Baldwin 		    subtable->Length);
306986dffafSJohn Baldwin 	}
307986dffafSJohn Baldwin }
308986dffafSJohn Baldwin 
309986dffafSJohn Baldwin static void
310340c0022SEd Maste acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
311340c0022SEd Maste     void (*action)(ACPI_NFIT_HEADER *))
312340c0022SEd Maste {
313340c0022SEd Maste 	ACPI_NFIT_HEADER *subtable;
314340c0022SEd Maste 	char *end;
315340c0022SEd Maste 
316340c0022SEd Maste 	subtable = first;
317340c0022SEd Maste 	end = (char *)table + table->Length;
318340c0022SEd Maste 	while ((char *)subtable < end) {
319340c0022SEd Maste 		printf("\n");
320340c0022SEd Maste 		if (subtable->Length < sizeof(ACPI_NFIT_HEADER)) {
321340c0022SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
322340c0022SEd Maste 			return;
323340c0022SEd Maste 		}
324340c0022SEd Maste 		action(subtable);
325340c0022SEd Maste 		subtable = (ACPI_NFIT_HEADER *)((char *)subtable +
326340c0022SEd Maste 		    subtable->Length);
327340c0022SEd Maste 	}
328340c0022SEd Maste }
329340c0022SEd Maste 
330340c0022SEd Maste static void
3310a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
3320a473124SJohn Baldwin {
3330a473124SJohn Baldwin 
3340a473124SJohn Baldwin 	printf("\tACPI CPU=");
3350a473124SJohn Baldwin 	if (cpu_id == 0xff)
3360a473124SJohn Baldwin 		printf("ALL\n");
3370a473124SJohn Baldwin 	else
3380a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
3390a473124SJohn Baldwin }
3400a473124SJohn Baldwin 
3410a473124SJohn Baldwin static void
342986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
3430a473124SJohn Baldwin {
344986dffafSJohn Baldwin 
345986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
346986dffafSJohn Baldwin 	if (uid_string != NULL)
347986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
348986dffafSJohn Baldwin 	printf("\n");
349986dffafSJohn Baldwin }
350986dffafSJohn Baldwin 
351986dffafSJohn Baldwin static void
352986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
353986dffafSJohn Baldwin {
354986dffafSJohn Baldwin 
3550a473124SJohn Baldwin 	printf("\tFlags={");
356986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
3570a473124SJohn Baldwin 		printf("ENABLED");
3580a473124SJohn Baldwin 	else
3590a473124SJohn Baldwin 		printf("DISABLED");
3600a473124SJohn Baldwin 	printf("}\n");
361986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3620a473124SJohn Baldwin }
3630a473124SJohn Baldwin 
3640a473124SJohn Baldwin static void
365986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
3660a473124SJohn Baldwin {
367986dffafSJohn Baldwin 
368986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3690a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
370986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
3710a473124SJohn Baldwin }
3720a473124SJohn Baldwin 
3730a473124SJohn Baldwin static void
374986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
3750a473124SJohn Baldwin {
3760a473124SJohn Baldwin 
3770a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
378986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
379986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
3800a473124SJohn Baldwin 		printf("conforming");
3810a473124SJohn Baldwin 		break;
382986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3830a473124SJohn Baldwin 		printf("active-hi");
3840a473124SJohn Baldwin 		break;
385986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3860a473124SJohn Baldwin 		printf("active-lo");
3870a473124SJohn Baldwin 		break;
3880a473124SJohn Baldwin 	default:
389986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3900a473124SJohn Baldwin 		break;
3910a473124SJohn Baldwin 	}
3920a473124SJohn Baldwin 	printf(", Trigger=");
393986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
394986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3950a473124SJohn Baldwin 		printf("conforming");
3960a473124SJohn Baldwin 		break;
397986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3980a473124SJohn Baldwin 		printf("edge");
3990a473124SJohn Baldwin 		break;
400986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
4010a473124SJohn Baldwin 		printf("level");
4020a473124SJohn Baldwin 		break;
4030a473124SJohn Baldwin 	default:
404986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
4050a473124SJohn Baldwin 	}
4060a473124SJohn Baldwin 	printf("}\n");
4070a473124SJohn Baldwin }
4080a473124SJohn Baldwin 
4090a473124SJohn Baldwin static void
4102b2b1f42SAndrew Turner acpi_print_gicc_flags(uint32_t flags)
4112b2b1f42SAndrew Turner {
4122b2b1f42SAndrew Turner 
4132b2b1f42SAndrew Turner 	printf("\tFlags={Performance intr=");
4142b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
4152b2b1f42SAndrew Turner 		printf("edge");
4162b2b1f42SAndrew Turner 	else
4172b2b1f42SAndrew Turner 		printf("level");
4182b2b1f42SAndrew Turner 	printf(", VGIC intr=");
4192b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_VGIC_IRQ_MODE)
4202b2b1f42SAndrew Turner 		printf("edge");
4212b2b1f42SAndrew Turner 	else
4222b2b1f42SAndrew Turner 		printf("level");
4232b2b1f42SAndrew Turner 	printf("}\n");
4242b2b1f42SAndrew Turner }
4252b2b1f42SAndrew Turner 
4262b2b1f42SAndrew Turner static void
427986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
4280a473124SJohn Baldwin {
4290a473124SJohn Baldwin 
430986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
431986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
432986dffafSJohn Baldwin }
433986dffafSJohn Baldwin 
434986dffafSJohn Baldwin static void
435986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
436986dffafSJohn Baldwin {
437986dffafSJohn Baldwin 
438986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
4390a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
4400a473124SJohn Baldwin }
4410a473124SJohn Baldwin 
44227941afaSEd Maste static const char *apic_types[] = {
44327941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
44427941afaSEd Maste     [ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
44527941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
44627941afaSEd Maste     [ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
44727941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
44827941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
44927941afaSEd Maste     [ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
45027941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
45127941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
45227941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
45327941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
45427941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
45527941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
45627941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
45727941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
45827941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
45927941afaSEd Maste };
46027941afaSEd Maste 
461bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
4620a473124SJohn Baldwin 					    "Corrected Platform Error" };
4630a473124SJohn Baldwin 
4640a473124SJohn Baldwin static void
465986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
4660a473124SJohn Baldwin {
467986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
468986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
469986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
470986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
471986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
472986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
473986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
474986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
475986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
476986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
477986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
4782b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_INTERRUPT *gicc;
4792b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
4802b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
4812b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_TRANSLATOR *gict;
4820a473124SJohn Baldwin 
483c86932b6SMarcelo Araujo 	if (mp->Type < nitems(apic_types))
484986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
485a0333ad1SJohn Baldwin 	else
486986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
487986dffafSJohn Baldwin 	switch (mp->Type) {
488986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
489986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
490986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
491986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4920a473124SJohn Baldwin 		break;
493986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
494986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
495986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
496986dffafSJohn Baldwin 		    ioapic->Address);
4970a473124SJohn Baldwin 		break;
498986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
499986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
500986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
501986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
502986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
5030a473124SJohn Baldwin 		break;
504986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
505986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
506986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
5070a473124SJohn Baldwin 		break;
508986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
509986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
510986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
511986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
5120a473124SJohn Baldwin 		break;
513986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
514986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
515945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
516986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
5170a473124SJohn Baldwin 		break;
518986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
519986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
520986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
521986dffafSJohn Baldwin 		    iosapic->Address);
5220a473124SJohn Baldwin 		break;
523986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
524986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
525986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
526986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
527986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
528986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
529986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
5300a473124SJohn Baldwin 		break;
531986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
532986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
533c86932b6SMarcelo Araujo 		if (isrc->Type < nitems(platform_int_types))
534986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
535986dffafSJohn Baldwin 		else
536986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
537986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
538986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
539986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
540986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
541986dffafSJohn Baldwin 		break;
542986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
543986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
544986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
545986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
546986dffafSJohn Baldwin 		break;
547986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
548986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
549986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
550986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
5510a473124SJohn Baldwin 		break;
5522b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
5532b2b1f42SAndrew Turner 		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
5542b2b1f42SAndrew Turner 		acpi_print_cpu_uid(gicc->Uid, NULL);
5552b2b1f42SAndrew Turner 		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
5562b2b1f42SAndrew Turner 		acpi_print_gicc_flags(gicc->Flags);
5572b2b1f42SAndrew Turner 		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
5582b2b1f42SAndrew Turner 		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
5592b2b1f42SAndrew Turner 		printf("\tParked ADDR=%016jx\n",
5602b2b1f42SAndrew Turner 		    (uintmax_t)gicc->ParkedAddress);
5612b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
5622b2b1f42SAndrew Turner 		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
5632b2b1f42SAndrew Turner 		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
5642b2b1f42SAndrew Turner 		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
5652b2b1f42SAndrew Turner 		printf("\tGICR ADDR=%016jx\n",
5662b2b1f42SAndrew Turner 		    (uintmax_t)gicc->GicrBaseAddress);
5672b2b1f42SAndrew Turner 		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
5680b4302aaSGordon Bergling 		printf("\tEfficiency Class=%d\n", (u_int)gicc->EfficiencyClass);
569c363da4aSAndrew Turner 		printf("\tSPE INTR=%d\n", gicc->SpeInterrupt);
5702b2b1f42SAndrew Turner 		break;
5712b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
5722b2b1f42SAndrew Turner 		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
5732b2b1f42SAndrew Turner 		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
5742b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
5752b2b1f42SAndrew Turner 		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
5762b2b1f42SAndrew Turner 		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
5772b2b1f42SAndrew Turner 		break;
5782b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
5792b2b1f42SAndrew Turner 		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
5802b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
5812b2b1f42SAndrew Turner 		printf("\tLength=%08x\n", gicr->Length);
5822b2b1f42SAndrew Turner 		break;
5832b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
5842b2b1f42SAndrew Turner 		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
5852b2b1f42SAndrew Turner 		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
5862b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
5872b2b1f42SAndrew Turner 		break;
5880a473124SJohn Baldwin 	}
5890a473124SJohn Baldwin }
5900a473124SJohn Baldwin 
5910a473124SJohn Baldwin static void
592986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
5930a473124SJohn Baldwin {
594986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
5950a473124SJohn Baldwin 
596773b6454SNate Lawson 	printf(BEGIN_COMMENT);
597773b6454SNate Lawson 	acpi_print_sdt(sdp);
598986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
599986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
6000a473124SJohn Baldwin 	printf("\tFlags={");
601986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
6020a473124SJohn Baldwin 		printf("PC-AT");
6030a473124SJohn Baldwin 	printf("}\n");
604986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
6050a473124SJohn Baldwin 	printf(END_COMMENT);
6060a473124SJohn Baldwin }
6070a473124SJohn Baldwin 
6080a473124SJohn Baldwin static void
609ebc22d04SAlexander Motin acpi_handle_bert(ACPI_TABLE_HEADER *sdp)
610ebc22d04SAlexander Motin {
611ebc22d04SAlexander Motin 	ACPI_TABLE_BERT *bert;
612ebc22d04SAlexander Motin 
613ebc22d04SAlexander Motin 	printf(BEGIN_COMMENT);
614ebc22d04SAlexander Motin 	acpi_print_sdt(sdp);
615ebc22d04SAlexander Motin 	bert = (ACPI_TABLE_BERT *)sdp;
616ebc22d04SAlexander Motin 	printf("\tRegionLength=%d\n", bert->RegionLength);
617ebc22d04SAlexander Motin 	printf("\tAddress=0x%016jx\n", bert->Address);
618ebc22d04SAlexander Motin 	printf(END_COMMENT);
619ebc22d04SAlexander Motin }
620ebc22d04SAlexander Motin 
621ebc22d04SAlexander Motin static void
622ebc22d04SAlexander Motin acpi_print_whea(ACPI_WHEA_HEADER *w)
623ebc22d04SAlexander Motin {
624ebc22d04SAlexander Motin 
625ebc22d04SAlexander Motin 	printf("\n\tAction=%d\n", w->Action);
626ebc22d04SAlexander Motin 	printf("\tInstruction=%d\n", w->Instruction);
627ebc22d04SAlexander Motin 	printf("\tFlags=%02x\n", w->Flags);
628ebc22d04SAlexander Motin 	printf("\tRegisterRegion=");
629ebc22d04SAlexander Motin 	acpi_print_gas(&w->RegisterRegion);
630ebc22d04SAlexander Motin 	printf("\n\tValue=0x%016jx\n", w->Value);
631ebc22d04SAlexander Motin 	printf("\tMask=0x%016jx\n", w->Mask);
632ebc22d04SAlexander Motin }
633ebc22d04SAlexander Motin 
634ebc22d04SAlexander Motin static void
635ebc22d04SAlexander Motin acpi_handle_einj(ACPI_TABLE_HEADER *sdp)
636ebc22d04SAlexander Motin {
637ebc22d04SAlexander Motin 	ACPI_TABLE_EINJ *einj;
638ebc22d04SAlexander Motin 	ACPI_WHEA_HEADER *w;
639ebc22d04SAlexander Motin 	u_int i;
640ebc22d04SAlexander Motin 
641ebc22d04SAlexander Motin 	printf(BEGIN_COMMENT);
642ebc22d04SAlexander Motin 	acpi_print_sdt(sdp);
643ebc22d04SAlexander Motin 	einj = (ACPI_TABLE_EINJ *)sdp;
644ebc22d04SAlexander Motin 	printf("\tHeaderLength=%d\n", einj->HeaderLength);
645ebc22d04SAlexander Motin 	printf("\tFlags=0x%02x\n", einj->Flags);
646ebc22d04SAlexander Motin 	printf("\tEntries=%d\n", einj->Entries);
647ebc22d04SAlexander Motin 	w = (ACPI_WHEA_HEADER *)(einj + 1);
648ebc22d04SAlexander Motin 	for (i = 0; i < MIN(einj->Entries, (sdp->Length -
649ebc22d04SAlexander Motin 	    sizeof(ACPI_TABLE_EINJ)) / sizeof(ACPI_WHEA_HEADER)); i++)
650ebc22d04SAlexander Motin 		acpi_print_whea(w + i);
651ebc22d04SAlexander Motin 	printf(END_COMMENT);
652ebc22d04SAlexander Motin }
653ebc22d04SAlexander Motin 
654ebc22d04SAlexander Motin static void
655ebc22d04SAlexander Motin acpi_handle_erst(ACPI_TABLE_HEADER *sdp)
656ebc22d04SAlexander Motin {
657ebc22d04SAlexander Motin 	ACPI_TABLE_ERST *erst;
658ebc22d04SAlexander Motin 	ACPI_WHEA_HEADER *w;
659ebc22d04SAlexander Motin 	u_int i;
660ebc22d04SAlexander Motin 
661ebc22d04SAlexander Motin 	printf(BEGIN_COMMENT);
662ebc22d04SAlexander Motin 	acpi_print_sdt(sdp);
663ebc22d04SAlexander Motin 	erst = (ACPI_TABLE_ERST *)sdp;
664ebc22d04SAlexander Motin 	printf("\tHeaderLength=%d\n", erst->HeaderLength);
665ebc22d04SAlexander Motin 	printf("\tEntries=%d\n", erst->Entries);
666ebc22d04SAlexander Motin 	w = (ACPI_WHEA_HEADER *)(erst + 1);
667ebc22d04SAlexander Motin 	for (i = 0; i < MIN(erst->Entries, (sdp->Length -
668ebc22d04SAlexander Motin 	    sizeof(ACPI_TABLE_ERST)) / sizeof(ACPI_WHEA_HEADER)); i++)
669ebc22d04SAlexander Motin 		acpi_print_whea(w + i);
670ebc22d04SAlexander Motin 	printf(END_COMMENT);
671ebc22d04SAlexander Motin }
672ebc22d04SAlexander Motin 
673ebc22d04SAlexander Motin static void
674ebc22d04SAlexander Motin acpi_print_hest_bank(ACPI_HEST_IA_ERROR_BANK *b)
675ebc22d04SAlexander Motin {
676ebc22d04SAlexander Motin 
677ebc22d04SAlexander Motin 	printf("\tBank:\n");
678ebc22d04SAlexander Motin 	printf("\t\tBankNumber=%d\n", b->BankNumber);
679ebc22d04SAlexander Motin 	printf("\t\tClearStatusOnInit=%d\n", b->ClearStatusOnInit);
680ebc22d04SAlexander Motin 	printf("\t\tStatusFormat=%d\n", b->StatusFormat);
681ebc22d04SAlexander Motin 	printf("\t\tControlRegister=%x\n", b->ControlRegister);
682ebc22d04SAlexander Motin 	printf("\t\tControlData=%jx\n", b->ControlData);
683ebc22d04SAlexander Motin 	printf("\t\tStatusRegister=%x\n", b->StatusRegister);
684ebc22d04SAlexander Motin 	printf("\t\tAddressRegister=%x\n", b->AddressRegister);
685ebc22d04SAlexander Motin 	printf("\t\tMiscRegister=%x\n", b->MiscRegister);
686ebc22d04SAlexander Motin }
687ebc22d04SAlexander Motin 
688ebc22d04SAlexander Motin static void
689ebc22d04SAlexander Motin acpi_print_hest_notify(ACPI_HEST_NOTIFY *n)
690ebc22d04SAlexander Motin {
691ebc22d04SAlexander Motin 
692ebc22d04SAlexander Motin 	printf("\t\tType=%d\n", n->Type);
693ebc22d04SAlexander Motin 	printf("\t\tLength=%d\n", n->Length);
694ebc22d04SAlexander Motin 	printf("\t\tConfigWriteEnable=%04x\n", n->ConfigWriteEnable);
695ebc22d04SAlexander Motin 	printf("\t\tPollInterval=%d\n", n->PollInterval);
696ebc22d04SAlexander Motin 	printf("\t\tVector=%d\n", n->Vector);
697ebc22d04SAlexander Motin 	printf("\t\tPollingThresholdValue=%d\n", n->PollingThresholdValue);
698ebc22d04SAlexander Motin 	printf("\t\tPollingThresholdWindow=%d\n", n->PollingThresholdWindow);
699ebc22d04SAlexander Motin 	printf("\t\tErrorThresholdValue=%d\n", n->ErrorThresholdValue);
700ebc22d04SAlexander Motin 	printf("\t\tErrorThresholdWindow=%d\n", n->ErrorThresholdWindow);
701ebc22d04SAlexander Motin }
702ebc22d04SAlexander Motin 
703ebc22d04SAlexander Motin static void
704ebc22d04SAlexander Motin acpi_print_hest_aer(ACPI_HEST_AER_COMMON *a)
705ebc22d04SAlexander Motin {
706ebc22d04SAlexander Motin 
707ebc22d04SAlexander Motin 	printf("\tFlags=%02x\n", a->Flags);
708ebc22d04SAlexander Motin 	printf("\tEnabled=%d\n", a->Enabled);
709ebc22d04SAlexander Motin 	printf("\tRecordsToPreallocate=%d\n", a->RecordsToPreallocate);
710ebc22d04SAlexander Motin 	printf("\tMaxSectionsPerRecord=%d\n", a->MaxSectionsPerRecord);
711ebc22d04SAlexander Motin 	printf("\tBus=%d\n", a->Bus);
712ebc22d04SAlexander Motin 	printf("\tDevice=%d\n", a->Device);
713ebc22d04SAlexander Motin 	printf("\tFunction=%d\n", a->Function);
714ebc22d04SAlexander Motin 	printf("\tDeviceControl=%d\n", a->DeviceControl);
715ebc22d04SAlexander Motin 	printf("\tUncorrectableMask=%d\n", a->UncorrectableMask);
716ebc22d04SAlexander Motin 	printf("\tUncorrectableSeverity=%d\n", a->UncorrectableSeverity);
717ebc22d04SAlexander Motin 	printf("\tCorrectableMask=%d\n", a->CorrectableMask);
718ebc22d04SAlexander Motin 	printf("\tAdvancedCapabilities=%d\n", a->AdvancedCapabilities);
719ebc22d04SAlexander Motin }
720ebc22d04SAlexander Motin 
721ebc22d04SAlexander Motin static int
722ebc22d04SAlexander Motin acpi_handle_hest_structure(void *addr, int remaining)
723ebc22d04SAlexander Motin {
724ebc22d04SAlexander Motin 	ACPI_HEST_HEADER *hdr = addr;
725ebc22d04SAlexander Motin 	int i;
726ebc22d04SAlexander Motin 
727ebc22d04SAlexander Motin 	if (remaining < (int)sizeof(ACPI_HEST_HEADER))
728ebc22d04SAlexander Motin 		return (-1);
729ebc22d04SAlexander Motin 
730ebc22d04SAlexander Motin 	printf("\n\tType=%d\n", hdr->Type);
731ebc22d04SAlexander Motin 	printf("\tSourceId=%d\n", hdr->SourceId);
732ebc22d04SAlexander Motin 	switch (hdr->Type) {
733ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_IA32_CHECK: {
734ebc22d04SAlexander Motin 		ACPI_HEST_IA_MACHINE_CHECK *s = addr;
735ebc22d04SAlexander Motin 		printf("\tFlags=%02x\n", s->Flags);
736ebc22d04SAlexander Motin 		printf("\tEnabled=%d\n", s->Enabled);
737ebc22d04SAlexander Motin 		printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
738ebc22d04SAlexander Motin 		printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
739ebc22d04SAlexander Motin 		printf("\tGlobalCapabilityData=%jd\n", s->GlobalCapabilityData);
740ebc22d04SAlexander Motin 		printf("\tGlobalControlData=%jd\n", s->GlobalControlData);
741ebc22d04SAlexander Motin 		printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
742ebc22d04SAlexander Motin 		for (i = 0; i < s->NumHardwareBanks; i++) {
743ebc22d04SAlexander Motin 			acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
744ebc22d04SAlexander Motin 			    (s + 1) + i);
745ebc22d04SAlexander Motin 		}
746ebc22d04SAlexander Motin 		return (sizeof(*s) + s->NumHardwareBanks *
747ebc22d04SAlexander Motin 		    sizeof(ACPI_HEST_IA_ERROR_BANK));
748ebc22d04SAlexander Motin 	}
749ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: {
750ebc22d04SAlexander Motin 		ACPI_HEST_IA_CORRECTED *s = addr;
751ebc22d04SAlexander Motin 		printf("\tFlags=%02x\n", s->Flags);
752ebc22d04SAlexander Motin 		printf("\tEnabled=%d\n", s->Enabled);
753ebc22d04SAlexander Motin 		printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
754ebc22d04SAlexander Motin 		printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
755ebc22d04SAlexander Motin 		printf("\tNotify:\n");
756ebc22d04SAlexander Motin 		acpi_print_hest_notify(&s->Notify);
757ebc22d04SAlexander Motin 		printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
758ebc22d04SAlexander Motin 		for (i = 0; i < s->NumHardwareBanks; i++) {
759ebc22d04SAlexander Motin 			acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
760ebc22d04SAlexander Motin 			    (s + 1) + i);
761ebc22d04SAlexander Motin 		}
762ebc22d04SAlexander Motin 		return (sizeof(*s) + s->NumHardwareBanks *
763ebc22d04SAlexander Motin 		    sizeof(ACPI_HEST_IA_ERROR_BANK));
764ebc22d04SAlexander Motin 	}
765ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_IA32_NMI: {
766ebc22d04SAlexander Motin 		ACPI_HEST_IA_NMI *s = addr;
767ebc22d04SAlexander Motin 		printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
768ebc22d04SAlexander Motin 		printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
769ebc22d04SAlexander Motin 		printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
770ebc22d04SAlexander Motin 		return (sizeof(*s));
771ebc22d04SAlexander Motin 	}
772ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_AER_ROOT_PORT: {
773ebc22d04SAlexander Motin 		ACPI_HEST_AER_ROOT *s = addr;
774ebc22d04SAlexander Motin 		acpi_print_hest_aer(&s->Aer);
775ebc22d04SAlexander Motin 		printf("\tRootErrorCommand=%d\n", s->RootErrorCommand);
776ebc22d04SAlexander Motin 		return (sizeof(*s));
777ebc22d04SAlexander Motin 	}
778ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_AER_ENDPOINT: {
779ebc22d04SAlexander Motin 		ACPI_HEST_AER *s = addr;
780ebc22d04SAlexander Motin 		acpi_print_hest_aer(&s->Aer);
781ebc22d04SAlexander Motin 		return (sizeof(*s));
782ebc22d04SAlexander Motin 	}
783ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_AER_BRIDGE: {
784ebc22d04SAlexander Motin 		ACPI_HEST_AER_BRIDGE *s = addr;
785ebc22d04SAlexander Motin 		acpi_print_hest_aer(&s->Aer);
786ebc22d04SAlexander Motin 		printf("\tUncorrectableMask2=%d\n", s->UncorrectableMask2);
787ebc22d04SAlexander Motin 		printf("\tUncorrectableSeverity2=%d\n", s->UncorrectableSeverity2);
788ebc22d04SAlexander Motin 		printf("\tAdvancedCapabilities2=%d\n", s->AdvancedCapabilities2);
789ebc22d04SAlexander Motin 		return (sizeof(*s));
790ebc22d04SAlexander Motin 	}
791ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_GENERIC_ERROR: {
792ebc22d04SAlexander Motin 		ACPI_HEST_GENERIC *s = addr;
793ebc22d04SAlexander Motin 		printf("\tRelatedSourceId=%d\n", s->RelatedSourceId);
794ebc22d04SAlexander Motin 		printf("\tEnabled=%d\n", s->Enabled);
795ebc22d04SAlexander Motin 		printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
796ebc22d04SAlexander Motin 		printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
797ebc22d04SAlexander Motin 		printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
798ebc22d04SAlexander Motin 		printf("\tErrorStatusAddress=");
799ebc22d04SAlexander Motin 		acpi_print_gas(&s->ErrorStatusAddress);
800ebc22d04SAlexander Motin 		printf("\n");
801ebc22d04SAlexander Motin 		printf("\tNotify:\n");
802ebc22d04SAlexander Motin 		acpi_print_hest_notify(&s->Notify);
803ebc22d04SAlexander Motin 		printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength);
804ebc22d04SAlexander Motin 		return (sizeof(*s));
805ebc22d04SAlexander Motin 	}
806ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_GENERIC_ERROR_V2: {
807ebc22d04SAlexander Motin 		ACPI_HEST_GENERIC_V2 *s = addr;
808ebc22d04SAlexander Motin 		printf("\tRelatedSourceId=%d\n", s->RelatedSourceId);
809ebc22d04SAlexander Motin 		printf("\tEnabled=%d\n", s->Enabled);
810ebc22d04SAlexander Motin 		printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
811ebc22d04SAlexander Motin 		printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
812ebc22d04SAlexander Motin 		printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
813ebc22d04SAlexander Motin 		printf("\tErrorStatusAddress=");
814ebc22d04SAlexander Motin 		acpi_print_gas(&s->ErrorStatusAddress);
815ebc22d04SAlexander Motin 		printf("\n");
816ebc22d04SAlexander Motin 		printf("\tNotify:\n");
817ebc22d04SAlexander Motin 		acpi_print_hest_notify(&s->Notify);
818ebc22d04SAlexander Motin 		printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength);
819ebc22d04SAlexander Motin 		printf("\tReadAckRegister=");
820ebc22d04SAlexander Motin 		acpi_print_gas(&s->ReadAckRegister);
821ebc22d04SAlexander Motin 		printf("\n");
822ebc22d04SAlexander Motin 		printf("\tReadAckPreserve=%jd\n", s->ReadAckPreserve);
823ebc22d04SAlexander Motin 		printf("\tReadAckWrite=%jd\n", s->ReadAckWrite);
824ebc22d04SAlexander Motin 		return (sizeof(*s));
825ebc22d04SAlexander Motin 	}
826ebc22d04SAlexander Motin 	case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: {
827ebc22d04SAlexander Motin 		ACPI_HEST_IA_DEFERRED_CHECK *s = addr;
828ebc22d04SAlexander Motin 		printf("\tFlags=%02x\n", s->Flags);
829ebc22d04SAlexander Motin 		printf("\tEnabled=%d\n", s->Enabled);
830ebc22d04SAlexander Motin 		printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
831ebc22d04SAlexander Motin 		printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
832ebc22d04SAlexander Motin 		printf("\tNotify:\n");
833ebc22d04SAlexander Motin 		acpi_print_hest_notify(&s->Notify);
834ebc22d04SAlexander Motin 		printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
835ebc22d04SAlexander Motin 		for (i = 0; i < s->NumHardwareBanks; i++) {
836ebc22d04SAlexander Motin 			acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
837ebc22d04SAlexander Motin 			    (s + 1) + i);
838ebc22d04SAlexander Motin 		}
839ebc22d04SAlexander Motin 		return (sizeof(*s) + s->NumHardwareBanks *
840ebc22d04SAlexander Motin 		    sizeof(ACPI_HEST_IA_ERROR_BANK));
841ebc22d04SAlexander Motin 	}
842ebc22d04SAlexander Motin 	default:
843ebc22d04SAlexander Motin 		return (-1);
844ebc22d04SAlexander Motin 	}
845ebc22d04SAlexander Motin }
846ebc22d04SAlexander Motin 
847ebc22d04SAlexander Motin static void
848ebc22d04SAlexander Motin acpi_handle_hest(ACPI_TABLE_HEADER *sdp)
849ebc22d04SAlexander Motin {
850ebc22d04SAlexander Motin 	char *cp;
851ebc22d04SAlexander Motin 	int remaining, consumed;
852ebc22d04SAlexander Motin 	ACPI_TABLE_HEST *hest;
853ebc22d04SAlexander Motin 
854ebc22d04SAlexander Motin 	printf(BEGIN_COMMENT);
855ebc22d04SAlexander Motin 	acpi_print_sdt(sdp);
856ebc22d04SAlexander Motin 	hest = (ACPI_TABLE_HEST *)sdp;
857ebc22d04SAlexander Motin 	printf("\tErrorSourceCount=%d\n", hest->ErrorSourceCount);
858ebc22d04SAlexander Motin 
859ebc22d04SAlexander Motin 	remaining = sdp->Length - sizeof(ACPI_TABLE_HEST);
860ebc22d04SAlexander Motin 	while (remaining > 0) {
861ebc22d04SAlexander Motin 		cp = (char *)sdp + sdp->Length - remaining;
862ebc22d04SAlexander Motin 		consumed = acpi_handle_hest_structure(cp, remaining);
863ebc22d04SAlexander Motin 		if (consumed <= 0)
864ebc22d04SAlexander Motin 			break;
865ebc22d04SAlexander Motin 		else
866ebc22d04SAlexander Motin 			remaining -= consumed;
867ebc22d04SAlexander Motin 	}
868ebc22d04SAlexander Motin 	printf(END_COMMENT);
869ebc22d04SAlexander Motin }
870ebc22d04SAlexander Motin 
871ebc22d04SAlexander Motin static void
872986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
87379d7565cSPeter Wemm {
874986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
87579d7565cSPeter Wemm 
876773b6454SNate Lawson 	printf(BEGIN_COMMENT);
877773b6454SNate Lawson 	acpi_print_sdt(sdp);
878986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
879986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
88087f9f09aSTakanori Watanabe 	printf("\tADDR=");
881986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
882ebc22d04SAlexander Motin 	printf("\n\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
883986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
884986dffafSJohn Baldwin 	    8);
885986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
886986dffafSJohn Baldwin 	    1 : 0);
88779d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
888986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
88979d7565cSPeter Wemm 		printf("TRUE}\n");
89079d7565cSPeter Wemm 	else
89179d7565cSPeter Wemm 		printf("FALSE}\n");
892986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
893986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
8949785e979SNeel Natu 	printf("\tFlags=0x%02x\n", hpet->Flags);
89579d7565cSPeter Wemm 	printf(END_COMMENT);
89679d7565cSPeter Wemm }
89779d7565cSPeter Wemm 
89879d7565cSPeter Wemm static void
899986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
90055d7ff9eSNate Lawson {
901986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
90255d7ff9eSNate Lawson 
90355d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
90455d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
905986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
90655d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
907986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
90855d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
909986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
910986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
911986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
912986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
91355d7ff9eSNate Lawson 	printf(END_COMMENT);
91455d7ff9eSNate Lawson }
91555d7ff9eSNate Lawson 
91655d7ff9eSNate Lawson static void
917986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
918a47e681bSScott Long {
919986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
920986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
921986dffafSJohn Baldwin 	u_int i, entries;
922a47e681bSScott Long 
923a47e681bSScott Long 	printf(BEGIN_COMMENT);
924a47e681bSScott Long 	acpi_print_sdt(sdp);
925986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
926986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
927986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
928986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
929986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
930a47e681bSScott Long 		printf("\n");
9310c10b85aSJung-uk Kim 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
932986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
933986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
934986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
935a47e681bSScott Long 	}
936a47e681bSScott Long 	printf(END_COMMENT);
937a47e681bSScott Long }
938a47e681bSScott Long 
939a47e681bSScott Long static void
94033866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
94133866658SJohn Baldwin {
94233866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
94333866658SJohn Baldwin 	UINT64 i, j;
94433866658SJohn Baldwin 
94533866658SJohn Baldwin 	printf(BEGIN_COMMENT);
94633866658SJohn Baldwin 	acpi_print_sdt(sdp);
94733866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
9480c10b85aSJung-uk Kim 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
94933866658SJohn Baldwin 	printf("\n\t      ");
95033866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
9510c10b85aSJung-uk Kim 		printf(" %3ju", (uintmax_t)i);
95233866658SJohn Baldwin 	printf("\n\t     +");
95333866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
95433866658SJohn Baldwin 		printf("----");
95533866658SJohn Baldwin 	printf("\n");
95633866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
9570c10b85aSJung-uk Kim 		printf("\t %3ju |", (uintmax_t)i);
95833866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
95933866658SJohn Baldwin 			printf(" %3d",
96033866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
96133866658SJohn Baldwin 		printf("\n");
96233866658SJohn Baldwin 	}
96333866658SJohn Baldwin 	printf(END_COMMENT);
96433866658SJohn Baldwin }
96533866658SJohn Baldwin 
96633866658SJohn Baldwin static void
967ed26c389SScott Long acpi_handle_wddt(ACPI_TABLE_HEADER *sdp)
968ed26c389SScott Long {
969ed26c389SScott Long 	ACPI_TABLE_WDDT *wddt;
970ed26c389SScott Long 
971ed26c389SScott Long 	printf(BEGIN_COMMENT);
972ed26c389SScott Long 	acpi_print_sdt(sdp);
973ed26c389SScott Long 	wddt = (ACPI_TABLE_WDDT *)sdp;
974ed26c389SScott Long 	printf("\tSpecVersion=0x%04x, TableVersion=0x%04x\n",
975ed26c389SScott Long 	    wddt->SpecVersion, wddt->TableVersion);
976ed26c389SScott Long 	printf("\tPciVendorId=0x%04x, Address=", wddt->PciVendorId);
977ed26c389SScott Long 	acpi_print_gas(&wddt->Address);
978ed26c389SScott Long 	printf("\n\tMaxCount=%u, MinCount=%u, Period=%ums\n",
979ed26c389SScott Long 	    wddt->MaxCount, wddt->MinCount, wddt->Period);
980ed26c389SScott Long 
981ed26c389SScott Long #define	PRINTFLAG(var, flag)	printflag((var), ACPI_WDDT_## flag, #flag)
982ed26c389SScott Long 	printf("\tStatus=");
983ed26c389SScott Long 	PRINTFLAG(wddt->Status, AVAILABLE);
984ed26c389SScott Long 	PRINTFLAG(wddt->Status, ACTIVE);
985ed26c389SScott Long 	PRINTFLAG(wddt->Status, TCO_OS_OWNED);
986ed26c389SScott Long 	PRINTFLAG(wddt->Status, USER_RESET);
987ed26c389SScott Long 	PRINTFLAG(wddt->Status, WDT_RESET);
988ed26c389SScott Long 	PRINTFLAG(wddt->Status, POWER_FAIL);
989ed26c389SScott Long 	PRINTFLAG(wddt->Status, UNKNOWN_RESET);
990ed26c389SScott Long 	PRINTFLAG_END();
991ed26c389SScott Long 	printf("\tCapability=");
992ed26c389SScott Long 	PRINTFLAG(wddt->Capability, AUTO_RESET);
993ed26c389SScott Long 	PRINTFLAG(wddt->Capability, ALERT_SUPPORT);
994ed26c389SScott Long 	PRINTFLAG_END();
995ed26c389SScott Long #undef PRINTFLAG
996ed26c389SScott Long 
997ed26c389SScott Long 	printf(END_COMMENT);
998ed26c389SScott Long }
999ed26c389SScott Long 
1000ed26c389SScott Long static void
10015857fba5SBen Widawsky acpi_print_native_lpit(ACPI_LPIT_NATIVE *nl)
10025857fba5SBen Widawsky {
10035857fba5SBen Widawsky 	printf("\tEntryTrigger=");
10045857fba5SBen Widawsky 	acpi_print_gas(&nl->EntryTrigger);
1005ebc22d04SAlexander Motin 	printf("\n\tResidency=%u\n", nl->Residency);
10065857fba5SBen Widawsky 	printf("\tLatency=%u\n", nl->Latency);
10075857fba5SBen Widawsky 	if (nl->Header.Flags & ACPI_LPIT_NO_COUNTER)
10085857fba5SBen Widawsky 		printf("\tResidencyCounter=Not Present");
10095857fba5SBen Widawsky 	else {
10105857fba5SBen Widawsky 		printf("\tResidencyCounter=");
10115857fba5SBen Widawsky 		acpi_print_gas(&nl->ResidencyCounter);
1012ebc22d04SAlexander Motin 		printf("\n");
10135857fba5SBen Widawsky 	}
10145857fba5SBen Widawsky 	if (nl->CounterFrequency)
10155857fba5SBen Widawsky 		printf("\tCounterFrequency=%ju\n", nl->CounterFrequency);
10165857fba5SBen Widawsky 	else
10175857fba5SBen Widawsky 		printf("\tCounterFrequency=TSC\n");
10185857fba5SBen Widawsky }
10195857fba5SBen Widawsky 
10205857fba5SBen Widawsky static void
10215857fba5SBen Widawsky acpi_print_lpit(ACPI_LPIT_HEADER *lpit)
10225857fba5SBen Widawsky {
10235857fba5SBen Widawsky 	if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
10245857fba5SBen Widawsky 		printf("\tType=ACPI_LPIT_TYPE_NATIVE_CSTATE\n");
10255857fba5SBen Widawsky 	else
10265857fba5SBen Widawsky 		warnx("unknown LPIT type %u", lpit->Type);
10275857fba5SBen Widawsky 
10285857fba5SBen Widawsky 	printf("\tLength=%u\n", lpit->Length);
10295857fba5SBen Widawsky 	printf("\tUniqueId=0x%04x\n", lpit->UniqueId);
10305857fba5SBen Widawsky #define	PRINTFLAG(var, flag)	printflag((var), ACPI_LPIT_## flag, #flag)
10315857fba5SBen Widawsky 	printf("\tFlags=");
10325857fba5SBen Widawsky 	PRINTFLAG(lpit->Flags, STATE_DISABLED);
10335857fba5SBen Widawsky 	PRINTFLAG_END();
10345857fba5SBen Widawsky #undef PRINTFLAG
10355857fba5SBen Widawsky 
10365857fba5SBen Widawsky 	if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
10375857fba5SBen Widawsky 		return acpi_print_native_lpit((ACPI_LPIT_NATIVE *)lpit);
10385857fba5SBen Widawsky }
10395857fba5SBen Widawsky 
10405857fba5SBen Widawsky static void
10415857fba5SBen Widawsky acpi_walk_lpit(ACPI_TABLE_HEADER *table, void *first,
10425857fba5SBen Widawsky     void (*action)(ACPI_LPIT_HEADER *))
10435857fba5SBen Widawsky {
10445857fba5SBen Widawsky 	ACPI_LPIT_HEADER *subtable;
10455857fba5SBen Widawsky 	char *end;
10465857fba5SBen Widawsky 
10475857fba5SBen Widawsky 	subtable = first;
10485857fba5SBen Widawsky 	end = (char *)table + table->Length;
10495857fba5SBen Widawsky 	while ((char *)subtable < end) {
10505857fba5SBen Widawsky 		printf("\n");
10515857fba5SBen Widawsky 		if (subtable->Length < sizeof(ACPI_LPIT_HEADER)) {
10525857fba5SBen Widawsky 			warnx("invalid subtable length %u", subtable->Length);
10535857fba5SBen Widawsky 			return;
10545857fba5SBen Widawsky 		}
10555857fba5SBen Widawsky 		action(subtable);
10565857fba5SBen Widawsky 		subtable = (ACPI_LPIT_HEADER *)((char *)subtable +
10575857fba5SBen Widawsky 		    subtable->Length);
10585857fba5SBen Widawsky 	}
10595857fba5SBen Widawsky }
10605857fba5SBen Widawsky 
10615857fba5SBen Widawsky static void
10625857fba5SBen Widawsky acpi_handle_lpit(ACPI_TABLE_HEADER *sdp)
10635857fba5SBen Widawsky {
10645857fba5SBen Widawsky 	ACPI_TABLE_LPIT *lpit;
10655857fba5SBen Widawsky 
10665857fba5SBen Widawsky 	printf(BEGIN_COMMENT);
10675857fba5SBen Widawsky 	acpi_print_sdt(sdp);
10685857fba5SBen Widawsky 	lpit = (ACPI_TABLE_LPIT *)sdp;
10695857fba5SBen Widawsky 	acpi_walk_lpit(sdp, (lpit + 1), acpi_print_lpit);
10705857fba5SBen Widawsky 
10715857fba5SBen Widawsky 	printf(END_COMMENT);
10725857fba5SBen Widawsky }
10735857fba5SBen Widawsky 
10745857fba5SBen Widawsky static void
1075a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
1076a0333ad1SJohn Baldwin     uint32_t flags)
1077a0333ad1SJohn Baldwin {
1078a0333ad1SJohn Baldwin 
1079a0333ad1SJohn Baldwin 	printf("\tFlags={");
1080a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
1081a0333ad1SJohn Baldwin 		printf("ENABLED");
1082a0333ad1SJohn Baldwin 	else
1083a0333ad1SJohn Baldwin 		printf("DISABLED");
1084a0333ad1SJohn Baldwin 	printf("}\n");
1085a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
1086a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
1087a0333ad1SJohn Baldwin }
1088a0333ad1SJohn Baldwin 
1089c031c93bSTakanori Watanabe static char *
1090c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
1091c031c93bSTakanori Watanabe {
1092c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
1093c031c93bSTakanori Watanabe 	char *eventname = NULL;
1094c031c93bSTakanori Watanabe 
1095c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
1096c031c93bSTakanori Watanabe 
1097c031c93bSTakanori Watanabe 	switch(event->event_type) {
1098c031c93bSTakanori Watanabe 	case PREBOOT:
1099c031c93bSTakanori Watanabe 	case POST_CODE:
1100c031c93bSTakanori Watanabe 	case UNUSED:
1101c031c93bSTakanori Watanabe 	case NO_ACTION:
1102c031c93bSTakanori Watanabe 	case SEPARATOR:
1103c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
1104c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
1105c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
1106c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
1107c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
1108c031c93bSTakanori Watanabe 	case COMPACT_HASH:
1109c031c93bSTakanori Watanabe 	case IPL:
1110c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
1111c031c93bSTakanori Watanabe 	case NONHOST_CODE:
1112c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
1113c031c93bSTakanori Watanabe 	case NONHOST_INFO:
1114c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
1115c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
1116c031c93bSTakanori Watanabe 		break;
1117c031c93bSTakanori Watanabe 
1118c031c93bSTakanori Watanabe 	case ACTION:
1119c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
1120c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
1121c031c93bSTakanori Watanabe 		break;
1122c031c93bSTakanori Watanabe 
1123c031c93bSTakanori Watanabe 	case EVENT_TAG:
1124c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
1125c031c93bSTakanori Watanabe 		case SMBIOS:
1126c031c93bSTakanori Watanabe 		case BIS_CERT:
1127c031c93bSTakanori Watanabe 		case CMOS:
1128c031c93bSTakanori Watanabe 		case NVRAM:
1129c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
1130c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
1131c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
1132c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
1133c031c93bSTakanori Watanabe 		case ESCD:
1134c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
1135c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
1136c031c93bSTakanori Watanabe 		case POST_CONTENTS:
1137c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
1138c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
1139c031c93bSTakanori Watanabe 			break;
1140c031c93bSTakanori Watanabe 
1141c031c93bSTakanori Watanabe 		default:
1142c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
1143c031c93bSTakanori Watanabe 			    pc_event->event_id);
1144c031c93bSTakanori Watanabe 			break;
1145c031c93bSTakanori Watanabe 		}
1146c031c93bSTakanori Watanabe 		break;
1147c031c93bSTakanori Watanabe 
1148c031c93bSTakanori Watanabe 	default:
1149c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
1150c031c93bSTakanori Watanabe 		break;
1151c031c93bSTakanori Watanabe 	}
1152c031c93bSTakanori Watanabe 
1153c031c93bSTakanori Watanabe 	return eventname;
1154c031c93bSTakanori Watanabe }
1155c031c93bSTakanori Watanabe 
1156c031c93bSTakanori Watanabe static void
1157c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
1158c031c93bSTakanori Watanabe {
1159c031c93bSTakanori Watanabe 	int i;
1160c031c93bSTakanori Watanabe 	char *eventname;
1161c031c93bSTakanori Watanabe 
1162c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
1163c031c93bSTakanori Watanabe 
1164c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
1165c031c93bSTakanori Watanabe 	printf(" 0x");
1166c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
1167c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
1168c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
1169c031c93bSTakanori Watanabe 
1170c031c93bSTakanori Watanabe 	free(eventname);
1171c031c93bSTakanori Watanabe }
1172c031c93bSTakanori Watanabe 
1173c031c93bSTakanori Watanabe static void
1174c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
1175c031c93bSTakanori Watanabe {
1176c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
1177c031c93bSTakanori Watanabe 	struct TCPAevent *event;
1178977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
1179c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
1180c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
1181c031c93bSTakanori Watanabe 
1182c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
1183c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
1184c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
1185c031c93bSTakanori Watanabe 
1186c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
1187c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
1188c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
1189c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
1190c031c93bSTakanori Watanabe 		break;
1191c031c93bSTakanori Watanabe 
1192c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
1193c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
1194c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
1195c031c93bSTakanori Watanabe 		break;
1196c031c93bSTakanori Watanabe 
1197c031c93bSTakanori Watanabe 	default:
1198c031c93bSTakanori Watanabe 		printf("XXX");
1199c031c93bSTakanori Watanabe 		printf(END_COMMENT);
1200c031c93bSTakanori Watanabe 		return;
1201c031c93bSTakanori Watanabe 	}
12020e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
1203c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
1204c031c93bSTakanori Watanabe 
1205c031c93bSTakanori Watanabe 	if (len == 0) {
1206c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
1207c031c93bSTakanori Watanabe 		printf(END_COMMENT);
1208c031c93bSTakanori Watanabe 		return;
1209c031c93bSTakanori Watanabe 	}
12102ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
12112ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
12122ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
12132ef23c6dSTakanori Watanabe 		return;
12142ef23c6dSTakanori Watanabe 	}
1215c031c93bSTakanori Watanabe 
1216c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
1217c031c93bSTakanori Watanabe 	vend = vaddr + len;
1218c031c93bSTakanori Watanabe 
1219c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
12202ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
12212ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
1222c031c93bSTakanori Watanabe 			break;
12230e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
1224c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
1225c031c93bSTakanori Watanabe 			break;
12262ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
12272ef23c6dSTakanori Watanabe 			break;
1228c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
1229c031c93bSTakanori Watanabe 			break;
1230c031c93bSTakanori Watanabe #if 0
1231c031c93bSTakanori Watanabe 		{
1232c031c93bSTakanori Watanabe 		unsigned int i, j, k;
1233c031c93bSTakanori Watanabe 
1234c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
1235c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
1236c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
1237c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
1238c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
1239c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
1240c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
1241c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
1242c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
1243c031c93bSTakanori Watanabe 				j = i + 1;
1244c031c93bSTakanori Watanabe 			}
1245c031c93bSTakanori Watanabe 		}
1246c031c93bSTakanori Watanabe 		printf("\n"); }
1247c031c93bSTakanori Watanabe #endif
1248c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
1249c031c93bSTakanori Watanabe 
1250c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
1251c031c93bSTakanori Watanabe 	}
1252c031c93bSTakanori Watanabe 
1253c031c93bSTakanori Watanabe 	printf(END_COMMENT);
1254c031c93bSTakanori Watanabe }
1255877fc2e3STakanori Watanabe static void acpi_handle_tpm2(ACPI_TABLE_HEADER *sdp)
1256877fc2e3STakanori Watanabe {
1257877fc2e3STakanori Watanabe 	ACPI_TABLE_TPM2 *tpm2;
1258877fc2e3STakanori Watanabe 
1259877fc2e3STakanori Watanabe 	printf (BEGIN_COMMENT);
1260877fc2e3STakanori Watanabe 	acpi_print_sdt(sdp);
1261877fc2e3STakanori Watanabe 	tpm2 = (ACPI_TABLE_TPM2 *) sdp;
12627aef7138SCy Schubert 	printf ("\t\tControlArea=%jx\n", tpm2->ControlAddress);
1263877fc2e3STakanori Watanabe 	printf ("\t\tStartMethod=%x\n", tpm2->StartMethod);
1264877fc2e3STakanori Watanabe 	printf (END_COMMENT);
1265877fc2e3STakanori Watanabe }
1266c031c93bSTakanori Watanabe 
1267ec650989SNeel Natu static const char *
1268ec650989SNeel Natu devscope_type2str(int type)
1269ec650989SNeel Natu {
1270ec650989SNeel Natu 	static char typebuf[16];
1271ec650989SNeel Natu 
1272ec650989SNeel Natu 	switch (type) {
1273ec650989SNeel Natu 	case 1:
1274ec650989SNeel Natu 		return ("PCI Endpoint Device");
1275ec650989SNeel Natu 	case 2:
1276ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
1277ec650989SNeel Natu 	case 3:
1278ec650989SNeel Natu 		return ("IOAPIC");
1279ec650989SNeel Natu 	case 4:
1280ec650989SNeel Natu 		return ("HPET");
1281ec650989SNeel Natu 	default:
1282ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
1283ec650989SNeel Natu 		return (typebuf);
1284ec650989SNeel Natu 	}
1285ec650989SNeel Natu }
1286ec650989SNeel Natu 
1287ec650989SNeel Natu static int
1288ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
1289ec650989SNeel Natu {
1290ec650989SNeel Natu 	char sep;
1291ec650989SNeel Natu 	int pathlen;
1292ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
1293ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
1294ec650989SNeel Natu 
1295ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
1296ec650989SNeel Natu 		return (-1);
1297ec650989SNeel Natu 
1298ec650989SNeel Natu 	if (remaining < devscope->Length)
1299ec650989SNeel Natu 		return (-1);
1300ec650989SNeel Natu 
1301ec650989SNeel Natu 	printf("\n");
1302ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
1303ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
1304ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
1305ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
1306ec650989SNeel Natu 
1307ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
1308ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
1309ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
1310ec650989SNeel Natu 	if (path < pathend) {
1311ec650989SNeel Natu 		sep = '{';
1312ec650989SNeel Natu 		printf("\t\tPath=");
1313ec650989SNeel Natu 		do {
1314ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
1315ec650989SNeel Natu 			sep=',';
1316ec650989SNeel Natu 			path++;
1317ec650989SNeel Natu 		} while (path < pathend);
1318ec650989SNeel Natu 		printf("}\n");
1319ec650989SNeel Natu 	}
1320ec650989SNeel Natu 
1321ec650989SNeel Natu 	return (devscope->Length);
1322ec650989SNeel Natu }
1323ec650989SNeel Natu 
1324ec650989SNeel Natu static void
1325ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
1326ec650989SNeel Natu {
1327ec650989SNeel Natu 	char *cp;
1328ec650989SNeel Natu 	int remaining, consumed;
1329ec650989SNeel Natu 
1330ec650989SNeel Natu 	printf("\n");
1331ec650989SNeel Natu 	printf("\tType=DRHD\n");
1332ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
1333ec650989SNeel Natu 
1334ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1335ec650989SNeel Natu 
1336ec650989SNeel Natu 	printf("\tFlags=");
1337ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
1338ec650989SNeel Natu 	PRINTFLAG_END();
1339ec650989SNeel Natu 
1340ec650989SNeel Natu #undef PRINTFLAG
1341ec650989SNeel Natu 
1342ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
13437d369c6eSJung-uk Kim 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
1344ec650989SNeel Natu 
1345ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
1346ec650989SNeel Natu 	if (remaining > 0)
1347ec650989SNeel Natu 		printf("\tDevice Scope:");
1348ec650989SNeel Natu 	while (remaining > 0) {
1349ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
1350ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1351ec650989SNeel Natu 		if (consumed <= 0)
1352ec650989SNeel Natu 			break;
1353ec650989SNeel Natu 		else
1354ec650989SNeel Natu 			remaining -= consumed;
1355ec650989SNeel Natu 	}
1356ec650989SNeel Natu }
1357ec650989SNeel Natu 
1358ec650989SNeel Natu static void
1359ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
1360ec650989SNeel Natu {
1361ec650989SNeel Natu 	char *cp;
1362ec650989SNeel Natu 	int remaining, consumed;
1363ec650989SNeel Natu 
1364ec650989SNeel Natu 	printf("\n");
1365ec650989SNeel Natu 	printf("\tType=RMRR\n");
1366ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
1367ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
13687d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
13697d369c6eSJung-uk Kim 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
1370ec650989SNeel Natu 
1371ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
1372ec650989SNeel Natu 	if (remaining > 0)
1373ec650989SNeel Natu 		printf("\tDevice Scope:");
1374ec650989SNeel Natu 	while (remaining > 0) {
1375ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
1376ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1377ec650989SNeel Natu 		if (consumed <= 0)
1378ec650989SNeel Natu 			break;
1379ec650989SNeel Natu 		else
1380ec650989SNeel Natu 			remaining -= consumed;
1381ec650989SNeel Natu 	}
1382ec650989SNeel Natu }
1383ec650989SNeel Natu 
1384ec650989SNeel Natu static void
1385ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
1386ec650989SNeel Natu {
1387ec650989SNeel Natu 	char *cp;
1388ec650989SNeel Natu 	int remaining, consumed;
1389ec650989SNeel Natu 
1390ec650989SNeel Natu 	printf("\n");
1391ec650989SNeel Natu 	printf("\tType=ATSR\n");
1392ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
1393ec650989SNeel Natu 
1394ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1395ec650989SNeel Natu 
1396ec650989SNeel Natu 	printf("\tFlags=");
1397ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
1398ec650989SNeel Natu 	PRINTFLAG_END();
1399ec650989SNeel Natu 
1400ec650989SNeel Natu #undef PRINTFLAG
1401ec650989SNeel Natu 
1402ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
1403ec650989SNeel Natu 
1404ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
1405ec650989SNeel Natu 	if (remaining > 0)
1406ec650989SNeel Natu 		printf("\tDevice Scope:");
1407ec650989SNeel Natu 	while (remaining > 0) {
1408ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
1409ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1410ec650989SNeel Natu 		if (consumed <= 0)
1411ec650989SNeel Natu 			break;
1412ec650989SNeel Natu 		else
1413ec650989SNeel Natu 			remaining -= consumed;
1414ec650989SNeel Natu 	}
1415ec650989SNeel Natu }
1416ec650989SNeel Natu 
1417ec650989SNeel Natu static void
1418ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
1419ec650989SNeel Natu {
1420ec650989SNeel Natu 
1421ec650989SNeel Natu 	printf("\n");
1422ec650989SNeel Natu 	printf("\tType=RHSA\n");
1423ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
14247d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
1425ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
1426ec650989SNeel Natu }
1427ec650989SNeel Natu 
1428ec650989SNeel Natu static int
1429ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
1430ec650989SNeel Natu {
1431ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
1432ec650989SNeel Natu 
1433ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
1434ec650989SNeel Natu 		return (-1);
1435ec650989SNeel Natu 
1436ec650989SNeel Natu 	if (remaining < hdr->Length)
1437ec650989SNeel Natu 		return (-1);
1438ec650989SNeel Natu 
1439ec650989SNeel Natu 	switch (hdr->Type) {
1440ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1441ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
1442ec650989SNeel Natu 		break;
1443ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1444ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
1445ec650989SNeel Natu 		break;
1446313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_ROOT_ATS:
1447ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
1448ec650989SNeel Natu 		break;
1449313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1450ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
1451ec650989SNeel Natu 		break;
1452ec650989SNeel Natu 	default:
1453ec650989SNeel Natu 		printf("\n");
1454ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
1455ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
1456ec650989SNeel Natu 		break;
1457ec650989SNeel Natu 	}
1458ec650989SNeel Natu 	return (hdr->Length);
1459ec650989SNeel Natu }
1460ec650989SNeel Natu 
1461ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1462ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
1463ec650989SNeel Natu #endif
1464ec650989SNeel Natu 
1465ec650989SNeel Natu static void
1466ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1467ec650989SNeel Natu {
1468ec650989SNeel Natu 	char *cp;
1469ec650989SNeel Natu 	int remaining, consumed;
1470ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
1471ec650989SNeel Natu 
1472ec650989SNeel Natu 	printf(BEGIN_COMMENT);
1473ec650989SNeel Natu 	acpi_print_sdt(sdp);
1474ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
1475ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
1476ec650989SNeel Natu 
1477ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1478ec650989SNeel Natu 
1479ec650989SNeel Natu 	printf("\tFlags=");
1480ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
1481ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1482ec650989SNeel Natu 	PRINTFLAG_END();
1483ec650989SNeel Natu 
1484ec650989SNeel Natu #undef PRINTFLAG
1485ec650989SNeel Natu 
1486ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1487ec650989SNeel Natu 	while (remaining > 0) {
1488ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
1489ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1490ec650989SNeel Natu 		if (consumed <= 0)
1491ec650989SNeel Natu 			break;
1492ec650989SNeel Natu 		else
1493ec650989SNeel Natu 			remaining -= consumed;
1494ec650989SNeel Natu 	}
1495ec650989SNeel Natu 
1496ec650989SNeel Natu 	printf(END_COMMENT);
1497ec650989SNeel Natu }
1498ec650989SNeel Natu 
1499a0333ad1SJohn Baldwin static void
1500986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1501a0333ad1SJohn Baldwin {
1502a0333ad1SJohn Baldwin 
1503a0333ad1SJohn Baldwin 	printf("\tFlags={");
1504986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1505a0333ad1SJohn Baldwin 		printf("ENABLED");
1506a0333ad1SJohn Baldwin 	else
1507a0333ad1SJohn Baldwin 		printf("DISABLED");
1508986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1509a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1510986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1511a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1512a0333ad1SJohn Baldwin 	printf("}\n");
1513986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1514986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1515986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1516a0333ad1SJohn Baldwin }
1517a0333ad1SJohn Baldwin 
151827941afaSEd Maste static const char *srat_types[] = {
151927941afaSEd Maste     [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
152027941afaSEd Maste     [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
152127941afaSEd Maste     [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
1522cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
1523cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GIC_ITS_AFFINITY] = "GIC ITS",
152427941afaSEd Maste };
1525a0333ad1SJohn Baldwin 
1526a0333ad1SJohn Baldwin static void
1527986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1528a0333ad1SJohn Baldwin {
1529986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1530986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
15312b2b1f42SAndrew Turner 	ACPI_SRAT_GICC_AFFINITY *gic;
1532a0333ad1SJohn Baldwin 
1533c86932b6SMarcelo Araujo 	if (srat->Type < nitems(srat_types))
1534986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1535a0333ad1SJohn Baldwin 	else
1536986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1537986dffafSJohn Baldwin 	switch (srat->Type) {
1538a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1539986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1540986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1541986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1542986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1543986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1544986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1545a0333ad1SJohn Baldwin 		break;
1546a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1547986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1548a0333ad1SJohn Baldwin 		break;
1549a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1550986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1551986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1552986dffafSJohn Baldwin 		    x2apic->Flags);
1553a0333ad1SJohn Baldwin 		break;
15542b2b1f42SAndrew Turner 	case ACPI_SRAT_TYPE_GICC_AFFINITY:
15552b2b1f42SAndrew Turner 		gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
15562b2b1f42SAndrew Turner 		acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
15572b2b1f42SAndrew Turner 		    gic->Flags);
15582b2b1f42SAndrew Turner 		break;
1559a0333ad1SJohn Baldwin 	}
1560a0333ad1SJohn Baldwin }
1561a0333ad1SJohn Baldwin 
1562a0333ad1SJohn Baldwin static void
1563986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1564a0333ad1SJohn Baldwin {
1565986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1566a0333ad1SJohn Baldwin 
1567a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1568a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1569986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1570986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1571986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1572a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1573a0333ad1SJohn Baldwin }
1574a0333ad1SJohn Baldwin 
1575340c0022SEd Maste static const char *nfit_types[] = {
1576340c0022SEd Maste     [ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
1577340c0022SEd Maste     [ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
1578340c0022SEd Maste     [ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
1579340c0022SEd Maste     [ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
1580340c0022SEd Maste     [ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
1581340c0022SEd Maste     [ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
15821b109c69SAlexander Motin     [ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address",
15831b109c69SAlexander Motin     [ACPI_NFIT_TYPE_CAPABILITIES] = "Platform Capabilities"
1584340c0022SEd Maste };
1585340c0022SEd Maste 
1586340c0022SEd Maste 
1587340c0022SEd Maste static void
1588340c0022SEd Maste acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
1589340c0022SEd Maste {
1590340c0022SEd Maste 	char *uuidstr;
15913b7935f3SAlexander Motin 	uint32_t m, status;
1592340c0022SEd Maste 
1593340c0022SEd Maste 	ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
1594340c0022SEd Maste 	ACPI_NFIT_MEMORY_MAP *mmap;
1595340c0022SEd Maste 	ACPI_NFIT_INTERLEAVE *ileave;
1596340c0022SEd Maste 	ACPI_NFIT_CONTROL_REGION *ctlreg;
1597340c0022SEd Maste 	ACPI_NFIT_DATA_REGION *datareg;
1598340c0022SEd Maste 	ACPI_NFIT_FLUSH_ADDRESS *fladdr;
15991b109c69SAlexander Motin 	ACPI_NFIT_CAPABILITIES *caps;
1600340c0022SEd Maste 
1601340c0022SEd Maste 	if (nfit->Type < nitems(nfit_types))
1602340c0022SEd Maste 		printf("\tType=%s\n", nfit_types[nfit->Type]);
1603340c0022SEd Maste 	else
1604340c0022SEd Maste 		printf("\tType=%u (unknown)\n", nfit->Type);
1605340c0022SEd Maste 	switch (nfit->Type) {
1606340c0022SEd Maste 	case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
1607340c0022SEd Maste 		sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
1608340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
1609340c0022SEd Maste 		printf("\tProximityDomain=%u\n",
1610340c0022SEd Maste 		    (u_int)sysaddr->ProximityDomain);
1611de937ecbSKonstantin Belousov 		uuid_to_string((uuid_t *)(uintptr_t)(sysaddr->RangeGuid),
1612340c0022SEd Maste 		    &uuidstr, &status);
1613340c0022SEd Maste 		if (status != uuid_s_ok)
1614340c0022SEd Maste 			errx(1, "uuid_to_string: status=%u", status);
1615340c0022SEd Maste 		printf("\tRangeGuid=%s\n", uuidstr);
1616340c0022SEd Maste 		free(uuidstr);
1617340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
1618340c0022SEd Maste 		printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
1619340c0022SEd Maste 		printf("\tMemoryMapping=0x%016jx\n",
1620340c0022SEd Maste 		    (uintmax_t)sysaddr->MemoryMapping);
1621340c0022SEd Maste 
1622340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1623340c0022SEd Maste 
1624340c0022SEd Maste 		printf("\tFlags=");
1625340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
1626340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
1627340c0022SEd Maste 		PRINTFLAG_END();
1628340c0022SEd Maste 
1629340c0022SEd Maste #undef PRINTFLAG
1630340c0022SEd Maste 
1631340c0022SEd Maste 		break;
1632340c0022SEd Maste 	case ACPI_NFIT_TYPE_MEMORY_MAP:
1633340c0022SEd Maste 		mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
163492d0d6bbSAlexander Motin 		printf("\tDeviceHandle=0x%x\n", (u_int)mmap->DeviceHandle);
163592d0d6bbSAlexander Motin 		printf("\tPhysicalId=0x%04x\n", (u_int)mmap->PhysicalId);
1636340c0022SEd Maste 		printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
1637340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
1638340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
1639340c0022SEd Maste 		printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
1640340c0022SEd Maste 		printf("\tRegionOffset=0x%016jx\n",
1641340c0022SEd Maste 		    (uintmax_t)mmap->RegionOffset);
1642340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
1643340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
1644fb1cf2a9SAlexander Motin 		printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
1645340c0022SEd Maste 
1646340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_MEM_## flag, #flag)
1647340c0022SEd Maste 
1648340c0022SEd Maste 		printf("\tFlags=");
1649340c0022SEd Maste 		PRINTFLAG(mmap->Flags, SAVE_FAILED);
1650340c0022SEd Maste 		PRINTFLAG(mmap->Flags, RESTORE_FAILED);
1651340c0022SEd Maste 		PRINTFLAG(mmap->Flags, FLUSH_FAILED);
1652340c0022SEd Maste 		PRINTFLAG(mmap->Flags, NOT_ARMED);
1653340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
1654340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
1655340c0022SEd Maste 		PRINTFLAG(mmap->Flags, MAP_FAILED);
1656340c0022SEd Maste 		PRINTFLAG_END();
1657340c0022SEd Maste 
1658340c0022SEd Maste #undef PRINTFLAG
1659340c0022SEd Maste 
1660340c0022SEd Maste 		break;
1661340c0022SEd Maste 	case ACPI_NFIT_TYPE_INTERLEAVE:
1662340c0022SEd Maste 		ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
1663340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n",
1664340c0022SEd Maste 		    (u_int)ileave->InterleaveIndex);
1665340c0022SEd Maste 		printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
1666340c0022SEd Maste 		printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
16673b7935f3SAlexander Motin 		for (m = 0; m < ileave->LineCount; m++) {
16683b7935f3SAlexander Motin 			printf("\tLine%uOffset=0x%08x\n", (u_int)m + 1,
16693b7935f3SAlexander Motin 			    (u_int)ileave->LineOffset[m]);
16703b7935f3SAlexander Motin 		}
1671340c0022SEd Maste 		break;
1672340c0022SEd Maste 	case ACPI_NFIT_TYPE_SMBIOS:
1673340c0022SEd Maste 		/* XXX smbios->Data[x] output is not supported */
1674340c0022SEd Maste 		break;
1675340c0022SEd Maste 	case ACPI_NFIT_TYPE_CONTROL_REGION:
1676340c0022SEd Maste 		ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
1677340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
1678340c0022SEd Maste 		printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
1679340c0022SEd Maste 		printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
168035e39fd9SAlexander Motin 		printf("\tRevisionId=0x%02x\n", (u_int)ctlreg->RevisionId);
1681340c0022SEd Maste 		printf("\tSubsystemVendorId=0x%04x\n",
1682340c0022SEd Maste 		    (u_int)ctlreg->SubsystemVendorId);
1683340c0022SEd Maste 		printf("\tSubsystemDeviceId=0x%04x\n",
1684340c0022SEd Maste 		    (u_int)ctlreg->SubsystemDeviceId);
168535e39fd9SAlexander Motin 		printf("\tSubsystemRevisionId=0x%02x\n",
1686340c0022SEd Maste 		    (u_int)ctlreg->SubsystemRevisionId);
1687d4c2de2eSAlexander Motin 		printf("\tValidFields=0x%02x\n", (u_int)ctlreg->ValidFields);
168835e39fd9SAlexander Motin 		printf("\tManufacturingLocation=0x%02x\n",
1689340c0022SEd Maste 		    (u_int)ctlreg->ManufacturingLocation);
169035e39fd9SAlexander Motin 		printf("\tManufacturingDate=%04x\n",
169135e39fd9SAlexander Motin 		    (u_int)be16toh(ctlreg->ManufacturingDate));
169235e39fd9SAlexander Motin 		printf("\tSerialNumber=%08X\n",
169335e39fd9SAlexander Motin 		    (u_int)be32toh(ctlreg->SerialNumber));
1694fb1cf2a9SAlexander Motin 		printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
1695340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
1696340c0022SEd Maste 		printf("\tWindowSize=0x%016jx\n",
1697340c0022SEd Maste 		    (uintmax_t)ctlreg->WindowSize);
1698340c0022SEd Maste 		printf("\tCommandOffset=0x%016jx\n",
1699340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandOffset);
1700340c0022SEd Maste 		printf("\tCommandSize=0x%016jx\n",
1701340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandSize);
1702340c0022SEd Maste 		printf("\tStatusOffset=0x%016jx\n",
1703340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusOffset);
1704340c0022SEd Maste 		printf("\tStatusSize=0x%016jx\n",
1705340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusSize);
1706340c0022SEd Maste 
1707340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1708340c0022SEd Maste 
1709340c0022SEd Maste 		printf("\tFlags=");
1710d4c2de2eSAlexander Motin 		PRINTFLAG(ctlreg->Flags, CONTROL_BUFFERED);
1711340c0022SEd Maste 		PRINTFLAG_END();
1712340c0022SEd Maste 
1713340c0022SEd Maste #undef PRINTFLAG
1714340c0022SEd Maste 
1715340c0022SEd Maste 		break;
1716340c0022SEd Maste 	case ACPI_NFIT_TYPE_DATA_REGION:
1717340c0022SEd Maste 		datareg = (ACPI_NFIT_DATA_REGION *)nfit;
1718340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
1719340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)datareg->Windows);
1720340c0022SEd Maste 		printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
1721340c0022SEd Maste 		printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
1722340c0022SEd Maste 		printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
1723340c0022SEd Maste 		printf("\tStartAddress=0x%016jx\n",
1724340c0022SEd Maste 		    (uintmax_t)datareg->StartAddress);
1725340c0022SEd Maste 		break;
1726340c0022SEd Maste 	case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
1727340c0022SEd Maste 		fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
1728340c0022SEd Maste 		printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
1729340c0022SEd Maste 		printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
17303b7935f3SAlexander Motin 		for (m = 0; m < fladdr->HintCount; m++) {
17313b7935f3SAlexander Motin 			printf("\tHintAddress%u=0x%016jx\n", (u_int)m + 1,
17323b7935f3SAlexander Motin 			    (uintmax_t)fladdr->HintAddress[m]);
17333b7935f3SAlexander Motin 		}
1734340c0022SEd Maste 		break;
17351b109c69SAlexander Motin 	case ACPI_NFIT_TYPE_CAPABILITIES:
17361b109c69SAlexander Motin 		caps = (ACPI_NFIT_CAPABILITIES *)nfit;
17371b109c69SAlexander Motin 		printf("\tHighestCapability=%u\n", (u_int)caps->HighestCapability);
17381b109c69SAlexander Motin 
17391b109c69SAlexander Motin #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_CAPABILITY_## flag, #flag)
17401b109c69SAlexander Motin 
17411b109c69SAlexander Motin 		printf("\tCapabilities=");
17421b109c69SAlexander Motin 		PRINTFLAG(caps->Capabilities, CACHE_FLUSH);
17431b109c69SAlexander Motin 		PRINTFLAG(caps->Capabilities, MEM_FLUSH);
17441b109c69SAlexander Motin 		PRINTFLAG(caps->Capabilities, MEM_MIRRORING);
17451b109c69SAlexander Motin 		PRINTFLAG_END();
17461b109c69SAlexander Motin 
17471b109c69SAlexander Motin #undef PRINTFLAG
17481b109c69SAlexander Motin 		break;
1749340c0022SEd Maste 	}
1750340c0022SEd Maste }
1751340c0022SEd Maste 
1752340c0022SEd Maste static void
1753340c0022SEd Maste acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
1754340c0022SEd Maste {
1755340c0022SEd Maste 	ACPI_TABLE_NFIT *nfit;
1756340c0022SEd Maste 
1757340c0022SEd Maste 	printf(BEGIN_COMMENT);
1758340c0022SEd Maste 	acpi_print_sdt(sdp);
1759340c0022SEd Maste 	nfit = (ACPI_TABLE_NFIT *)sdp;
1760340c0022SEd Maste 	acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
1761340c0022SEd Maste 	printf(END_COMMENT);
1762340c0022SEd Maste }
1763340c0022SEd Maste 
1764a0333ad1SJohn Baldwin static void
1765986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1766c62f1cccSMitsuru IWASAKI {
1767773b6454SNate Lawson 	printf("  ");
1768278f0de6SJung-uk Kim 	acpi_print_string(sdp->Signature, ACPI_NAMESEG_SIZE);
1769c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1770986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1771e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1772986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1773e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1774986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1775986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1776e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1777278f0de6SJung-uk Kim 	acpi_print_string(sdp->AslCompilerId, ACPI_NAMESEG_SIZE);
1778986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1779e1e9a4bfSMitsuru IWASAKI }
1780e1e9a4bfSMitsuru IWASAKI 
1781945137d9SNate Lawson static void
1782986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1783e1e9a4bfSMitsuru IWASAKI {
1784986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1785986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1786e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1787e1e9a4bfSMitsuru IWASAKI 
1788986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1789986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1790773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1791773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1792986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1793e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1794e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1795e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1796e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1797fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
17987d369c6eSJung-uk Kim 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1799fe1d0c2dSJung-uk Kim 		else
18007d369c6eSJung-uk Kim 			printf("0x%016jx",
18017d369c6eSJung-uk Kim 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1802e1e9a4bfSMitsuru IWASAKI 	}
1803e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1804c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1805e1e9a4bfSMitsuru IWASAKI }
1806e1e9a4bfSMitsuru IWASAKI 
18078e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
18088e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
18098e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
18108e6a8737SNate Lawson };
18118e6a8737SNate Lawson 
1812945137d9SNate Lawson static void
1813986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1814e1e9a4bfSMitsuru IWASAKI {
1815986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
18168e6a8737SNate Lawson 	const char *pm;
1817e1e9a4bfSMitsuru IWASAKI 
1818986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1819c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
18202177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1821986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1822986dffafSJohn Baldwin 	       fadt->Dsdt);
1823986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1824986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
18258e6a8737SNate Lawson 		pm = "Reserved";
18268e6a8737SNate Lawson 	else
1827986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1828986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1829986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1830986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1831986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1832986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1833986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1834986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1835e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1836986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1837986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1838986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1839e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1840986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1841986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1842e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1843986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1844986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1845986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1846e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1847986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1848986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1849986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1850e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1851986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1852986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1853c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1854986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1855986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1856986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
18578e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1858986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1859986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1860986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
18618e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1862986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1863986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1864986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1865986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1866986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
186751c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1868986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1869e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1870986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1871e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1872986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1873e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1874986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1875e1e9a4bfSMitsuru IWASAKI 
1876ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1877e1e9a4bfSMitsuru IWASAKI 
18788e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1879986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1880986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1881986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1882986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1883986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1884f6469ce1SAndrew Turner 	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1885ec650989SNeel Natu 	PRINTFLAG_END();
18868e6a8737SNate Lawson 
18878e6a8737SNate Lawson 	printf("\tFlags=");
1888986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1889986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1890986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1891986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1892986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1893986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1894986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1895986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1896986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1897986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1898986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1899986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1900986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1901986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1902986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1903986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1904986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1905986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1906986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1907986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1908f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, HW_REDUCED);
1909f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1910ec650989SNeel Natu 	PRINTFLAG_END();
1911e1e9a4bfSMitsuru IWASAKI 
1912e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1913e1e9a4bfSMitsuru IWASAKI 
1914986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
19158e6a8737SNate Lawson 		printf("\tRESET_REG=");
1916986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1917986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
19188e6a8737SNate Lawson 	}
1919c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
19207d369c6eSJung-uk Kim 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
19217d369c6eSJung-uk Kim 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1922c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1923986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1924986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1925c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1926986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1927c08c4e81SNate Lawson 		}
1928c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1929986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1930986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1931c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1932986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1933c08c4e81SNate Lawson 		}
1934986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1935773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1936986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1937c08c4e81SNate Lawson 		}
1938773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1939986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1940986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1941773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1942986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1943c08c4e81SNate Lawson 		}
1944986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1945773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1946986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1947c08c4e81SNate Lawson 		}
1948773b6454SNate Lawson 		printf("\n");
1949773b6454SNate Lawson 	}
19508e6a8737SNate Lawson 
19518e6a8737SNate Lawson 	printf(END_COMMENT);
19528e6a8737SNate Lawson }
19538e6a8737SNate Lawson 
19548e6a8737SNate Lawson static void
1955986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
19568e6a8737SNate Lawson {
19578e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1958986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1959986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1960986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
19618e6a8737SNate Lawson 
1962773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1963986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1964986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
19658e6a8737SNate Lawson 			printf("PENDING,");
1966986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
19678e6a8737SNate Lawson 			printf("OWNED");
19688e6a8737SNate Lawson 	}
1969773b6454SNate Lawson 	printf("\n");
19708e6a8737SNate Lawson 
1971773b6454SNate Lawson 	printf("\tFlags=");
1972986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
19738e6a8737SNate Lawson 		printf("S4BIOS");
1974773b6454SNate Lawson 	printf("\n");
19758e6a8737SNate Lawson 
19767d369c6eSJung-uk Kim 	if (facs->XFirmwareWakingVector != 0)
19777d369c6eSJung-uk Kim 		printf("\tX_Firm_Wake_Vec=%016jx\n",
19787d369c6eSJung-uk Kim 		    (uintmax_t)facs->XFirmwareWakingVector);
1979986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
19808e6a8737SNate Lawson 
1981c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1982e1e9a4bfSMitsuru IWASAKI }
1983e1e9a4bfSMitsuru IWASAKI 
1984945137d9SNate Lawson static void
1985986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1986e1e9a4bfSMitsuru IWASAKI {
1987773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1988773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1989773b6454SNate Lawson 	printf(END_COMMENT);
1990e1e9a4bfSMitsuru IWASAKI }
1991e1e9a4bfSMitsuru IWASAKI 
1992e1e9a4bfSMitsuru IWASAKI int
1993e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1994e1e9a4bfSMitsuru IWASAKI {
1995986dffafSJohn Baldwin 	uint8_t *bp;
1996986dffafSJohn Baldwin 	uint8_t sum;
1997e1e9a4bfSMitsuru IWASAKI 
1998e1e9a4bfSMitsuru IWASAKI 	bp = p;
1999e1e9a4bfSMitsuru IWASAKI 	sum = 0;
2000e1e9a4bfSMitsuru IWASAKI 	while (length--)
2001e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
2002e1e9a4bfSMitsuru IWASAKI 
2003e1e9a4bfSMitsuru IWASAKI 	return (sum);
2004e1e9a4bfSMitsuru IWASAKI }
2005e1e9a4bfSMitsuru IWASAKI 
2006986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
2007e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
2008e1e9a4bfSMitsuru IWASAKI {
2009986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
2010e1e9a4bfSMitsuru IWASAKI 
2011986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
2012986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
2013e1e9a4bfSMitsuru IWASAKI 	return (sp);
2014e1e9a4bfSMitsuru IWASAKI }
2015e1e9a4bfSMitsuru IWASAKI 
2016945137d9SNate Lawson static void
2017986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
2018e1e9a4bfSMitsuru IWASAKI {
2019c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
2020a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
2021986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
2022986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
2023986dffafSJohn Baldwin 	       rp->Revision);
2024986dffafSJohn Baldwin 	if (rp->Revision < 2) {
2025986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
2026986dffafSJohn Baldwin 		    rp->Checksum);
2027a74172abSNate Lawson 	} else {
20287d369c6eSJung-uk Kim 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
20297d369c6eSJung-uk Kim 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
2030986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
2031a74172abSNate Lawson 	}
2032c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
2033e1e9a4bfSMitsuru IWASAKI }
2034e1e9a4bfSMitsuru IWASAKI 
2035945137d9SNate Lawson static void
2036986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
2037e1e9a4bfSMitsuru IWASAKI {
2038986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
2039986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
2040986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
2041a74172abSNate Lawson 	vm_offset_t addr;
2042a74172abSNate Lawson 	int entries, i;
2043e1e9a4bfSMitsuru IWASAKI 
2044e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
2045986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
2046986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
2047986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
2048e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
2049fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
2050986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
2051fe1d0c2dSJung-uk Kim 		else
2052986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
2053fe1d0c2dSJung-uk Kim 		if (addr == 0)
2054fe1d0c2dSJung-uk Kim 			continue;
2055986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
2056986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
20575cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
2058986dffafSJohn Baldwin 			    sdp->Signature);
20595cf6d493SNate Lawson 			continue;
20605cf6d493SNate Lawson 		}
2061ebc22d04SAlexander Motin 		if (!memcmp(sdp->Signature, ACPI_SIG_BERT, 4))
2062ebc22d04SAlexander Motin 			acpi_handle_bert(sdp);
2063ebc22d04SAlexander Motin 		else if (!memcmp(sdp->Signature, ACPI_SIG_EINJ, 4))
2064ebc22d04SAlexander Motin 			acpi_handle_einj(sdp);
2065ebc22d04SAlexander Motin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ERST, 4))
2066ebc22d04SAlexander Motin 			acpi_handle_erst(sdp);
2067ebc22d04SAlexander Motin 		else if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
20682177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
2069986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
2070986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
2071ebc22d04SAlexander Motin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HEST, 4))
2072ebc22d04SAlexander Motin 			acpi_handle_hest(sdp);
2073986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
207479d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
2075986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
207655d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
2077986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
2078a47e681bSScott Long 			acpi_handle_mcfg(sdp);
207933866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
208033866658SJohn Baldwin 			acpi_handle_slit(sdp);
2081986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
2082a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
2083c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
2084c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
2085ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
2086ec650989SNeel Natu 			acpi_handle_dmar(sdp);
2087340c0022SEd Maste 		else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
2088340c0022SEd Maste 			acpi_handle_nfit(sdp);
2089ed26c389SScott Long 		else if (!memcmp(sdp->Signature, ACPI_SIG_WDDT, 4))
2090ed26c389SScott Long 			acpi_handle_wddt(sdp);
20915857fba5SBen Widawsky 		else if (!memcmp(sdp->Signature, ACPI_SIG_LPIT, 4))
20925857fba5SBen Widawsky 			acpi_handle_lpit(sdp);
2093877fc2e3STakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TPM2, 4))
2094877fc2e3STakanori Watanabe 			acpi_handle_tpm2(sdp);
2095773b6454SNate Lawson 		else {
2096773b6454SNate Lawson 			printf(BEGIN_COMMENT);
2097773b6454SNate Lawson 			acpi_print_sdt(sdp);
2098773b6454SNate Lawson 			printf(END_COMMENT);
2099773b6454SNate Lawson 		}
2100e1e9a4bfSMitsuru IWASAKI 	}
2101e1e9a4bfSMitsuru IWASAKI }
2102c62f1cccSMitsuru IWASAKI 
2103986dffafSJohn Baldwin ACPI_TABLE_HEADER *
2104476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
2105945137d9SNate Lawson {
2106986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
2107986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
2108945137d9SNate Lawson 
2109945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
2110945137d9SNate Lawson 	if (!rp)
2111945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
2112945137d9SNate Lawson 
2113945137d9SNate Lawson 	if (tflag)
2114945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
2115986dffafSJohn Baldwin 	if (rp->Revision < 2) {
2116986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
2117986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
2118986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
2119945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
2120a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
2121a74172abSNate Lawson 	} else {
2122986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
2123986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
2124986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
2125a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
2126a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
2127a74172abSNate Lawson 	}
2128945137d9SNate Lawson 	return (rsdp);
2129945137d9SNate Lawson }
2130c62f1cccSMitsuru IWASAKI 
213162c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
2132bfa3f012SMarcel Moolenaar static int
2133986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
2134bfa3f012SMarcel Moolenaar {
2135986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
2136986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
2137bfa3f012SMarcel Moolenaar 	uint8_t sum;
2138bfa3f012SMarcel Moolenaar 
213962c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
2140bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
2141bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
2142986dffafSJohn Baldwin 		sdt.Checksum = 0;
2143986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
2144986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
2145986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
2146f7675a56SNate Lawson 		while (ssdt != NULL) {
2147986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
2148986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
2149986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
2150986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
2151bfa3f012SMarcel Moolenaar 		}
2152986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
2153986dffafSJohn Baldwin 		sdt.Checksum -= sum;
2154bfa3f012SMarcel Moolenaar 	}
215562c7bde1SNate Lawson 
215662c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
2157986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
2158986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
215962c7bde1SNate Lawson 
2160b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
2161f7675a56SNate Lawson 	if (rsdt != NULL) {
2162bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
2163bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
2164986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
2165986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
2166bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
2167bfa3f012SMarcel Moolenaar 		}
2168bfa3f012SMarcel Moolenaar 	}
2169bfa3f012SMarcel Moolenaar 	return (0);
2170bfa3f012SMarcel Moolenaar }
2171bfa3f012SMarcel Moolenaar 
2172c62f1cccSMitsuru IWASAKI void
2173986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
2174c62f1cccSMitsuru IWASAKI {
2175945137d9SNate Lawson 	int	fd;
2176945137d9SNate Lawson 	mode_t	mode;
2177945137d9SNate Lawson 
2178945137d9SNate Lawson 	assert(outfile != NULL);
2179945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
2180945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
2181945137d9SNate Lawson 	if (fd == -1) {
2182945137d9SNate Lawson 		perror("dsdt_save_file");
2183945137d9SNate Lawson 		return;
2184945137d9SNate Lawson 	}
2185bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
2186945137d9SNate Lawson 	close(fd);
2187c62f1cccSMitsuru IWASAKI }
2188c62f1cccSMitsuru IWASAKI 
2189945137d9SNate Lawson void
2190986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
2191c62f1cccSMitsuru IWASAKI {
21927e2cc014SDon Lewis 	char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
21937e2cc014SDon Lewis 	const char *iname = "/acpdump.din";
21947e2cc014SDon Lewis 	const char *oname = "/acpdump.dsl";
219599065116SJung-uk Kim 	const char *tmpdir;
2196945137d9SNate Lawson 	FILE *fp;
219799065116SJung-uk Kim 	size_t len;
21987e2cc014SDon Lewis 	int fd, status;
21997e2cc014SDon Lewis 	pid_t pid;
2200945137d9SNate Lawson 
220199065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
220299065116SJung-uk Kim 	if (tmpdir == NULL)
220399065116SJung-uk Kim 		tmpdir = _PATH_TMP;
22047e2cc014SDon Lewis 	if (realpath(tmpdir, buf) == NULL) {
2205d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
220699065116SJung-uk Kim 		return;
220799065116SJung-uk Kim 	}
22087e2cc014SDon Lewis 	len = sizeof(wrkdir) - strlen(iname);
22097e2cc014SDon Lewis 	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
22107e2cc014SDon Lewis 		fprintf(stderr, "$TMPDIR too long\n");
22117e2cc014SDon Lewis 		return;
22127e2cc014SDon Lewis 	}
22137e2cc014SDon Lewis 	if  (mkdtemp(wrkdir) == NULL) {
22147e2cc014SDon Lewis 		perror("mkdtemp tmp working dir");
22157e2cc014SDon Lewis 		return;
22167e2cc014SDon Lewis 	}
221730bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
221830bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
22197e2cc014SDon Lewis 	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
2220945137d9SNate Lawson 	if (fd < 0) {
2221945137d9SNate Lawson 		perror("iasl tmp file");
2222945137d9SNate Lawson 		return;
2223c62f1cccSMitsuru IWASAKI 	}
2224bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
2225945137d9SNate Lawson 	close(fd);
2226945137d9SNate Lawson 
2227945137d9SNate Lawson 	/* Run iasl -d on the temp file */
22287e2cc014SDon Lewis 	if ((pid = fork()) == 0) {
2229945137d9SNate Lawson 		close(STDOUT_FILENO);
2230945137d9SNate Lawson 		if (vflag == 0)
2231945137d9SNate Lawson 			close(STDERR_FILENO);
223299065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
2233945137d9SNate Lawson 		err(1, "exec");
2234c62f1cccSMitsuru IWASAKI 	}
22357e2cc014SDon Lewis 	if (pid > 0)
22367e2cc014SDon Lewis 		wait(&status);
22377e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
22387e2cc014SDon Lewis 		perror("unlink");
22397e2cc014SDon Lewis 		goto out;
22407e2cc014SDon Lewis 	}
22417e2cc014SDon Lewis 	if (pid < 0) {
22427e2cc014SDon Lewis 		perror("fork");
22437e2cc014SDon Lewis 		goto out;
22447e2cc014SDon Lewis 	}
22457e2cc014SDon Lewis 	if (status != 0) {
2246861f5b95SSHENG-YI HONG 		fprintf(stderr, "iasl exit status = %d\n", status);
22477e2cc014SDon Lewis 	}
2248945137d9SNate Lawson 
2249945137d9SNate Lawson 	/* Dump iasl's output to stdout */
225030bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
225130bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
225299065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
22537e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
22547e2cc014SDon Lewis 		perror("unlink");
22557e2cc014SDon Lewis 		goto out;
22567e2cc014SDon Lewis 	}
2257945137d9SNate Lawson 	if (fp == NULL) {
2258945137d9SNate Lawson 		perror("iasl tmp file (read)");
22597e2cc014SDon Lewis 		goto out;
2260945137d9SNate Lawson 	}
2261945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
2262945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
2263945137d9SNate Lawson 	fclose(fp);
22647e2cc014SDon Lewis 
22657e2cc014SDon Lewis     out:
22667e2cc014SDon Lewis 	if (rmdir(wrkdir) < 0)
22677e2cc014SDon Lewis 		perror("rmdir");
2268c62f1cccSMitsuru IWASAKI }
2269c62f1cccSMitsuru IWASAKI 
2270945137d9SNate Lawson void
2271986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
2272c62f1cccSMitsuru IWASAKI {
2273945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
2274c62f1cccSMitsuru IWASAKI }
2275c62f1cccSMitsuru IWASAKI 
2276bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
2277986dffafSJohn Baldwin ACPI_TABLE_HEADER *
2278986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
2279c62f1cccSMitsuru IWASAKI {
2280986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
2281986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
2282986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
2283a74172abSNate Lawson 	vm_offset_t addr;
2284a74172abSNate Lawson 	int entries, i;
2285945137d9SNate Lawson 
2286986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
2287986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
2288986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
2289945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
2290fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
2291986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
2292fe1d0c2dSJung-uk Kim 		else
2293986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
2294fe1d0c2dSJung-uk Kim 		if (addr == 0)
2295fe1d0c2dSJung-uk Kim 			continue;
2296986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
2297bfa3f012SMarcel Moolenaar 		if (last != NULL) {
2298bfa3f012SMarcel Moolenaar 			if (sdt == last)
2299bfa3f012SMarcel Moolenaar 				last = NULL;
2300bfa3f012SMarcel Moolenaar 			continue;
2301bfa3f012SMarcel Moolenaar 		}
2302986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
2303a74172abSNate Lawson 			continue;
2304986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
2305945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
2306945137d9SNate Lawson 		return (sdt);
2307c62f1cccSMitsuru IWASAKI 	}
2308c62f1cccSMitsuru IWASAKI 
2309945137d9SNate Lawson 	return (NULL);
2310c62f1cccSMitsuru IWASAKI }
2311c62f1cccSMitsuru IWASAKI 
2312986dffafSJohn Baldwin ACPI_TABLE_HEADER *
2313986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
2314c62f1cccSMitsuru IWASAKI {
2315986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
2316c62f1cccSMitsuru IWASAKI 
2317986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
2318c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
2319986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
23202e71eb12SNate Lawson 	else
2321986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
2322986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
2323945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
2324945137d9SNate Lawson 	return (sdt);
2325c62f1cccSMitsuru IWASAKI }
2326