xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision bc71118183ddd2493c6c8ce4511da3a2e8368804)
1e1e9a4bfSMitsuru IWASAKI /*-
21de7b4b8SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
31de7b4b8SPedro F. Giffuni  *
4e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 1998 Doug Rabson
5e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6e1e9a4bfSMitsuru IWASAKI  * All rights reserved.
7e1e9a4bfSMitsuru IWASAKI  *
8e1e9a4bfSMitsuru IWASAKI  * Redistribution and use in source and binary forms, with or without
9e1e9a4bfSMitsuru IWASAKI  * modification, are permitted provided that the following conditions
10e1e9a4bfSMitsuru IWASAKI  * are met:
11e1e9a4bfSMitsuru IWASAKI  * 1. Redistributions of source code must retain the above copyright
12e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer.
13e1e9a4bfSMitsuru IWASAKI  * 2. Redistributions in binary form must reproduce the above copyright
14e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer in the
15e1e9a4bfSMitsuru IWASAKI  *    documentation and/or other materials provided with the distribution.
16e1e9a4bfSMitsuru IWASAKI  *
17e1e9a4bfSMitsuru IWASAKI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18e1e9a4bfSMitsuru IWASAKI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19e1e9a4bfSMitsuru IWASAKI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20e1e9a4bfSMitsuru IWASAKI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21e1e9a4bfSMitsuru IWASAKI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22e1e9a4bfSMitsuru IWASAKI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23e1e9a4bfSMitsuru IWASAKI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24e1e9a4bfSMitsuru IWASAKI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25e1e9a4bfSMitsuru IWASAKI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26e1e9a4bfSMitsuru IWASAKI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27e1e9a4bfSMitsuru IWASAKI  * SUCH DAMAGE.
28e1e9a4bfSMitsuru IWASAKI  *
29e1e9a4bfSMitsuru IWASAKI  *	$FreeBSD$
30e1e9a4bfSMitsuru IWASAKI  */
31e1e9a4bfSMitsuru IWASAKI 
32e1e9a4bfSMitsuru IWASAKI #include <sys/param.h>
33a74172abSNate Lawson #include <sys/endian.h>
34e1e9a4bfSMitsuru IWASAKI #include <sys/stat.h>
35945137d9SNate Lawson #include <sys/wait.h>
36e1e9a4bfSMitsuru IWASAKI #include <assert.h>
37e1e9a4bfSMitsuru IWASAKI #include <err.h>
38e1e9a4bfSMitsuru IWASAKI #include <fcntl.h>
3999065116SJung-uk Kim #include <paths.h>
40e1e9a4bfSMitsuru IWASAKI #include <stdio.h>
41a0333ad1SJohn Baldwin #include <stdint.h>
4299065116SJung-uk Kim #include <stdlib.h>
43945137d9SNate Lawson #include <string.h>
44e1e9a4bfSMitsuru IWASAKI #include <unistd.h>
45340c0022SEd Maste #include <uuid.h>
46e1e9a4bfSMitsuru IWASAKI 
47e1e9a4bfSMitsuru IWASAKI #include "acpidump.h"
48e1e9a4bfSMitsuru IWASAKI 
49c62f1cccSMitsuru IWASAKI #define BEGIN_COMMENT	"/*\n"
50c62f1cccSMitsuru IWASAKI #define END_COMMENT	" */\n"
51c62f1cccSMitsuru IWASAKI 
52945137d9SNate Lawson static void	acpi_print_string(char *s, size_t length);
53986dffafSJohn Baldwin static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
54986dffafSJohn Baldwin static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
55986dffafSJohn Baldwin static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
56945137d9SNate Lawson static void	acpi_print_cpu(u_char cpu_id);
57986dffafSJohn Baldwin static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
58986dffafSJohn Baldwin static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
59986dffafSJohn Baldwin static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
60986dffafSJohn Baldwin 		    uint64_t apic_addr);
61986dffafSJohn Baldwin static void	acpi_print_mps_flags(uint16_t flags);
62986dffafSJohn Baldwin static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
63986dffafSJohn Baldwin static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
64986dffafSJohn Baldwin static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
65986dffafSJohn Baldwin static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
66986dffafSJohn Baldwin static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
67986dffafSJohn Baldwin static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
68986dffafSJohn Baldwin static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
6933866658SJohn Baldwin static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
70ed26c389SScott Long static void	acpi_handle_wddt(ACPI_TABLE_HEADER *sdp);
715857fba5SBen Widawsky static void	acpi_handle_lpit(ACPI_TABLE_HEADER *sdp);
72a0333ad1SJohn Baldwin static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
73a0333ad1SJohn Baldwin 		    uint32_t flags);
74986dffafSJohn Baldwin static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
75986dffafSJohn Baldwin static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
76986dffafSJohn Baldwin static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
77c031c93bSTakanori Watanabe static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
78340c0022SEd Maste static void	acpi_print_nfit(ACPI_NFIT_HEADER *nfit);
79340c0022SEd Maste static void	acpi_handle_nfit(ACPI_TABLE_HEADER *sdp);
80986dffafSJohn Baldwin static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
81986dffafSJohn Baldwin static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
82986dffafSJohn Baldwin static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
83986dffafSJohn Baldwin static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
84986dffafSJohn Baldwin static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
85986dffafSJohn Baldwin static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
86986dffafSJohn Baldwin static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
87986dffafSJohn Baldwin static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
88986dffafSJohn Baldwin 		    void (*action)(ACPI_SUBTABLE_HEADER *));
89340c0022SEd Maste static void	acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
90340c0022SEd Maste 		    void (*action)(ACPI_NFIT_HEADER *));
91c62f1cccSMitsuru IWASAKI 
92773b6454SNate Lawson /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
93a74172abSNate Lawson static int addr_size;
94a74172abSNate Lawson 
95c031c93bSTakanori Watanabe /* Strings used in the TCPA table */
96c031c93bSTakanori Watanabe static const char *tcpa_event_type_strings[] = {
97c031c93bSTakanori Watanabe 	"PREBOOT Certificate",
98c031c93bSTakanori Watanabe 	"POST Code",
99c031c93bSTakanori Watanabe 	"Unused",
100c031c93bSTakanori Watanabe 	"No Action",
101c031c93bSTakanori Watanabe 	"Separator",
102c031c93bSTakanori Watanabe 	"Action",
103c031c93bSTakanori Watanabe 	"Event Tag",
104c031c93bSTakanori Watanabe 	"S-CRTM Contents",
105c031c93bSTakanori Watanabe 	"S-CRTM Version",
106c031c93bSTakanori Watanabe 	"CPU Microcode",
107c031c93bSTakanori Watanabe 	"Platform Config Flags",
108c031c93bSTakanori Watanabe 	"Table of Devices",
109c031c93bSTakanori Watanabe 	"Compact Hash",
110c031c93bSTakanori Watanabe 	"IPL",
111c031c93bSTakanori Watanabe 	"IPL Partition Data",
112c031c93bSTakanori Watanabe 	"Non-Host Code",
113c031c93bSTakanori Watanabe 	"Non-Host Config",
114c031c93bSTakanori Watanabe 	"Non-Host Info"
115c031c93bSTakanori Watanabe };
116c031c93bSTakanori Watanabe 
117c031c93bSTakanori Watanabe static const char *TCPA_pcclient_strings[] = {
118c031c93bSTakanori Watanabe 	"<undefined>",
119c031c93bSTakanori Watanabe 	"SMBIOS",
120c031c93bSTakanori Watanabe 	"BIS Certificate",
121c031c93bSTakanori Watanabe 	"POST BIOS ROM Strings",
122c031c93bSTakanori Watanabe 	"ESCD",
123c031c93bSTakanori Watanabe 	"CMOS",
124c031c93bSTakanori Watanabe 	"NVRAM",
125c031c93bSTakanori Watanabe 	"Option ROM Execute",
126c031c93bSTakanori Watanabe 	"Option ROM Configurateion",
127c031c93bSTakanori Watanabe 	"<undefined>",
128c031c93bSTakanori Watanabe 	"Option ROM Microcode Update ",
129c031c93bSTakanori Watanabe 	"S-CRTM Version String",
130c031c93bSTakanori Watanabe 	"S-CRTM Contents",
131c031c93bSTakanori Watanabe 	"POST Contents",
132c031c93bSTakanori Watanabe 	"Table of Devices",
133c031c93bSTakanori Watanabe };
134c031c93bSTakanori Watanabe 
135ec650989SNeel Natu #define	PRINTFLAG_END()		printflag_end()
136ec650989SNeel Natu 
137ec650989SNeel Natu static char pf_sep = '{';
138ec650989SNeel Natu 
139ec650989SNeel Natu static void
140ec650989SNeel Natu printflag_end(void)
141ec650989SNeel Natu {
142ec650989SNeel Natu 
143ec650989SNeel Natu 	if (pf_sep != '{') {
144ec650989SNeel Natu 		printf("}");
145ec650989SNeel Natu 		pf_sep = '{';
146ec650989SNeel Natu 	}
147ec650989SNeel Natu 	printf("\n");
148ec650989SNeel Natu }
149ec650989SNeel Natu 
150ec650989SNeel Natu static void
151ec650989SNeel Natu printflag(uint64_t var, uint64_t mask, const char *name)
152ec650989SNeel Natu {
153ec650989SNeel Natu 
154ec650989SNeel Natu 	if (var & mask) {
155ec650989SNeel Natu 		printf("%c%s", pf_sep, name);
156ec650989SNeel Natu 		pf_sep = ',';
157ec650989SNeel Natu 	}
158ec650989SNeel Natu }
159ec650989SNeel Natu 
160e1e9a4bfSMitsuru IWASAKI static void
161e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
162e1e9a4bfSMitsuru IWASAKI {
163e1e9a4bfSMitsuru IWASAKI 	int	c;
164e1e9a4bfSMitsuru IWASAKI 
165e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
166e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
167e1e9a4bfSMitsuru IWASAKI 		length--;
168e1e9a4bfSMitsuru IWASAKI 
169e1e9a4bfSMitsuru IWASAKI 	while (length--) {
170e1e9a4bfSMitsuru IWASAKI 		c = *s++;
171e1e9a4bfSMitsuru IWASAKI 		putchar(c);
172e1e9a4bfSMitsuru IWASAKI 	}
173e1e9a4bfSMitsuru IWASAKI }
174e1e9a4bfSMitsuru IWASAKI 
175e1e9a4bfSMitsuru IWASAKI static void
176986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1778e6a8737SNate Lawson {
178986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1798e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
1807d369c6eSJung-uk Kim 		if (gas->BitWidth <= 32)
1817d369c6eSJung-uk Kim 			printf("0x%08x:%u[%u] (Memory)",
1827d369c6eSJung-uk Kim 			    (u_int)gas->Address, gas->BitOffset,
1837d369c6eSJung-uk Kim 			    gas->BitWidth);
1847d369c6eSJung-uk Kim 		else
1857d369c6eSJung-uk Kim 			printf("0x%016jx:%u[%u] (Memory)",
1867d369c6eSJung-uk Kim 			    (uintmax_t)gas->Address, gas->BitOffset,
1877d369c6eSJung-uk Kim 			    gas->BitWidth);
1888e6a8737SNate Lawson 		break;
1898e6a8737SNate Lawson 	case ACPI_GAS_IO:
1907d369c6eSJung-uk Kim 		printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
191986dffafSJohn Baldwin 		    gas->BitOffset, gas->BitWidth);
1928e6a8737SNate Lawson 		break;
1938e6a8737SNate Lawson 	case ACPI_GAS_PCI:
194986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
195986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
196986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1978e6a8737SNate Lawson 		break;
1988e6a8737SNate Lawson 	/* XXX How to handle these below? */
1998e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
200986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
201986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
2028e6a8737SNate Lawson 		break;
2038e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
204986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
205986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
2068e6a8737SNate Lawson 		break;
207986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
208986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
209986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
2108e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
2118e6a8737SNate Lawson 	default:
2127d369c6eSJung-uk Kim 		printf("0x%016jx (?)", (uintmax_t)gas->Address);
2138e6a8737SNate Lawson 		break;
2148e6a8737SNate Lawson 	}
2158e6a8737SNate Lawson }
2168e6a8737SNate Lawson 
217c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
218c2962974SNate Lawson static int
219986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
220e1e9a4bfSMitsuru IWASAKI {
221c2962974SNate Lawson 	int fadt_revision;
222e1e9a4bfSMitsuru IWASAKI 
223c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
224c83f0f99SNate Lawson 	if (addr_size == 8) {
225c83f0f99SNate Lawson 		fadt_revision = 2;
2268e6a8737SNate Lawson 
227773b6454SNate Lawson 		/*
228c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
229c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
230c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
231c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
232c83f0f99SNate Lawson 		 * version for all subsequent tables.
233773b6454SNate Lawson 		 */
234986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
235986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
236c83f0f99SNate Lawson 			fadt_revision = 1;
237c2962974SNate Lawson 	} else
238c83f0f99SNate Lawson 		fadt_revision = 1;
239c2962974SNate Lawson 	return (fadt_revision);
240c83f0f99SNate Lawson }
241c2962974SNate Lawson 
242c2962974SNate Lawson static void
243986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
244c2962974SNate Lawson {
245986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
246986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
247986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
248*bc711181SAndrew Turner 	vm_offset_t	addr;
249c2962974SNate Lawson 	int		fadt_revision;
250c2962974SNate Lawson 
251986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2522177d4e6SNate Lawson 	acpi_print_fadt(sdp);
253c83f0f99SNate Lawson 
254c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
255c83f0f99SNate Lawson 	if (fadt_revision == 1)
256*bc711181SAndrew Turner 		addr = fadt->Facs;
257773b6454SNate Lawson 	else
258*bc711181SAndrew Turner 		addr = fadt->XFacs;
259*bc711181SAndrew Turner 	if (addr != 0) {
260*bc711181SAndrew Turner 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(addr);
261*bc711181SAndrew Turner 
262*bc711181SAndrew Turner 		if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 ||
263*bc711181SAndrew Turner 		    facs->Length < 64)
2648e6a8737SNate Lawson 			errx(1, "FACS is corrupt");
2658e6a8737SNate Lawson 		acpi_print_facs(facs);
266*bc711181SAndrew Turner 	}
2678e6a8737SNate Lawson 
268c83f0f99SNate Lawson 	if (fadt_revision == 1)
269986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
270773b6454SNate Lawson 	else
271986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
272986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
273945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
274945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
275c62f1cccSMitsuru IWASAKI }
276c62f1cccSMitsuru IWASAKI 
277c62f1cccSMitsuru IWASAKI static void
278986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
279986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
280986dffafSJohn Baldwin {
281986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
282986dffafSJohn Baldwin 	char *end;
283986dffafSJohn Baldwin 
284986dffafSJohn Baldwin 	subtable = first;
285986dffafSJohn Baldwin 	end = (char *)table + table->Length;
286986dffafSJohn Baldwin 	while ((char *)subtable < end) {
287986dffafSJohn Baldwin 		printf("\n");
288f5d0a8f7SEd Maste 		if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
289f5d0a8f7SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
290f5d0a8f7SEd Maste 			return;
291f5d0a8f7SEd Maste 		}
292986dffafSJohn Baldwin 		action(subtable);
293986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
294986dffafSJohn Baldwin 		    subtable->Length);
295986dffafSJohn Baldwin 	}
296986dffafSJohn Baldwin }
297986dffafSJohn Baldwin 
298986dffafSJohn Baldwin static void
299340c0022SEd Maste acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
300340c0022SEd Maste     void (*action)(ACPI_NFIT_HEADER *))
301340c0022SEd Maste {
302340c0022SEd Maste 	ACPI_NFIT_HEADER *subtable;
303340c0022SEd Maste 	char *end;
304340c0022SEd Maste 
305340c0022SEd Maste 	subtable = first;
306340c0022SEd Maste 	end = (char *)table + table->Length;
307340c0022SEd Maste 	while ((char *)subtable < end) {
308340c0022SEd Maste 		printf("\n");
309340c0022SEd Maste 		if (subtable->Length < sizeof(ACPI_NFIT_HEADER)) {
310340c0022SEd Maste 			warnx("invalid subtable length %u", subtable->Length);
311340c0022SEd Maste 			return;
312340c0022SEd Maste 		}
313340c0022SEd Maste 		action(subtable);
314340c0022SEd Maste 		subtable = (ACPI_NFIT_HEADER *)((char *)subtable +
315340c0022SEd Maste 		    subtable->Length);
316340c0022SEd Maste 	}
317340c0022SEd Maste }
318340c0022SEd Maste 
319340c0022SEd Maste static void
3200a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
3210a473124SJohn Baldwin {
3220a473124SJohn Baldwin 
3230a473124SJohn Baldwin 	printf("\tACPI CPU=");
3240a473124SJohn Baldwin 	if (cpu_id == 0xff)
3250a473124SJohn Baldwin 		printf("ALL\n");
3260a473124SJohn Baldwin 	else
3270a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
3280a473124SJohn Baldwin }
3290a473124SJohn Baldwin 
3300a473124SJohn Baldwin static void
331986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
3320a473124SJohn Baldwin {
333986dffafSJohn Baldwin 
334986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
335986dffafSJohn Baldwin 	if (uid_string != NULL)
336986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
337986dffafSJohn Baldwin 	printf("\n");
338986dffafSJohn Baldwin }
339986dffafSJohn Baldwin 
340986dffafSJohn Baldwin static void
341986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
342986dffafSJohn Baldwin {
343986dffafSJohn Baldwin 
3440a473124SJohn Baldwin 	printf("\tFlags={");
345986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
3460a473124SJohn Baldwin 		printf("ENABLED");
3470a473124SJohn Baldwin 	else
3480a473124SJohn Baldwin 		printf("DISABLED");
3490a473124SJohn Baldwin 	printf("}\n");
350986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3510a473124SJohn Baldwin }
3520a473124SJohn Baldwin 
3530a473124SJohn Baldwin static void
354986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
3550a473124SJohn Baldwin {
356986dffafSJohn Baldwin 
357986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3580a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
359986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
3600a473124SJohn Baldwin }
3610a473124SJohn Baldwin 
3620a473124SJohn Baldwin static void
363986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
3640a473124SJohn Baldwin {
3650a473124SJohn Baldwin 
3660a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
367986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
368986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
3690a473124SJohn Baldwin 		printf("conforming");
3700a473124SJohn Baldwin 		break;
371986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3720a473124SJohn Baldwin 		printf("active-hi");
3730a473124SJohn Baldwin 		break;
374986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3750a473124SJohn Baldwin 		printf("active-lo");
3760a473124SJohn Baldwin 		break;
3770a473124SJohn Baldwin 	default:
378986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3790a473124SJohn Baldwin 		break;
3800a473124SJohn Baldwin 	}
3810a473124SJohn Baldwin 	printf(", Trigger=");
382986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
383986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3840a473124SJohn Baldwin 		printf("conforming");
3850a473124SJohn Baldwin 		break;
386986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3870a473124SJohn Baldwin 		printf("edge");
3880a473124SJohn Baldwin 		break;
389986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3900a473124SJohn Baldwin 		printf("level");
3910a473124SJohn Baldwin 		break;
3920a473124SJohn Baldwin 	default:
393986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3940a473124SJohn Baldwin 	}
3950a473124SJohn Baldwin 	printf("}\n");
3960a473124SJohn Baldwin }
3970a473124SJohn Baldwin 
3980a473124SJohn Baldwin static void
3992b2b1f42SAndrew Turner acpi_print_gicc_flags(uint32_t flags)
4002b2b1f42SAndrew Turner {
4012b2b1f42SAndrew Turner 
4022b2b1f42SAndrew Turner 	printf("\tFlags={Performance intr=");
4032b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
4042b2b1f42SAndrew Turner 		printf("edge");
4052b2b1f42SAndrew Turner 	else
4062b2b1f42SAndrew Turner 		printf("level");
4072b2b1f42SAndrew Turner 	printf(", VGIC intr=");
4082b2b1f42SAndrew Turner 	if (flags & ACPI_MADT_VGIC_IRQ_MODE)
4092b2b1f42SAndrew Turner 		printf("edge");
4102b2b1f42SAndrew Turner 	else
4112b2b1f42SAndrew Turner 		printf("level");
4122b2b1f42SAndrew Turner 	printf("}\n");
4132b2b1f42SAndrew Turner }
4142b2b1f42SAndrew Turner 
4152b2b1f42SAndrew Turner static void
416986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
4170a473124SJohn Baldwin {
4180a473124SJohn Baldwin 
419986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
420986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
421986dffafSJohn Baldwin }
422986dffafSJohn Baldwin 
423986dffafSJohn Baldwin static void
424986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
425986dffafSJohn Baldwin {
426986dffafSJohn Baldwin 
427986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
4280a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
4290a473124SJohn Baldwin }
4300a473124SJohn Baldwin 
43127941afaSEd Maste static const char *apic_types[] = {
43227941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
43327941afaSEd Maste     [ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
43427941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
43527941afaSEd Maste     [ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
43627941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
43727941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
43827941afaSEd Maste     [ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
43927941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
44027941afaSEd Maste     [ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
44127941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
44227941afaSEd Maste     [ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
44327941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
44427941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
44527941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
44627941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
44727941afaSEd Maste     [ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
44827941afaSEd Maste };
44927941afaSEd Maste 
450bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
4510a473124SJohn Baldwin 					    "Corrected Platform Error" };
4520a473124SJohn Baldwin 
4530a473124SJohn Baldwin static void
454986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
4550a473124SJohn Baldwin {
456986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
457986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
458986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
459986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
460986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
461986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
462986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
463986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
464986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
465986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
466986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
4672b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_INTERRUPT *gicc;
4682b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
4692b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
4702b2b1f42SAndrew Turner 	ACPI_MADT_GENERIC_TRANSLATOR *gict;
4710a473124SJohn Baldwin 
472c86932b6SMarcelo Araujo 	if (mp->Type < nitems(apic_types))
473986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
474a0333ad1SJohn Baldwin 	else
475986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
476986dffafSJohn Baldwin 	switch (mp->Type) {
477986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
478986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
479986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
480986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4810a473124SJohn Baldwin 		break;
482986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
483986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
484986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
485986dffafSJohn Baldwin 		    ioapic->Address);
4860a473124SJohn Baldwin 		break;
487986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
488986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
489986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
490986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
491986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
4920a473124SJohn Baldwin 		break;
493986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
494986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
495986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
4960a473124SJohn Baldwin 		break;
497986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
498986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
499986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
500986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
5010a473124SJohn Baldwin 		break;
502986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
503986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
504945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
505986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
5060a473124SJohn Baldwin 		break;
507986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
508986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
509986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
510986dffafSJohn Baldwin 		    iosapic->Address);
5110a473124SJohn Baldwin 		break;
512986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
513986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
514986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
515986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
516986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
517986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
518986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
5190a473124SJohn Baldwin 		break;
520986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
521986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
522c86932b6SMarcelo Araujo 		if (isrc->Type < nitems(platform_int_types))
523986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
524986dffafSJohn Baldwin 		else
525986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
526986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
527986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
528986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
529986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
530986dffafSJohn Baldwin 		break;
531986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
532986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
533986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
534986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
535986dffafSJohn Baldwin 		break;
536986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
537986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
538986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
539986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
5400a473124SJohn Baldwin 		break;
5412b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
5422b2b1f42SAndrew Turner 		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
5432b2b1f42SAndrew Turner 		acpi_print_cpu_uid(gicc->Uid, NULL);
5442b2b1f42SAndrew Turner 		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
5452b2b1f42SAndrew Turner 		acpi_print_gicc_flags(gicc->Flags);
5462b2b1f42SAndrew Turner 		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
5472b2b1f42SAndrew Turner 		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
5482b2b1f42SAndrew Turner 		printf("\tParked ADDR=%016jx\n",
5492b2b1f42SAndrew Turner 		    (uintmax_t)gicc->ParkedAddress);
5502b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
5512b2b1f42SAndrew Turner 		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
5522b2b1f42SAndrew Turner 		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
5532b2b1f42SAndrew Turner 		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
5542b2b1f42SAndrew Turner 		printf("\tGICR ADDR=%016jx\n",
5552b2b1f42SAndrew Turner 		    (uintmax_t)gicc->GicrBaseAddress);
5562b2b1f42SAndrew Turner 		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
5572b2b1f42SAndrew Turner 		printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass);
5582b2b1f42SAndrew Turner 		break;
5592b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
5602b2b1f42SAndrew Turner 		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
5612b2b1f42SAndrew Turner 		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
5622b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
5632b2b1f42SAndrew Turner 		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
5642b2b1f42SAndrew Turner 		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
5652b2b1f42SAndrew Turner 		break;
5662b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
5672b2b1f42SAndrew Turner 		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
5682b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
5692b2b1f42SAndrew Turner 		printf("\tLength=%08x\n", gicr->Length);
5702b2b1f42SAndrew Turner 		break;
5712b2b1f42SAndrew Turner 	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
5722b2b1f42SAndrew Turner 		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
5732b2b1f42SAndrew Turner 		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
5742b2b1f42SAndrew Turner 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
5752b2b1f42SAndrew Turner 		break;
5760a473124SJohn Baldwin 	}
5770a473124SJohn Baldwin }
5780a473124SJohn Baldwin 
5790a473124SJohn Baldwin static void
580986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
5810a473124SJohn Baldwin {
582986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
5830a473124SJohn Baldwin 
584773b6454SNate Lawson 	printf(BEGIN_COMMENT);
585773b6454SNate Lawson 	acpi_print_sdt(sdp);
586986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
587986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
5880a473124SJohn Baldwin 	printf("\tFlags={");
589986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
5900a473124SJohn Baldwin 		printf("PC-AT");
5910a473124SJohn Baldwin 	printf("}\n");
592986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
5930a473124SJohn Baldwin 	printf(END_COMMENT);
5940a473124SJohn Baldwin }
5950a473124SJohn Baldwin 
5960a473124SJohn Baldwin static void
597986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
59879d7565cSPeter Wemm {
599986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
60079d7565cSPeter Wemm 
601773b6454SNate Lawson 	printf(BEGIN_COMMENT);
602773b6454SNate Lawson 	acpi_print_sdt(sdp);
603986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
604986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
60587f9f09aSTakanori Watanabe 	printf("\tADDR=");
606986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
607986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
608986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
609986dffafSJohn Baldwin 	    8);
610986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
611986dffafSJohn Baldwin 	    1 : 0);
61279d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
613986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
61479d7565cSPeter Wemm 		printf("TRUE}\n");
61579d7565cSPeter Wemm 	else
61679d7565cSPeter Wemm 		printf("FALSE}\n");
617986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
618986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
6199785e979SNeel Natu 	printf("\tFlags=0x%02x\n", hpet->Flags);
62079d7565cSPeter Wemm 	printf(END_COMMENT);
62179d7565cSPeter Wemm }
62279d7565cSPeter Wemm 
62379d7565cSPeter Wemm static void
624986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
62555d7ff9eSNate Lawson {
626986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
62755d7ff9eSNate Lawson 
62855d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
62955d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
630986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
63155d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
632986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
63355d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
634986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
635986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
636986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
637986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
63855d7ff9eSNate Lawson 	printf(END_COMMENT);
63955d7ff9eSNate Lawson }
64055d7ff9eSNate Lawson 
64155d7ff9eSNate Lawson static void
642986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
643a47e681bSScott Long {
644986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
645986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
646986dffafSJohn Baldwin 	u_int i, entries;
647a47e681bSScott Long 
648a47e681bSScott Long 	printf(BEGIN_COMMENT);
649a47e681bSScott Long 	acpi_print_sdt(sdp);
650986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
651986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
652986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
653986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
654986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
655a47e681bSScott Long 		printf("\n");
6560c10b85aSJung-uk Kim 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
657986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
658986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
659986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
660a47e681bSScott Long 	}
661a47e681bSScott Long 	printf(END_COMMENT);
662a47e681bSScott Long }
663a47e681bSScott Long 
664a47e681bSScott Long static void
66533866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
66633866658SJohn Baldwin {
66733866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
66833866658SJohn Baldwin 	UINT64 i, j;
66933866658SJohn Baldwin 
67033866658SJohn Baldwin 	printf(BEGIN_COMMENT);
67133866658SJohn Baldwin 	acpi_print_sdt(sdp);
67233866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
6730c10b85aSJung-uk Kim 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
67433866658SJohn Baldwin 	printf("\n\t      ");
67533866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
6760c10b85aSJung-uk Kim 		printf(" %3ju", (uintmax_t)i);
67733866658SJohn Baldwin 	printf("\n\t     +");
67833866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
67933866658SJohn Baldwin 		printf("----");
68033866658SJohn Baldwin 	printf("\n");
68133866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
6820c10b85aSJung-uk Kim 		printf("\t %3ju |", (uintmax_t)i);
68333866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
68433866658SJohn Baldwin 			printf(" %3d",
68533866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
68633866658SJohn Baldwin 		printf("\n");
68733866658SJohn Baldwin 	}
68833866658SJohn Baldwin 	printf(END_COMMENT);
68933866658SJohn Baldwin }
69033866658SJohn Baldwin 
69133866658SJohn Baldwin static void
692ed26c389SScott Long acpi_handle_wddt(ACPI_TABLE_HEADER *sdp)
693ed26c389SScott Long {
694ed26c389SScott Long 	ACPI_TABLE_WDDT *wddt;
695ed26c389SScott Long 
696ed26c389SScott Long 	printf(BEGIN_COMMENT);
697ed26c389SScott Long 	acpi_print_sdt(sdp);
698ed26c389SScott Long 	wddt = (ACPI_TABLE_WDDT *)sdp;
699ed26c389SScott Long 	printf("\tSpecVersion=0x%04x, TableVersion=0x%04x\n",
700ed26c389SScott Long 	    wddt->SpecVersion, wddt->TableVersion);
701ed26c389SScott Long 	printf("\tPciVendorId=0x%04x, Address=", wddt->PciVendorId);
702ed26c389SScott Long 	acpi_print_gas(&wddt->Address);
703ed26c389SScott Long 	printf("\n\tMaxCount=%u, MinCount=%u, Period=%ums\n",
704ed26c389SScott Long 	    wddt->MaxCount, wddt->MinCount, wddt->Period);
705ed26c389SScott Long 
706ed26c389SScott Long #define	PRINTFLAG(var, flag)	printflag((var), ACPI_WDDT_## flag, #flag)
707ed26c389SScott Long 	printf("\tStatus=");
708ed26c389SScott Long 	PRINTFLAG(wddt->Status, AVAILABLE);
709ed26c389SScott Long 	PRINTFLAG(wddt->Status, ACTIVE);
710ed26c389SScott Long 	PRINTFLAG(wddt->Status, TCO_OS_OWNED);
711ed26c389SScott Long 	PRINTFLAG(wddt->Status, USER_RESET);
712ed26c389SScott Long 	PRINTFLAG(wddt->Status, WDT_RESET);
713ed26c389SScott Long 	PRINTFLAG(wddt->Status, POWER_FAIL);
714ed26c389SScott Long 	PRINTFLAG(wddt->Status, UNKNOWN_RESET);
715ed26c389SScott Long 	PRINTFLAG_END();
716ed26c389SScott Long 	printf("\tCapability=");
717ed26c389SScott Long 	PRINTFLAG(wddt->Capability, AUTO_RESET);
718ed26c389SScott Long 	PRINTFLAG(wddt->Capability, ALERT_SUPPORT);
719ed26c389SScott Long 	PRINTFLAG_END();
720ed26c389SScott Long #undef PRINTFLAG
721ed26c389SScott Long 
722ed26c389SScott Long 	printf(END_COMMENT);
723ed26c389SScott Long }
724ed26c389SScott Long 
725ed26c389SScott Long static void
7265857fba5SBen Widawsky acpi_print_native_lpit(ACPI_LPIT_NATIVE *nl)
7275857fba5SBen Widawsky {
7285857fba5SBen Widawsky 	printf("\tEntryTrigger=");
7295857fba5SBen Widawsky 	acpi_print_gas(&nl->EntryTrigger);
7305857fba5SBen Widawsky 	printf("\tResidency=%u\n", nl->Residency);
7315857fba5SBen Widawsky 	printf("\tLatency=%u\n", nl->Latency);
7325857fba5SBen Widawsky 	if (nl->Header.Flags & ACPI_LPIT_NO_COUNTER)
7335857fba5SBen Widawsky 		printf("\tResidencyCounter=Not Present");
7345857fba5SBen Widawsky 	else {
7355857fba5SBen Widawsky 		printf("\tResidencyCounter=");
7365857fba5SBen Widawsky 		acpi_print_gas(&nl->ResidencyCounter);
7375857fba5SBen Widawsky 	}
7385857fba5SBen Widawsky 	if (nl->CounterFrequency)
7395857fba5SBen Widawsky 		printf("\tCounterFrequency=%ju\n", nl->CounterFrequency);
7405857fba5SBen Widawsky 	else
7415857fba5SBen Widawsky 		printf("\tCounterFrequency=TSC\n");
7425857fba5SBen Widawsky }
7435857fba5SBen Widawsky 
7445857fba5SBen Widawsky static void
7455857fba5SBen Widawsky acpi_print_lpit(ACPI_LPIT_HEADER *lpit)
7465857fba5SBen Widawsky {
7475857fba5SBen Widawsky 	if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
7485857fba5SBen Widawsky 		printf("\tType=ACPI_LPIT_TYPE_NATIVE_CSTATE\n");
7495857fba5SBen Widawsky 	else
7505857fba5SBen Widawsky 		warnx("unknown LPIT type %u", lpit->Type);
7515857fba5SBen Widawsky 
7525857fba5SBen Widawsky 	printf("\tLength=%u\n", lpit->Length);
7535857fba5SBen Widawsky 	printf("\tUniqueId=0x%04x\n", lpit->UniqueId);
7545857fba5SBen Widawsky #define	PRINTFLAG(var, flag)	printflag((var), ACPI_LPIT_## flag, #flag)
7555857fba5SBen Widawsky 	printf("\tFlags=");
7565857fba5SBen Widawsky 	PRINTFLAG(lpit->Flags, STATE_DISABLED);
7575857fba5SBen Widawsky 	PRINTFLAG_END();
7585857fba5SBen Widawsky #undef PRINTFLAG
7595857fba5SBen Widawsky 
7605857fba5SBen Widawsky 	if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
7615857fba5SBen Widawsky 		return acpi_print_native_lpit((ACPI_LPIT_NATIVE *)lpit);
7625857fba5SBen Widawsky }
7635857fba5SBen Widawsky 
7645857fba5SBen Widawsky static void
7655857fba5SBen Widawsky acpi_walk_lpit(ACPI_TABLE_HEADER *table, void *first,
7665857fba5SBen Widawsky     void (*action)(ACPI_LPIT_HEADER *))
7675857fba5SBen Widawsky {
7685857fba5SBen Widawsky 	ACPI_LPIT_HEADER *subtable;
7695857fba5SBen Widawsky 	char *end;
7705857fba5SBen Widawsky 
7715857fba5SBen Widawsky 	subtable = first;
7725857fba5SBen Widawsky 	end = (char *)table + table->Length;
7735857fba5SBen Widawsky 	while ((char *)subtable < end) {
7745857fba5SBen Widawsky 		printf("\n");
7755857fba5SBen Widawsky 		if (subtable->Length < sizeof(ACPI_LPIT_HEADER)) {
7765857fba5SBen Widawsky 			warnx("invalid subtable length %u", subtable->Length);
7775857fba5SBen Widawsky 			return;
7785857fba5SBen Widawsky 		}
7795857fba5SBen Widawsky 		action(subtable);
7805857fba5SBen Widawsky 		subtable = (ACPI_LPIT_HEADER *)((char *)subtable +
7815857fba5SBen Widawsky 		    subtable->Length);
7825857fba5SBen Widawsky 	}
7835857fba5SBen Widawsky }
7845857fba5SBen Widawsky 
7855857fba5SBen Widawsky static void
7865857fba5SBen Widawsky acpi_handle_lpit(ACPI_TABLE_HEADER *sdp)
7875857fba5SBen Widawsky {
7885857fba5SBen Widawsky 	ACPI_TABLE_LPIT *lpit;
7895857fba5SBen Widawsky 
7905857fba5SBen Widawsky 	printf(BEGIN_COMMENT);
7915857fba5SBen Widawsky 	acpi_print_sdt(sdp);
7925857fba5SBen Widawsky 	lpit = (ACPI_TABLE_LPIT *)sdp;
7935857fba5SBen Widawsky 	acpi_walk_lpit(sdp, (lpit + 1), acpi_print_lpit);
7945857fba5SBen Widawsky 
7955857fba5SBen Widawsky 	printf(END_COMMENT);
7965857fba5SBen Widawsky }
7975857fba5SBen Widawsky 
7985857fba5SBen Widawsky static void
799a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
800a0333ad1SJohn Baldwin     uint32_t flags)
801a0333ad1SJohn Baldwin {
802a0333ad1SJohn Baldwin 
803a0333ad1SJohn Baldwin 	printf("\tFlags={");
804a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
805a0333ad1SJohn Baldwin 		printf("ENABLED");
806a0333ad1SJohn Baldwin 	else
807a0333ad1SJohn Baldwin 		printf("DISABLED");
808a0333ad1SJohn Baldwin 	printf("}\n");
809a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
810a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
811a0333ad1SJohn Baldwin }
812a0333ad1SJohn Baldwin 
813c031c93bSTakanori Watanabe static char *
814c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
815c031c93bSTakanori Watanabe {
816c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
817c031c93bSTakanori Watanabe 	char *eventname = NULL;
818c031c93bSTakanori Watanabe 
819c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
820c031c93bSTakanori Watanabe 
821c031c93bSTakanori Watanabe 	switch(event->event_type) {
822c031c93bSTakanori Watanabe 	case PREBOOT:
823c031c93bSTakanori Watanabe 	case POST_CODE:
824c031c93bSTakanori Watanabe 	case UNUSED:
825c031c93bSTakanori Watanabe 	case NO_ACTION:
826c031c93bSTakanori Watanabe 	case SEPARATOR:
827c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
828c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
829c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
830c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
831c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
832c031c93bSTakanori Watanabe 	case COMPACT_HASH:
833c031c93bSTakanori Watanabe 	case IPL:
834c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
835c031c93bSTakanori Watanabe 	case NONHOST_CODE:
836c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
837c031c93bSTakanori Watanabe 	case NONHOST_INFO:
838c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
839c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
840c031c93bSTakanori Watanabe 		break;
841c031c93bSTakanori Watanabe 
842c031c93bSTakanori Watanabe 	case ACTION:
843c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
844c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
845c031c93bSTakanori Watanabe 		break;
846c031c93bSTakanori Watanabe 
847c031c93bSTakanori Watanabe 	case EVENT_TAG:
848c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
849c031c93bSTakanori Watanabe 		case SMBIOS:
850c031c93bSTakanori Watanabe 		case BIS_CERT:
851c031c93bSTakanori Watanabe 		case CMOS:
852c031c93bSTakanori Watanabe 		case NVRAM:
853c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
854c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
855c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
856c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
857c031c93bSTakanori Watanabe 		case ESCD:
858c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
859c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
860c031c93bSTakanori Watanabe 		case POST_CONTENTS:
861c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
862c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
863c031c93bSTakanori Watanabe 			break;
864c031c93bSTakanori Watanabe 
865c031c93bSTakanori Watanabe 		default:
866c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
867c031c93bSTakanori Watanabe 			    pc_event->event_id);
868c031c93bSTakanori Watanabe 			break;
869c031c93bSTakanori Watanabe 		}
870c031c93bSTakanori Watanabe 		break;
871c031c93bSTakanori Watanabe 
872c031c93bSTakanori Watanabe 	default:
873c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
874c031c93bSTakanori Watanabe 		break;
875c031c93bSTakanori Watanabe 	}
876c031c93bSTakanori Watanabe 
877c031c93bSTakanori Watanabe 	return eventname;
878c031c93bSTakanori Watanabe }
879c031c93bSTakanori Watanabe 
880c031c93bSTakanori Watanabe static void
881c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
882c031c93bSTakanori Watanabe {
883c031c93bSTakanori Watanabe 	int i;
884c031c93bSTakanori Watanabe 	char *eventname;
885c031c93bSTakanori Watanabe 
886c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
887c031c93bSTakanori Watanabe 
888c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
889c031c93bSTakanori Watanabe 	printf(" 0x");
890c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
891c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
892c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
893c031c93bSTakanori Watanabe 
894c031c93bSTakanori Watanabe 	free(eventname);
895c031c93bSTakanori Watanabe }
896c031c93bSTakanori Watanabe 
897c031c93bSTakanori Watanabe static void
898c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
899c031c93bSTakanori Watanabe {
900c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
901c031c93bSTakanori Watanabe 	struct TCPAevent *event;
902977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
903c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
904c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
905c031c93bSTakanori Watanabe 
906c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
907c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
908c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
909c031c93bSTakanori Watanabe 
910c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
911c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
912c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
913c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
914c031c93bSTakanori Watanabe 		break;
915c031c93bSTakanori Watanabe 
916c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
917c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
918c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
919c031c93bSTakanori Watanabe 		break;
920c031c93bSTakanori Watanabe 
921c031c93bSTakanori Watanabe 	default:
922c031c93bSTakanori Watanabe 		printf("XXX");
923c031c93bSTakanori Watanabe 		printf(END_COMMENT);
924c031c93bSTakanori Watanabe 		return;
925c031c93bSTakanori Watanabe 	}
9260e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
927c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
928c031c93bSTakanori Watanabe 
929c031c93bSTakanori Watanabe 	if (len == 0) {
930c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
931c031c93bSTakanori Watanabe 		printf(END_COMMENT);
932c031c93bSTakanori Watanabe 		return;
933c031c93bSTakanori Watanabe 	}
9342ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
9352ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
9362ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
9372ef23c6dSTakanori Watanabe 		return;
9382ef23c6dSTakanori Watanabe 	}
939c031c93bSTakanori Watanabe 
940c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
941c031c93bSTakanori Watanabe 	vend = vaddr + len;
942c031c93bSTakanori Watanabe 
943c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
9442ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
9452ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
946c031c93bSTakanori Watanabe 			break;
9470e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
948c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
949c031c93bSTakanori Watanabe 			break;
9502ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
9512ef23c6dSTakanori Watanabe 			break;
952c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
953c031c93bSTakanori Watanabe 			break;
954c031c93bSTakanori Watanabe #if 0
955c031c93bSTakanori Watanabe 		{
956c031c93bSTakanori Watanabe 		unsigned int i, j, k;
957c031c93bSTakanori Watanabe 
958c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
959c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
960c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
961c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
962c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
963c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
964c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
965c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
966c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
967c031c93bSTakanori Watanabe 				j = i + 1;
968c031c93bSTakanori Watanabe 			}
969c031c93bSTakanori Watanabe 		}
970c031c93bSTakanori Watanabe 		printf("\n"); }
971c031c93bSTakanori Watanabe #endif
972c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
973c031c93bSTakanori Watanabe 
974c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
975c031c93bSTakanori Watanabe 	}
976c031c93bSTakanori Watanabe 
977c031c93bSTakanori Watanabe 	printf(END_COMMENT);
978c031c93bSTakanori Watanabe }
979877fc2e3STakanori Watanabe static void acpi_handle_tpm2(ACPI_TABLE_HEADER *sdp)
980877fc2e3STakanori Watanabe {
981877fc2e3STakanori Watanabe 	ACPI_TABLE_TPM2 *tpm2;
982877fc2e3STakanori Watanabe 
983877fc2e3STakanori Watanabe 	printf (BEGIN_COMMENT);
984877fc2e3STakanori Watanabe 	acpi_print_sdt(sdp);
985877fc2e3STakanori Watanabe 	tpm2 = (ACPI_TABLE_TPM2 *) sdp;
9867aef7138SCy Schubert 	printf ("\t\tControlArea=%jx\n", tpm2->ControlAddress);
987877fc2e3STakanori Watanabe 	printf ("\t\tStartMethod=%x\n", tpm2->StartMethod);
988877fc2e3STakanori Watanabe 	printf (END_COMMENT);
989877fc2e3STakanori Watanabe }
990c031c93bSTakanori Watanabe 
991ec650989SNeel Natu static const char *
992ec650989SNeel Natu devscope_type2str(int type)
993ec650989SNeel Natu {
994ec650989SNeel Natu 	static char typebuf[16];
995ec650989SNeel Natu 
996ec650989SNeel Natu 	switch (type) {
997ec650989SNeel Natu 	case 1:
998ec650989SNeel Natu 		return ("PCI Endpoint Device");
999ec650989SNeel Natu 	case 2:
1000ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
1001ec650989SNeel Natu 	case 3:
1002ec650989SNeel Natu 		return ("IOAPIC");
1003ec650989SNeel Natu 	case 4:
1004ec650989SNeel Natu 		return ("HPET");
1005ec650989SNeel Natu 	default:
1006ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
1007ec650989SNeel Natu 		return (typebuf);
1008ec650989SNeel Natu 	}
1009ec650989SNeel Natu }
1010ec650989SNeel Natu 
1011ec650989SNeel Natu static int
1012ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
1013ec650989SNeel Natu {
1014ec650989SNeel Natu 	char sep;
1015ec650989SNeel Natu 	int pathlen;
1016ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
1017ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
1018ec650989SNeel Natu 
1019ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
1020ec650989SNeel Natu 		return (-1);
1021ec650989SNeel Natu 
1022ec650989SNeel Natu 	if (remaining < devscope->Length)
1023ec650989SNeel Natu 		return (-1);
1024ec650989SNeel Natu 
1025ec650989SNeel Natu 	printf("\n");
1026ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
1027ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
1028ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
1029ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
1030ec650989SNeel Natu 
1031ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
1032ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
1033ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
1034ec650989SNeel Natu 	if (path < pathend) {
1035ec650989SNeel Natu 		sep = '{';
1036ec650989SNeel Natu 		printf("\t\tPath=");
1037ec650989SNeel Natu 		do {
1038ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
1039ec650989SNeel Natu 			sep=',';
1040ec650989SNeel Natu 			path++;
1041ec650989SNeel Natu 		} while (path < pathend);
1042ec650989SNeel Natu 		printf("}\n");
1043ec650989SNeel Natu 	}
1044ec650989SNeel Natu 
1045ec650989SNeel Natu 	return (devscope->Length);
1046ec650989SNeel Natu }
1047ec650989SNeel Natu 
1048ec650989SNeel Natu static void
1049ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
1050ec650989SNeel Natu {
1051ec650989SNeel Natu 	char *cp;
1052ec650989SNeel Natu 	int remaining, consumed;
1053ec650989SNeel Natu 
1054ec650989SNeel Natu 	printf("\n");
1055ec650989SNeel Natu 	printf("\tType=DRHD\n");
1056ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
1057ec650989SNeel Natu 
1058ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1059ec650989SNeel Natu 
1060ec650989SNeel Natu 	printf("\tFlags=");
1061ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
1062ec650989SNeel Natu 	PRINTFLAG_END();
1063ec650989SNeel Natu 
1064ec650989SNeel Natu #undef PRINTFLAG
1065ec650989SNeel Natu 
1066ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
10677d369c6eSJung-uk Kim 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
1068ec650989SNeel Natu 
1069ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
1070ec650989SNeel Natu 	if (remaining > 0)
1071ec650989SNeel Natu 		printf("\tDevice Scope:");
1072ec650989SNeel Natu 	while (remaining > 0) {
1073ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
1074ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1075ec650989SNeel Natu 		if (consumed <= 0)
1076ec650989SNeel Natu 			break;
1077ec650989SNeel Natu 		else
1078ec650989SNeel Natu 			remaining -= consumed;
1079ec650989SNeel Natu 	}
1080ec650989SNeel Natu }
1081ec650989SNeel Natu 
1082ec650989SNeel Natu static void
1083ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
1084ec650989SNeel Natu {
1085ec650989SNeel Natu 	char *cp;
1086ec650989SNeel Natu 	int remaining, consumed;
1087ec650989SNeel Natu 
1088ec650989SNeel Natu 	printf("\n");
1089ec650989SNeel Natu 	printf("\tType=RMRR\n");
1090ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
1091ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
10927d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
10937d369c6eSJung-uk Kim 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
1094ec650989SNeel Natu 
1095ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
1096ec650989SNeel Natu 	if (remaining > 0)
1097ec650989SNeel Natu 		printf("\tDevice Scope:");
1098ec650989SNeel Natu 	while (remaining > 0) {
1099ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
1100ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1101ec650989SNeel Natu 		if (consumed <= 0)
1102ec650989SNeel Natu 			break;
1103ec650989SNeel Natu 		else
1104ec650989SNeel Natu 			remaining -= consumed;
1105ec650989SNeel Natu 	}
1106ec650989SNeel Natu }
1107ec650989SNeel Natu 
1108ec650989SNeel Natu static void
1109ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
1110ec650989SNeel Natu {
1111ec650989SNeel Natu 	char *cp;
1112ec650989SNeel Natu 	int remaining, consumed;
1113ec650989SNeel Natu 
1114ec650989SNeel Natu 	printf("\n");
1115ec650989SNeel Natu 	printf("\tType=ATSR\n");
1116ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
1117ec650989SNeel Natu 
1118ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1119ec650989SNeel Natu 
1120ec650989SNeel Natu 	printf("\tFlags=");
1121ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
1122ec650989SNeel Natu 	PRINTFLAG_END();
1123ec650989SNeel Natu 
1124ec650989SNeel Natu #undef PRINTFLAG
1125ec650989SNeel Natu 
1126ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
1127ec650989SNeel Natu 
1128ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
1129ec650989SNeel Natu 	if (remaining > 0)
1130ec650989SNeel Natu 		printf("\tDevice Scope:");
1131ec650989SNeel Natu 	while (remaining > 0) {
1132ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
1133ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
1134ec650989SNeel Natu 		if (consumed <= 0)
1135ec650989SNeel Natu 			break;
1136ec650989SNeel Natu 		else
1137ec650989SNeel Natu 			remaining -= consumed;
1138ec650989SNeel Natu 	}
1139ec650989SNeel Natu }
1140ec650989SNeel Natu 
1141ec650989SNeel Natu static void
1142ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
1143ec650989SNeel Natu {
1144ec650989SNeel Natu 
1145ec650989SNeel Natu 	printf("\n");
1146ec650989SNeel Natu 	printf("\tType=RHSA\n");
1147ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
11487d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
1149ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
1150ec650989SNeel Natu }
1151ec650989SNeel Natu 
1152ec650989SNeel Natu static int
1153ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
1154ec650989SNeel Natu {
1155ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
1156ec650989SNeel Natu 
1157ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
1158ec650989SNeel Natu 		return (-1);
1159ec650989SNeel Natu 
1160ec650989SNeel Natu 	if (remaining < hdr->Length)
1161ec650989SNeel Natu 		return (-1);
1162ec650989SNeel Natu 
1163ec650989SNeel Natu 	switch (hdr->Type) {
1164ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1165ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
1166ec650989SNeel Natu 		break;
1167ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1168ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
1169ec650989SNeel Natu 		break;
1170313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_ROOT_ATS:
1171ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
1172ec650989SNeel Natu 		break;
1173313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1174ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
1175ec650989SNeel Natu 		break;
1176ec650989SNeel Natu 	default:
1177ec650989SNeel Natu 		printf("\n");
1178ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
1179ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
1180ec650989SNeel Natu 		break;
1181ec650989SNeel Natu 	}
1182ec650989SNeel Natu 	return (hdr->Length);
1183ec650989SNeel Natu }
1184ec650989SNeel Natu 
1185ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1186ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
1187ec650989SNeel Natu #endif
1188ec650989SNeel Natu 
1189ec650989SNeel Natu static void
1190ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1191ec650989SNeel Natu {
1192ec650989SNeel Natu 	char *cp;
1193ec650989SNeel Natu 	int remaining, consumed;
1194ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
1195ec650989SNeel Natu 
1196ec650989SNeel Natu 	printf(BEGIN_COMMENT);
1197ec650989SNeel Natu 	acpi_print_sdt(sdp);
1198ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
1199ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
1200ec650989SNeel Natu 
1201ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1202ec650989SNeel Natu 
1203ec650989SNeel Natu 	printf("\tFlags=");
1204ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
1205ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1206ec650989SNeel Natu 	PRINTFLAG_END();
1207ec650989SNeel Natu 
1208ec650989SNeel Natu #undef PRINTFLAG
1209ec650989SNeel Natu 
1210ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1211ec650989SNeel Natu 	while (remaining > 0) {
1212ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
1213ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1214ec650989SNeel Natu 		if (consumed <= 0)
1215ec650989SNeel Natu 			break;
1216ec650989SNeel Natu 		else
1217ec650989SNeel Natu 			remaining -= consumed;
1218ec650989SNeel Natu 	}
1219ec650989SNeel Natu 
1220ec650989SNeel Natu 	printf(END_COMMENT);
1221ec650989SNeel Natu }
1222ec650989SNeel Natu 
1223a0333ad1SJohn Baldwin static void
1224986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1225a0333ad1SJohn Baldwin {
1226a0333ad1SJohn Baldwin 
1227a0333ad1SJohn Baldwin 	printf("\tFlags={");
1228986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1229a0333ad1SJohn Baldwin 		printf("ENABLED");
1230a0333ad1SJohn Baldwin 	else
1231a0333ad1SJohn Baldwin 		printf("DISABLED");
1232986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1233a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1234986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1235a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1236a0333ad1SJohn Baldwin 	printf("}\n");
1237986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1238986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1239986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1240a0333ad1SJohn Baldwin }
1241a0333ad1SJohn Baldwin 
124227941afaSEd Maste static const char *srat_types[] = {
124327941afaSEd Maste     [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
124427941afaSEd Maste     [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
124527941afaSEd Maste     [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
1246cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
1247cebb7b19SEd Maste     [ACPI_SRAT_TYPE_GIC_ITS_AFFINITY] = "GIC ITS",
124827941afaSEd Maste };
1249a0333ad1SJohn Baldwin 
1250a0333ad1SJohn Baldwin static void
1251986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1252a0333ad1SJohn Baldwin {
1253986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1254986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
12552b2b1f42SAndrew Turner 	ACPI_SRAT_GICC_AFFINITY *gic;
1256a0333ad1SJohn Baldwin 
1257c86932b6SMarcelo Araujo 	if (srat->Type < nitems(srat_types))
1258986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1259a0333ad1SJohn Baldwin 	else
1260986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1261986dffafSJohn Baldwin 	switch (srat->Type) {
1262a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1263986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1264986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1265986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1266986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1267986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1268986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1269a0333ad1SJohn Baldwin 		break;
1270a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1271986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1272a0333ad1SJohn Baldwin 		break;
1273a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1274986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1275986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1276986dffafSJohn Baldwin 		    x2apic->Flags);
1277a0333ad1SJohn Baldwin 		break;
12782b2b1f42SAndrew Turner 	case ACPI_SRAT_TYPE_GICC_AFFINITY:
12792b2b1f42SAndrew Turner 		gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
12802b2b1f42SAndrew Turner 		acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
12812b2b1f42SAndrew Turner 		    gic->Flags);
12822b2b1f42SAndrew Turner 		break;
1283a0333ad1SJohn Baldwin 	}
1284a0333ad1SJohn Baldwin }
1285a0333ad1SJohn Baldwin 
1286a0333ad1SJohn Baldwin static void
1287986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1288a0333ad1SJohn Baldwin {
1289986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1290a0333ad1SJohn Baldwin 
1291a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1292a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1293986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1294986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1295986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1296a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1297a0333ad1SJohn Baldwin }
1298a0333ad1SJohn Baldwin 
1299340c0022SEd Maste static const char *nfit_types[] = {
1300340c0022SEd Maste     [ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
1301340c0022SEd Maste     [ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
1302340c0022SEd Maste     [ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
1303340c0022SEd Maste     [ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
1304340c0022SEd Maste     [ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
1305340c0022SEd Maste     [ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
1306340c0022SEd Maste     [ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address"
1307340c0022SEd Maste };
1308340c0022SEd Maste 
1309340c0022SEd Maste 
1310340c0022SEd Maste static void
1311340c0022SEd Maste acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
1312340c0022SEd Maste {
1313340c0022SEd Maste 	char *uuidstr;
1314340c0022SEd Maste 	uint32_t status;
1315340c0022SEd Maste 
1316340c0022SEd Maste 	ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
1317340c0022SEd Maste 	ACPI_NFIT_MEMORY_MAP *mmap;
1318340c0022SEd Maste 	ACPI_NFIT_INTERLEAVE *ileave;
1319340c0022SEd Maste 	ACPI_NFIT_SMBIOS *smbios;
1320340c0022SEd Maste 	ACPI_NFIT_CONTROL_REGION *ctlreg;
1321340c0022SEd Maste 	ACPI_NFIT_DATA_REGION *datareg;
1322340c0022SEd Maste 	ACPI_NFIT_FLUSH_ADDRESS *fladdr;
1323340c0022SEd Maste 
1324340c0022SEd Maste 	if (nfit->Type < nitems(nfit_types))
1325340c0022SEd Maste 		printf("\tType=%s\n", nfit_types[nfit->Type]);
1326340c0022SEd Maste 	else
1327340c0022SEd Maste 		printf("\tType=%u (unknown)\n", nfit->Type);
1328340c0022SEd Maste 	switch (nfit->Type) {
1329340c0022SEd Maste 	case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
1330340c0022SEd Maste 		sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
1331340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
1332340c0022SEd Maste 		printf("\tProximityDomain=%u\n",
1333340c0022SEd Maste 		    (u_int)sysaddr->ProximityDomain);
1334340c0022SEd Maste 		uuid_to_string((uuid_t *)(sysaddr->RangeGuid),
1335340c0022SEd Maste 		    &uuidstr, &status);
1336340c0022SEd Maste 		if (status != uuid_s_ok)
1337340c0022SEd Maste 			errx(1, "uuid_to_string: status=%u", status);
1338340c0022SEd Maste 		printf("\tRangeGuid=%s\n", uuidstr);
1339340c0022SEd Maste 		free(uuidstr);
1340340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
1341340c0022SEd Maste 		printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
1342340c0022SEd Maste 		printf("\tMemoryMapping=0x%016jx\n",
1343340c0022SEd Maste 		    (uintmax_t)sysaddr->MemoryMapping);
1344340c0022SEd Maste 
1345340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1346340c0022SEd Maste 
1347340c0022SEd Maste 		printf("\tFlags=");
1348340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
1349340c0022SEd Maste 		PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
1350340c0022SEd Maste 		PRINTFLAG_END();
1351340c0022SEd Maste 
1352340c0022SEd Maste #undef PRINTFLAG
1353340c0022SEd Maste 
1354340c0022SEd Maste 		break;
1355340c0022SEd Maste 	case ACPI_NFIT_TYPE_MEMORY_MAP:
1356340c0022SEd Maste 		mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
1357340c0022SEd Maste 		printf("\tDeviceHandle=%u\n", (u_int)mmap->DeviceHandle);
1358340c0022SEd Maste 		printf("\tPhysicalId=%u\n", (u_int)mmap->PhysicalId);
1359340c0022SEd Maste 		printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
1360340c0022SEd Maste 		printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
1361340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
1362340c0022SEd Maste 		printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
1363340c0022SEd Maste 		printf("\tRegionOffset=0x%016jx\n",
1364340c0022SEd Maste 		    (uintmax_t)mmap->RegionOffset);
1365340c0022SEd Maste 		printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
1366340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
1367fb1cf2a9SAlexander Motin 		printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
1368340c0022SEd Maste 
1369340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_MEM_## flag, #flag)
1370340c0022SEd Maste 
1371340c0022SEd Maste 		printf("\tFlags=");
1372340c0022SEd Maste 		PRINTFLAG(mmap->Flags, SAVE_FAILED);
1373340c0022SEd Maste 		PRINTFLAG(mmap->Flags, RESTORE_FAILED);
1374340c0022SEd Maste 		PRINTFLAG(mmap->Flags, FLUSH_FAILED);
1375340c0022SEd Maste 		PRINTFLAG(mmap->Flags, NOT_ARMED);
1376340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
1377340c0022SEd Maste 		PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
1378340c0022SEd Maste 		PRINTFLAG(mmap->Flags, MAP_FAILED);
1379340c0022SEd Maste 		PRINTFLAG_END();
1380340c0022SEd Maste 
1381340c0022SEd Maste #undef PRINTFLAG
1382340c0022SEd Maste 
1383340c0022SEd Maste 		break;
1384340c0022SEd Maste 	case ACPI_NFIT_TYPE_INTERLEAVE:
1385340c0022SEd Maste 		ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
1386340c0022SEd Maste 		printf("\tInterleaveIndex=%u\n",
1387340c0022SEd Maste 		    (u_int)ileave->InterleaveIndex);
1388340c0022SEd Maste 		printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
1389340c0022SEd Maste 		printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
1390340c0022SEd Maste 		/* XXX ileave->LineOffset[i] output is not supported */
1391340c0022SEd Maste 		break;
1392340c0022SEd Maste 	case ACPI_NFIT_TYPE_SMBIOS:
1393340c0022SEd Maste 		smbios = (ACPI_NFIT_SMBIOS *)nfit;
1394340c0022SEd Maste 		/* XXX smbios->Data[x] output is not supported */
1395340c0022SEd Maste 		break;
1396340c0022SEd Maste 	case ACPI_NFIT_TYPE_CONTROL_REGION:
1397340c0022SEd Maste 		ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
1398340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
1399340c0022SEd Maste 		printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
1400340c0022SEd Maste 		printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
1401340c0022SEd Maste 		printf("\tRevisionId=%u\n", (u_int)ctlreg->RevisionId);
1402340c0022SEd Maste 		printf("\tSubsystemVendorId=0x%04x\n",
1403340c0022SEd Maste 		    (u_int)ctlreg->SubsystemVendorId);
1404340c0022SEd Maste 		printf("\tSubsystemDeviceId=0x%04x\n",
1405340c0022SEd Maste 		    (u_int)ctlreg->SubsystemDeviceId);
1406340c0022SEd Maste 		printf("\tSubsystemRevisionId=%u\n",
1407340c0022SEd Maste 		    (u_int)ctlreg->SubsystemRevisionId);
1408d4c2de2eSAlexander Motin 		printf("\tValidFields=0x%02x\n", (u_int)ctlreg->ValidFields);
1409340c0022SEd Maste 		printf("\tManufacturingLocation=%u\n",
1410340c0022SEd Maste 		    (u_int)ctlreg->ManufacturingLocation);
1411340c0022SEd Maste 		printf("\tManufacturingDate=%u\n",
1412340c0022SEd Maste 		    (u_int)ctlreg->ManufacturingDate);
1413340c0022SEd Maste 		printf("\tSerialNumber=%u\n",
1414340c0022SEd Maste 		    (u_int)ctlreg->SerialNumber);
1415fb1cf2a9SAlexander Motin 		printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
1416340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
1417340c0022SEd Maste 		printf("\tWindowSize=0x%016jx\n",
1418340c0022SEd Maste 		    (uintmax_t)ctlreg->WindowSize);
1419340c0022SEd Maste 		printf("\tCommandOffset=0x%016jx\n",
1420340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandOffset);
1421340c0022SEd Maste 		printf("\tCommandSize=0x%016jx\n",
1422340c0022SEd Maste 		    (uintmax_t)ctlreg->CommandSize);
1423340c0022SEd Maste 		printf("\tStatusOffset=0x%016jx\n",
1424340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusOffset);
1425340c0022SEd Maste 		printf("\tStatusSize=0x%016jx\n",
1426340c0022SEd Maste 		    (uintmax_t)ctlreg->StatusSize);
1427340c0022SEd Maste 
1428340c0022SEd Maste #define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
1429340c0022SEd Maste 
1430340c0022SEd Maste 		printf("\tFlags=");
1431d4c2de2eSAlexander Motin 		PRINTFLAG(ctlreg->Flags, CONTROL_BUFFERED);
1432340c0022SEd Maste 		PRINTFLAG_END();
1433340c0022SEd Maste 
1434340c0022SEd Maste #undef PRINTFLAG
1435340c0022SEd Maste 
1436340c0022SEd Maste 		break;
1437340c0022SEd Maste 	case ACPI_NFIT_TYPE_DATA_REGION:
1438340c0022SEd Maste 		datareg = (ACPI_NFIT_DATA_REGION *)nfit;
1439340c0022SEd Maste 		printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
1440340c0022SEd Maste 		printf("\tWindows=%u\n", (u_int)datareg->Windows);
1441340c0022SEd Maste 		printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
1442340c0022SEd Maste 		printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
1443340c0022SEd Maste 		printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
1444340c0022SEd Maste 		printf("\tStartAddress=0x%016jx\n",
1445340c0022SEd Maste 		    (uintmax_t)datareg->StartAddress);
1446340c0022SEd Maste 		break;
1447340c0022SEd Maste 	case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
1448340c0022SEd Maste 		fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
1449340c0022SEd Maste 		printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
1450340c0022SEd Maste 		printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
1451340c0022SEd Maste 		/* XXX fladdr->HintAddress[i] output is not supported */
1452340c0022SEd Maste 		break;
1453340c0022SEd Maste 	}
1454340c0022SEd Maste }
1455340c0022SEd Maste 
1456340c0022SEd Maste static void
1457340c0022SEd Maste acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
1458340c0022SEd Maste {
1459340c0022SEd Maste 	ACPI_TABLE_NFIT *nfit;
1460340c0022SEd Maste 
1461340c0022SEd Maste 	printf(BEGIN_COMMENT);
1462340c0022SEd Maste 	acpi_print_sdt(sdp);
1463340c0022SEd Maste 	nfit = (ACPI_TABLE_NFIT *)sdp;
1464340c0022SEd Maste 	acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
1465340c0022SEd Maste 	printf(END_COMMENT);
1466340c0022SEd Maste }
1467340c0022SEd Maste 
1468a0333ad1SJohn Baldwin static void
1469986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1470c62f1cccSMitsuru IWASAKI {
1471773b6454SNate Lawson 	printf("  ");
1472278f0de6SJung-uk Kim 	acpi_print_string(sdp->Signature, ACPI_NAMESEG_SIZE);
1473c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1474986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1475e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1476986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1477e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1478986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1479986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1480e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1481278f0de6SJung-uk Kim 	acpi_print_string(sdp->AslCompilerId, ACPI_NAMESEG_SIZE);
1482986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1483e1e9a4bfSMitsuru IWASAKI }
1484e1e9a4bfSMitsuru IWASAKI 
1485945137d9SNate Lawson static void
1486986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1487e1e9a4bfSMitsuru IWASAKI {
1488986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1489986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1490e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1491e1e9a4bfSMitsuru IWASAKI 
1492986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1493986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1494773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1495773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1496986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1497e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1498e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1499e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1500e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1501fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
15027d369c6eSJung-uk Kim 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1503fe1d0c2dSJung-uk Kim 		else
15047d369c6eSJung-uk Kim 			printf("0x%016jx",
15057d369c6eSJung-uk Kim 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1506e1e9a4bfSMitsuru IWASAKI 	}
1507e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1508c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1509e1e9a4bfSMitsuru IWASAKI }
1510e1e9a4bfSMitsuru IWASAKI 
15118e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
15128e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
15138e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
15148e6a8737SNate Lawson };
15158e6a8737SNate Lawson 
1516945137d9SNate Lawson static void
1517986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1518e1e9a4bfSMitsuru IWASAKI {
1519986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
15208e6a8737SNate Lawson 	const char *pm;
1521e1e9a4bfSMitsuru IWASAKI 
1522986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1523c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
15242177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1525986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1526986dffafSJohn Baldwin 	       fadt->Dsdt);
1527986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1528986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
15298e6a8737SNate Lawson 		pm = "Reserved";
15308e6a8737SNate Lawson 	else
1531986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1532986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1533986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1534986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1535986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1536986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1537986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1538986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1539e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1540986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1541986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1542986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1543e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1544986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1545986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1546e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1547986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1548986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1549986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1550e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1551986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1552986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1553986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1554e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1555986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1556986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1557c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1558986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1559986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1560986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
15618e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1562986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1563986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1564986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
15658e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1566986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1567986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1568986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1569986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1570986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
157151c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1572986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1573e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1574986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1575e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1576986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1577e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1578986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1579e1e9a4bfSMitsuru IWASAKI 
1580ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1581e1e9a4bfSMitsuru IWASAKI 
15828e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1583986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1584986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1585986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1586986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1587986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1588f6469ce1SAndrew Turner 	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1589ec650989SNeel Natu 	PRINTFLAG_END();
15908e6a8737SNate Lawson 
15918e6a8737SNate Lawson 	printf("\tFlags=");
1592986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1593986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1594986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1595986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1596986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1597986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1598986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1599986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1600986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1601986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1602986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1603986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1604986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1605986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1606986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1607986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1608986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1609986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1610986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1611986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1612f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, HW_REDUCED);
1613f6469ce1SAndrew Turner 	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1614ec650989SNeel Natu 	PRINTFLAG_END();
1615e1e9a4bfSMitsuru IWASAKI 
1616e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1617e1e9a4bfSMitsuru IWASAKI 
1618986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
16198e6a8737SNate Lawson 		printf("\tRESET_REG=");
1620986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1621986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
16228e6a8737SNate Lawson 	}
1623c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
16247d369c6eSJung-uk Kim 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
16257d369c6eSJung-uk Kim 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1626c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1627986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1628986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1629c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1630986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1631c08c4e81SNate Lawson 		}
1632c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1633986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1634986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1635c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1636986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1637c08c4e81SNate Lawson 		}
1638986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1639773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1640986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1641c08c4e81SNate Lawson 		}
1642773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1643986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1644986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1645773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1646986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1647c08c4e81SNate Lawson 		}
1648986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1649773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1650986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1651c08c4e81SNate Lawson 		}
1652773b6454SNate Lawson 		printf("\n");
1653773b6454SNate Lawson 	}
16548e6a8737SNate Lawson 
16558e6a8737SNate Lawson 	printf(END_COMMENT);
16568e6a8737SNate Lawson }
16578e6a8737SNate Lawson 
16588e6a8737SNate Lawson static void
1659986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
16608e6a8737SNate Lawson {
16618e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1662986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1663986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1664986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
16658e6a8737SNate Lawson 
1666773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1667986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1668986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
16698e6a8737SNate Lawson 			printf("PENDING,");
1670986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
16718e6a8737SNate Lawson 			printf("OWNED");
16728e6a8737SNate Lawson 	}
1673773b6454SNate Lawson 	printf("\n");
16748e6a8737SNate Lawson 
1675773b6454SNate Lawson 	printf("\tFlags=");
1676986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
16778e6a8737SNate Lawson 		printf("S4BIOS");
1678773b6454SNate Lawson 	printf("\n");
16798e6a8737SNate Lawson 
16807d369c6eSJung-uk Kim 	if (facs->XFirmwareWakingVector != 0)
16817d369c6eSJung-uk Kim 		printf("\tX_Firm_Wake_Vec=%016jx\n",
16827d369c6eSJung-uk Kim 		    (uintmax_t)facs->XFirmwareWakingVector);
1683986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
16848e6a8737SNate Lawson 
1685c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1686e1e9a4bfSMitsuru IWASAKI }
1687e1e9a4bfSMitsuru IWASAKI 
1688945137d9SNate Lawson static void
1689986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1690e1e9a4bfSMitsuru IWASAKI {
1691773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1692773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1693773b6454SNate Lawson 	printf(END_COMMENT);
1694e1e9a4bfSMitsuru IWASAKI }
1695e1e9a4bfSMitsuru IWASAKI 
1696e1e9a4bfSMitsuru IWASAKI int
1697e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1698e1e9a4bfSMitsuru IWASAKI {
1699986dffafSJohn Baldwin 	uint8_t *bp;
1700986dffafSJohn Baldwin 	uint8_t sum;
1701e1e9a4bfSMitsuru IWASAKI 
1702e1e9a4bfSMitsuru IWASAKI 	bp = p;
1703e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1704e1e9a4bfSMitsuru IWASAKI 	while (length--)
1705e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1706e1e9a4bfSMitsuru IWASAKI 
1707e1e9a4bfSMitsuru IWASAKI 	return (sum);
1708e1e9a4bfSMitsuru IWASAKI }
1709e1e9a4bfSMitsuru IWASAKI 
1710986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1711e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1712e1e9a4bfSMitsuru IWASAKI {
1713986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1714e1e9a4bfSMitsuru IWASAKI 
1715986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1716986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1717e1e9a4bfSMitsuru IWASAKI 	return (sp);
1718e1e9a4bfSMitsuru IWASAKI }
1719e1e9a4bfSMitsuru IWASAKI 
1720945137d9SNate Lawson static void
1721986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1722e1e9a4bfSMitsuru IWASAKI {
1723c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1724a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1725986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1726986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1727986dffafSJohn Baldwin 	       rp->Revision);
1728986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1729986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1730986dffafSJohn Baldwin 		    rp->Checksum);
1731a74172abSNate Lawson 	} else {
17327d369c6eSJung-uk Kim 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
17337d369c6eSJung-uk Kim 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
1734986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1735a74172abSNate Lawson 	}
1736c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1737e1e9a4bfSMitsuru IWASAKI }
1738e1e9a4bfSMitsuru IWASAKI 
1739945137d9SNate Lawson static void
1740986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1741e1e9a4bfSMitsuru IWASAKI {
1742986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1743986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1744986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1745a74172abSNate Lawson 	vm_offset_t addr;
1746a74172abSNate Lawson 	int entries, i;
1747e1e9a4bfSMitsuru IWASAKI 
1748e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1749986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1750986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1751986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1752e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1753fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1754986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1755fe1d0c2dSJung-uk Kim 		else
1756986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1757fe1d0c2dSJung-uk Kim 		if (addr == 0)
1758fe1d0c2dSJung-uk Kim 			continue;
1759986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1760986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
17615cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1762986dffafSJohn Baldwin 			    sdp->Signature);
17635cf6d493SNate Lawson 			continue;
17645cf6d493SNate Lawson 		}
1765986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
17662177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1767986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1768986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1769986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
177079d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1771986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
177255d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1773986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1774a47e681bSScott Long 			acpi_handle_mcfg(sdp);
177533866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
177633866658SJohn Baldwin 			acpi_handle_slit(sdp);
1777986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1778a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1779c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1780c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1781ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1782ec650989SNeel Natu 			acpi_handle_dmar(sdp);
1783340c0022SEd Maste 		else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
1784340c0022SEd Maste 			acpi_handle_nfit(sdp);
1785ed26c389SScott Long 		else if (!memcmp(sdp->Signature, ACPI_SIG_WDDT, 4))
1786ed26c389SScott Long 			acpi_handle_wddt(sdp);
17875857fba5SBen Widawsky 		else if (!memcmp(sdp->Signature, ACPI_SIG_LPIT, 4))
17885857fba5SBen Widawsky 			acpi_handle_lpit(sdp);
1789877fc2e3STakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TPM2, 4))
1790877fc2e3STakanori Watanabe 			acpi_handle_tpm2(sdp);
1791773b6454SNate Lawson 		else {
1792773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1793773b6454SNate Lawson 			acpi_print_sdt(sdp);
1794773b6454SNate Lawson 			printf(END_COMMENT);
1795773b6454SNate Lawson 		}
1796e1e9a4bfSMitsuru IWASAKI 	}
1797e1e9a4bfSMitsuru IWASAKI }
1798c62f1cccSMitsuru IWASAKI 
1799986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1800476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1801945137d9SNate Lawson {
1802986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1803986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1804945137d9SNate Lawson 
1805945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1806945137d9SNate Lawson 	if (!rp)
1807945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1808945137d9SNate Lawson 
1809945137d9SNate Lawson 	if (tflag)
1810945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1811986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1812986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1813986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1814986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1815945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1816a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1817a74172abSNate Lawson 	} else {
1818986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1819986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1820986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1821a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1822a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1823a74172abSNate Lawson 	}
1824945137d9SNate Lawson 	return (rsdp);
1825945137d9SNate Lawson }
1826c62f1cccSMitsuru IWASAKI 
182762c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1828bfa3f012SMarcel Moolenaar static int
1829986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1830bfa3f012SMarcel Moolenaar {
1831986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1832986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1833bfa3f012SMarcel Moolenaar 	uint8_t sum;
1834bfa3f012SMarcel Moolenaar 
183562c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1836bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1837bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1838986dffafSJohn Baldwin 		sdt.Checksum = 0;
1839986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1840986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1841986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1842f7675a56SNate Lawson 		while (ssdt != NULL) {
1843986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1844986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1845986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1846986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1847bfa3f012SMarcel Moolenaar 		}
1848986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1849986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1850bfa3f012SMarcel Moolenaar 	}
185162c7bde1SNate Lawson 
185262c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1853986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1854986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
185562c7bde1SNate Lawson 
1856b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1857f7675a56SNate Lawson 	if (rsdt != NULL) {
1858bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1859bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1860986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1861986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1862bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1863bfa3f012SMarcel Moolenaar 		}
1864bfa3f012SMarcel Moolenaar 	}
1865bfa3f012SMarcel Moolenaar 	return (0);
1866bfa3f012SMarcel Moolenaar }
1867bfa3f012SMarcel Moolenaar 
1868c62f1cccSMitsuru IWASAKI void
1869986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1870c62f1cccSMitsuru IWASAKI {
1871945137d9SNate Lawson 	int	fd;
1872945137d9SNate Lawson 	mode_t	mode;
1873945137d9SNate Lawson 
1874945137d9SNate Lawson 	assert(outfile != NULL);
1875945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1876945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1877945137d9SNate Lawson 	if (fd == -1) {
1878945137d9SNate Lawson 		perror("dsdt_save_file");
1879945137d9SNate Lawson 		return;
1880945137d9SNate Lawson 	}
1881bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1882945137d9SNate Lawson 	close(fd);
1883c62f1cccSMitsuru IWASAKI }
1884c62f1cccSMitsuru IWASAKI 
1885945137d9SNate Lawson void
1886986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1887c62f1cccSMitsuru IWASAKI {
18887e2cc014SDon Lewis 	char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
18897e2cc014SDon Lewis 	const char *iname = "/acpdump.din";
18907e2cc014SDon Lewis 	const char *oname = "/acpdump.dsl";
189199065116SJung-uk Kim 	const char *tmpdir;
1892945137d9SNate Lawson 	FILE *fp;
189399065116SJung-uk Kim 	size_t len;
18947e2cc014SDon Lewis 	int fd, status;
18957e2cc014SDon Lewis 	pid_t pid;
1896945137d9SNate Lawson 
189799065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
189899065116SJung-uk Kim 	if (tmpdir == NULL)
189999065116SJung-uk Kim 		tmpdir = _PATH_TMP;
19007e2cc014SDon Lewis 	if (realpath(tmpdir, buf) == NULL) {
1901d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
190299065116SJung-uk Kim 		return;
190399065116SJung-uk Kim 	}
19047e2cc014SDon Lewis 	len = sizeof(wrkdir) - strlen(iname);
19057e2cc014SDon Lewis 	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
19067e2cc014SDon Lewis 		fprintf(stderr, "$TMPDIR too long\n");
19077e2cc014SDon Lewis 		return;
19087e2cc014SDon Lewis 	}
19097e2cc014SDon Lewis 	if  (mkdtemp(wrkdir) == NULL) {
19107e2cc014SDon Lewis 		perror("mkdtemp tmp working dir");
19117e2cc014SDon Lewis 		return;
19127e2cc014SDon Lewis 	}
191330bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
191430bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
19157e2cc014SDon Lewis 	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1916945137d9SNate Lawson 	if (fd < 0) {
1917945137d9SNate Lawson 		perror("iasl tmp file");
1918945137d9SNate Lawson 		return;
1919c62f1cccSMitsuru IWASAKI 	}
1920bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1921945137d9SNate Lawson 	close(fd);
1922945137d9SNate Lawson 
1923945137d9SNate Lawson 	/* Run iasl -d on the temp file */
19247e2cc014SDon Lewis 	if ((pid = fork()) == 0) {
1925945137d9SNate Lawson 		close(STDOUT_FILENO);
1926945137d9SNate Lawson 		if (vflag == 0)
1927945137d9SNate Lawson 			close(STDERR_FILENO);
192899065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1929945137d9SNate Lawson 		err(1, "exec");
1930c62f1cccSMitsuru IWASAKI 	}
19317e2cc014SDon Lewis 	if (pid > 0)
19327e2cc014SDon Lewis 		wait(&status);
19337e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
19347e2cc014SDon Lewis 		perror("unlink");
19357e2cc014SDon Lewis 		goto out;
19367e2cc014SDon Lewis 	}
19377e2cc014SDon Lewis 	if (pid < 0) {
19387e2cc014SDon Lewis 		perror("fork");
19397e2cc014SDon Lewis 		goto out;
19407e2cc014SDon Lewis 	}
19417e2cc014SDon Lewis 	if (status != 0) {
19427e2cc014SDon Lewis 		fprintf(stderr, "iast exit status = %d\n", status);
19437e2cc014SDon Lewis 	}
1944945137d9SNate Lawson 
1945945137d9SNate Lawson 	/* Dump iasl's output to stdout */
194630bebccaSMaxim Konovalov 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
194730bebccaSMaxim Konovalov 	assert(len <= sizeof(tmpstr) - 1);
194899065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
19497e2cc014SDon Lewis 	if (unlink(tmpstr) < 0) {
19507e2cc014SDon Lewis 		perror("unlink");
19517e2cc014SDon Lewis 		goto out;
19527e2cc014SDon Lewis 	}
1953945137d9SNate Lawson 	if (fp == NULL) {
1954945137d9SNate Lawson 		perror("iasl tmp file (read)");
19557e2cc014SDon Lewis 		goto out;
1956945137d9SNate Lawson 	}
1957945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1958945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1959945137d9SNate Lawson 	fclose(fp);
19607e2cc014SDon Lewis 
19617e2cc014SDon Lewis     out:
19627e2cc014SDon Lewis 	if (rmdir(wrkdir) < 0)
19637e2cc014SDon Lewis 		perror("rmdir");
1964c62f1cccSMitsuru IWASAKI }
1965c62f1cccSMitsuru IWASAKI 
1966945137d9SNate Lawson void
1967986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1968c62f1cccSMitsuru IWASAKI {
1969945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1970c62f1cccSMitsuru IWASAKI }
1971c62f1cccSMitsuru IWASAKI 
1972bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1973986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1974986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1975c62f1cccSMitsuru IWASAKI {
1976986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1977986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1978986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1979a74172abSNate Lawson 	vm_offset_t addr;
1980a74172abSNate Lawson 	int entries, i;
1981945137d9SNate Lawson 
1982986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1983986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1984986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1985945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1986fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1987986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1988fe1d0c2dSJung-uk Kim 		else
1989986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1990fe1d0c2dSJung-uk Kim 		if (addr == 0)
1991fe1d0c2dSJung-uk Kim 			continue;
1992986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1993bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1994bfa3f012SMarcel Moolenaar 			if (sdt == last)
1995bfa3f012SMarcel Moolenaar 				last = NULL;
1996bfa3f012SMarcel Moolenaar 			continue;
1997bfa3f012SMarcel Moolenaar 		}
1998986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1999a74172abSNate Lawson 			continue;
2000986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
2001945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
2002945137d9SNate Lawson 		return (sdt);
2003c62f1cccSMitsuru IWASAKI 	}
2004c62f1cccSMitsuru IWASAKI 
2005945137d9SNate Lawson 	return (NULL);
2006c62f1cccSMitsuru IWASAKI }
2007c62f1cccSMitsuru IWASAKI 
2008986dffafSJohn Baldwin ACPI_TABLE_HEADER *
2009986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
2010c62f1cccSMitsuru IWASAKI {
2011986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
2012c62f1cccSMitsuru IWASAKI 
2013986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
2014c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
2015986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
20162e71eb12SNate Lawson 	else
2017986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
2018986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
2019945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
2020945137d9SNate Lawson 	return (sdt);
2021c62f1cccSMitsuru IWASAKI }
2022