xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision 7d369c6e2f59b57919127121382eb99e81f8401c)
1e1e9a4bfSMitsuru IWASAKI /*-
2e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 1998 Doug Rabson
3e1e9a4bfSMitsuru IWASAKI  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
4e1e9a4bfSMitsuru IWASAKI  * All rights reserved.
5e1e9a4bfSMitsuru IWASAKI  *
6e1e9a4bfSMitsuru IWASAKI  * Redistribution and use in source and binary forms, with or without
7e1e9a4bfSMitsuru IWASAKI  * modification, are permitted provided that the following conditions
8e1e9a4bfSMitsuru IWASAKI  * are met:
9e1e9a4bfSMitsuru IWASAKI  * 1. Redistributions of source code must retain the above copyright
10e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer.
11e1e9a4bfSMitsuru IWASAKI  * 2. Redistributions in binary form must reproduce the above copyright
12e1e9a4bfSMitsuru IWASAKI  *    notice, this list of conditions and the following disclaimer in the
13e1e9a4bfSMitsuru IWASAKI  *    documentation and/or other materials provided with the distribution.
14e1e9a4bfSMitsuru IWASAKI  *
15e1e9a4bfSMitsuru IWASAKI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e1e9a4bfSMitsuru IWASAKI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e1e9a4bfSMitsuru IWASAKI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e1e9a4bfSMitsuru IWASAKI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e1e9a4bfSMitsuru IWASAKI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e1e9a4bfSMitsuru IWASAKI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e1e9a4bfSMitsuru IWASAKI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e1e9a4bfSMitsuru IWASAKI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e1e9a4bfSMitsuru IWASAKI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e1e9a4bfSMitsuru IWASAKI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e1e9a4bfSMitsuru IWASAKI  * SUCH DAMAGE.
26e1e9a4bfSMitsuru IWASAKI  *
27e1e9a4bfSMitsuru IWASAKI  *	$FreeBSD$
28e1e9a4bfSMitsuru IWASAKI  */
29e1e9a4bfSMitsuru IWASAKI 
30e1e9a4bfSMitsuru IWASAKI #include <sys/param.h>
31a74172abSNate Lawson #include <sys/endian.h>
32e1e9a4bfSMitsuru IWASAKI #include <sys/stat.h>
33945137d9SNate Lawson #include <sys/wait.h>
34e1e9a4bfSMitsuru IWASAKI #include <assert.h>
35e1e9a4bfSMitsuru IWASAKI #include <err.h>
36e1e9a4bfSMitsuru IWASAKI #include <fcntl.h>
3799065116SJung-uk Kim #include <paths.h>
38e1e9a4bfSMitsuru IWASAKI #include <stdio.h>
39a0333ad1SJohn Baldwin #include <stdint.h>
4099065116SJung-uk Kim #include <stdlib.h>
41945137d9SNate Lawson #include <string.h>
42e1e9a4bfSMitsuru IWASAKI #include <unistd.h>
43e1e9a4bfSMitsuru IWASAKI 
44e1e9a4bfSMitsuru IWASAKI #include "acpidump.h"
45e1e9a4bfSMitsuru IWASAKI 
46c62f1cccSMitsuru IWASAKI #define BEGIN_COMMENT	"/*\n"
47c62f1cccSMitsuru IWASAKI #define END_COMMENT	" */\n"
48c62f1cccSMitsuru IWASAKI 
49945137d9SNate Lawson static void	acpi_print_string(char *s, size_t length);
50986dffafSJohn Baldwin static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
51986dffafSJohn Baldwin static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
52986dffafSJohn Baldwin static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
53945137d9SNate Lawson static void	acpi_print_cpu(u_char cpu_id);
54986dffafSJohn Baldwin static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
55986dffafSJohn Baldwin static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
56986dffafSJohn Baldwin static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
57986dffafSJohn Baldwin 		    uint64_t apic_addr);
58986dffafSJohn Baldwin static void	acpi_print_mps_flags(uint16_t flags);
59986dffafSJohn Baldwin static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
60986dffafSJohn Baldwin static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
61986dffafSJohn Baldwin static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
62986dffafSJohn Baldwin static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
63986dffafSJohn Baldwin static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
64986dffafSJohn Baldwin static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
65986dffafSJohn Baldwin static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
6633866658SJohn Baldwin static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
67a0333ad1SJohn Baldwin static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
68a0333ad1SJohn Baldwin 		    uint32_t flags);
69986dffafSJohn Baldwin static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
70986dffafSJohn Baldwin static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
71986dffafSJohn Baldwin static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
72c031c93bSTakanori Watanabe static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
73986dffafSJohn Baldwin static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
74986dffafSJohn Baldwin static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
75986dffafSJohn Baldwin static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
76986dffafSJohn Baldwin static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
77986dffafSJohn Baldwin static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
78986dffafSJohn Baldwin static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
79986dffafSJohn Baldwin static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
80986dffafSJohn Baldwin static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
81986dffafSJohn Baldwin 		    void (*action)(ACPI_SUBTABLE_HEADER *));
82c62f1cccSMitsuru IWASAKI 
83773b6454SNate Lawson /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
84a74172abSNate Lawson static int addr_size;
85a74172abSNate Lawson 
86c031c93bSTakanori Watanabe /* Strings used in the TCPA table */
87c031c93bSTakanori Watanabe static const char *tcpa_event_type_strings[] = {
88c031c93bSTakanori Watanabe 	"PREBOOT Certificate",
89c031c93bSTakanori Watanabe 	"POST Code",
90c031c93bSTakanori Watanabe 	"Unused",
91c031c93bSTakanori Watanabe 	"No Action",
92c031c93bSTakanori Watanabe 	"Separator",
93c031c93bSTakanori Watanabe 	"Action",
94c031c93bSTakanori Watanabe 	"Event Tag",
95c031c93bSTakanori Watanabe 	"S-CRTM Contents",
96c031c93bSTakanori Watanabe 	"S-CRTM Version",
97c031c93bSTakanori Watanabe 	"CPU Microcode",
98c031c93bSTakanori Watanabe 	"Platform Config Flags",
99c031c93bSTakanori Watanabe 	"Table of Devices",
100c031c93bSTakanori Watanabe 	"Compact Hash",
101c031c93bSTakanori Watanabe 	"IPL",
102c031c93bSTakanori Watanabe 	"IPL Partition Data",
103c031c93bSTakanori Watanabe 	"Non-Host Code",
104c031c93bSTakanori Watanabe 	"Non-Host Config",
105c031c93bSTakanori Watanabe 	"Non-Host Info"
106c031c93bSTakanori Watanabe };
107c031c93bSTakanori Watanabe 
108c031c93bSTakanori Watanabe static const char *TCPA_pcclient_strings[] = {
109c031c93bSTakanori Watanabe 	"<undefined>",
110c031c93bSTakanori Watanabe 	"SMBIOS",
111c031c93bSTakanori Watanabe 	"BIS Certificate",
112c031c93bSTakanori Watanabe 	"POST BIOS ROM Strings",
113c031c93bSTakanori Watanabe 	"ESCD",
114c031c93bSTakanori Watanabe 	"CMOS",
115c031c93bSTakanori Watanabe 	"NVRAM",
116c031c93bSTakanori Watanabe 	"Option ROM Execute",
117c031c93bSTakanori Watanabe 	"Option ROM Configurateion",
118c031c93bSTakanori Watanabe 	"<undefined>",
119c031c93bSTakanori Watanabe 	"Option ROM Microcode Update ",
120c031c93bSTakanori Watanabe 	"S-CRTM Version String",
121c031c93bSTakanori Watanabe 	"S-CRTM Contents",
122c031c93bSTakanori Watanabe 	"POST Contents",
123c031c93bSTakanori Watanabe 	"Table of Devices",
124c031c93bSTakanori Watanabe };
125c031c93bSTakanori Watanabe 
126ec650989SNeel Natu #define	PRINTFLAG_END()		printflag_end()
127ec650989SNeel Natu 
128ec650989SNeel Natu static char pf_sep = '{';
129ec650989SNeel Natu 
130ec650989SNeel Natu static void
131ec650989SNeel Natu printflag_end(void)
132ec650989SNeel Natu {
133ec650989SNeel Natu 
134ec650989SNeel Natu 	if (pf_sep != '{') {
135ec650989SNeel Natu 		printf("}");
136ec650989SNeel Natu 		pf_sep = '{';
137ec650989SNeel Natu 	}
138ec650989SNeel Natu 	printf("\n");
139ec650989SNeel Natu }
140ec650989SNeel Natu 
141ec650989SNeel Natu static void
142ec650989SNeel Natu printflag(uint64_t var, uint64_t mask, const char *name)
143ec650989SNeel Natu {
144ec650989SNeel Natu 
145ec650989SNeel Natu 	if (var & mask) {
146ec650989SNeel Natu 		printf("%c%s", pf_sep, name);
147ec650989SNeel Natu 		pf_sep = ',';
148ec650989SNeel Natu 	}
149ec650989SNeel Natu }
150ec650989SNeel Natu 
151e1e9a4bfSMitsuru IWASAKI static void
152e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
153e1e9a4bfSMitsuru IWASAKI {
154e1e9a4bfSMitsuru IWASAKI 	int	c;
155e1e9a4bfSMitsuru IWASAKI 
156e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
157e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
158e1e9a4bfSMitsuru IWASAKI 		length--;
159e1e9a4bfSMitsuru IWASAKI 
160e1e9a4bfSMitsuru IWASAKI 	while (length--) {
161e1e9a4bfSMitsuru IWASAKI 		c = *s++;
162e1e9a4bfSMitsuru IWASAKI 		putchar(c);
163e1e9a4bfSMitsuru IWASAKI 	}
164e1e9a4bfSMitsuru IWASAKI }
165e1e9a4bfSMitsuru IWASAKI 
166e1e9a4bfSMitsuru IWASAKI static void
167986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1688e6a8737SNate Lawson {
169986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1708e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
171*7d369c6eSJung-uk Kim 		if (gas->BitWidth <= 32)
172*7d369c6eSJung-uk Kim 			printf("0x%08x:%u[%u] (Memory)",
173*7d369c6eSJung-uk Kim 			    (u_int)gas->Address, gas->BitOffset,
174*7d369c6eSJung-uk Kim 			    gas->BitWidth);
175*7d369c6eSJung-uk Kim 		else
176*7d369c6eSJung-uk Kim 			printf("0x%016jx:%u[%u] (Memory)",
177*7d369c6eSJung-uk Kim 			    (uintmax_t)gas->Address, gas->BitOffset,
178*7d369c6eSJung-uk Kim 			    gas->BitWidth);
1798e6a8737SNate Lawson 		break;
1808e6a8737SNate Lawson 	case ACPI_GAS_IO:
181*7d369c6eSJung-uk Kim 		printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
182986dffafSJohn Baldwin 		    gas->BitOffset, gas->BitWidth);
1838e6a8737SNate Lawson 		break;
1848e6a8737SNate Lawson 	case ACPI_GAS_PCI:
185986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
186986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
187986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1888e6a8737SNate Lawson 		break;
1898e6a8737SNate Lawson 	/* XXX How to handle these below? */
1908e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
191986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
192986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1938e6a8737SNate Lawson 		break;
1948e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
195986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
196986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1978e6a8737SNate Lawson 		break;
198986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
199986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
200986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
2018e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
2028e6a8737SNate Lawson 	default:
203*7d369c6eSJung-uk Kim 		printf("0x%016jx (?)", (uintmax_t)gas->Address);
2048e6a8737SNate Lawson 		break;
2058e6a8737SNate Lawson 	}
2068e6a8737SNate Lawson }
2078e6a8737SNate Lawson 
208c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
209c2962974SNate Lawson static int
210986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
211e1e9a4bfSMitsuru IWASAKI {
212c2962974SNate Lawson 	int fadt_revision;
213e1e9a4bfSMitsuru IWASAKI 
214c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
215c83f0f99SNate Lawson 	if (addr_size == 8) {
216c83f0f99SNate Lawson 		fadt_revision = 2;
2178e6a8737SNate Lawson 
218773b6454SNate Lawson 		/*
219c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
220c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
221c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
222c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
223c83f0f99SNate Lawson 		 * version for all subsequent tables.
224773b6454SNate Lawson 		 */
225986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
226986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
227c83f0f99SNate Lawson 			fadt_revision = 1;
228c2962974SNate Lawson 	} else
229c83f0f99SNate Lawson 		fadt_revision = 1;
230c2962974SNate Lawson 	return (fadt_revision);
231c83f0f99SNate Lawson }
232c2962974SNate Lawson 
233c2962974SNate Lawson static void
234986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
235c2962974SNate Lawson {
236986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
237986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
238986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
239c2962974SNate Lawson 	int		fadt_revision;
240c2962974SNate Lawson 
241986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2422177d4e6SNate Lawson 	acpi_print_fadt(sdp);
243c83f0f99SNate Lawson 
244c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
245c83f0f99SNate Lawson 	if (fadt_revision == 1)
246986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
247773b6454SNate Lawson 	else
248986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
249986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2508e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2518e6a8737SNate Lawson 	acpi_print_facs(facs);
2528e6a8737SNate Lawson 
253c83f0f99SNate Lawson 	if (fadt_revision == 1)
254986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
255773b6454SNate Lawson 	else
256986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
257986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
258945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
259945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
260c62f1cccSMitsuru IWASAKI }
261c62f1cccSMitsuru IWASAKI 
262c62f1cccSMitsuru IWASAKI static void
263986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
264986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
265986dffafSJohn Baldwin {
266986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
267986dffafSJohn Baldwin 	char *end;
268986dffafSJohn Baldwin 
269986dffafSJohn Baldwin 	subtable = first;
270986dffafSJohn Baldwin 	end = (char *)table + table->Length;
271986dffafSJohn Baldwin 	while ((char *)subtable < end) {
272986dffafSJohn Baldwin 		printf("\n");
273986dffafSJohn Baldwin 		action(subtable);
274986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
275986dffafSJohn Baldwin 		    subtable->Length);
276986dffafSJohn Baldwin 	}
277986dffafSJohn Baldwin }
278986dffafSJohn Baldwin 
279986dffafSJohn Baldwin static void
2800a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
2810a473124SJohn Baldwin {
2820a473124SJohn Baldwin 
2830a473124SJohn Baldwin 	printf("\tACPI CPU=");
2840a473124SJohn Baldwin 	if (cpu_id == 0xff)
2850a473124SJohn Baldwin 		printf("ALL\n");
2860a473124SJohn Baldwin 	else
2870a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
2880a473124SJohn Baldwin }
2890a473124SJohn Baldwin 
2900a473124SJohn Baldwin static void
291986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
2920a473124SJohn Baldwin {
293986dffafSJohn Baldwin 
294986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
295986dffafSJohn Baldwin 	if (uid_string != NULL)
296986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
297986dffafSJohn Baldwin 	printf("\n");
298986dffafSJohn Baldwin }
299986dffafSJohn Baldwin 
300986dffafSJohn Baldwin static void
301986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
302986dffafSJohn Baldwin {
303986dffafSJohn Baldwin 
3040a473124SJohn Baldwin 	printf("\tFlags={");
305986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
3060a473124SJohn Baldwin 		printf("ENABLED");
3070a473124SJohn Baldwin 	else
3080a473124SJohn Baldwin 		printf("DISABLED");
3090a473124SJohn Baldwin 	printf("}\n");
310986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3110a473124SJohn Baldwin }
3120a473124SJohn Baldwin 
3130a473124SJohn Baldwin static void
314986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
3150a473124SJohn Baldwin {
316986dffafSJohn Baldwin 
317986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3180a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
319986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
3200a473124SJohn Baldwin }
3210a473124SJohn Baldwin 
3220a473124SJohn Baldwin static void
323986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
3240a473124SJohn Baldwin {
3250a473124SJohn Baldwin 
3260a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
327986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
328986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
3290a473124SJohn Baldwin 		printf("conforming");
3300a473124SJohn Baldwin 		break;
331986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3320a473124SJohn Baldwin 		printf("active-hi");
3330a473124SJohn Baldwin 		break;
334986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3350a473124SJohn Baldwin 		printf("active-lo");
3360a473124SJohn Baldwin 		break;
3370a473124SJohn Baldwin 	default:
338986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3390a473124SJohn Baldwin 		break;
3400a473124SJohn Baldwin 	}
3410a473124SJohn Baldwin 	printf(", Trigger=");
342986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
343986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3440a473124SJohn Baldwin 		printf("conforming");
3450a473124SJohn Baldwin 		break;
346986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3470a473124SJohn Baldwin 		printf("edge");
3480a473124SJohn Baldwin 		break;
349986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3500a473124SJohn Baldwin 		printf("level");
3510a473124SJohn Baldwin 		break;
3520a473124SJohn Baldwin 	default:
353986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3540a473124SJohn Baldwin 	}
3550a473124SJohn Baldwin 	printf("}\n");
3560a473124SJohn Baldwin }
3570a473124SJohn Baldwin 
3580a473124SJohn Baldwin static void
359986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
3600a473124SJohn Baldwin {
3610a473124SJohn Baldwin 
362986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
363986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
364986dffafSJohn Baldwin }
365986dffafSJohn Baldwin 
366986dffafSJohn Baldwin static void
367986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
368986dffafSJohn Baldwin {
369986dffafSJohn Baldwin 
370986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
3710a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
3720a473124SJohn Baldwin }
3730a473124SJohn Baldwin 
374bf70beceSEd Schouten static const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override",
375bf70beceSEd Schouten 				    "NMI", "Local APIC NMI",
376bf70beceSEd Schouten 				    "Local APIC Override", "IO SAPIC",
377bf70beceSEd Schouten 				    "Local SAPIC", "Platform Interrupt",
378986dffafSJohn Baldwin 				    "Local X2APIC", "Local X2APIC NMI" };
379bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
3800a473124SJohn Baldwin 					    "Corrected Platform Error" };
3810a473124SJohn Baldwin 
3820a473124SJohn Baldwin static void
383986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
3840a473124SJohn Baldwin {
385986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
386986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
387986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
388986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
389986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
390986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
391986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
392986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
393986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
394986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
395986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
3960a473124SJohn Baldwin 
397986dffafSJohn Baldwin 	if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0]))
398986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
399a0333ad1SJohn Baldwin 	else
400986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
401986dffafSJohn Baldwin 	switch (mp->Type) {
402986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
403986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
404986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
405986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4060a473124SJohn Baldwin 		break;
407986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
408986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
409986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
410986dffafSJohn Baldwin 		    ioapic->Address);
4110a473124SJohn Baldwin 		break;
412986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
413986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
414986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
415986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
416986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
4170a473124SJohn Baldwin 		break;
418986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
419986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
420986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
4210a473124SJohn Baldwin 		break;
422986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
423986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
424986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
425986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
4260a473124SJohn Baldwin 		break;
427986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
428986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
429945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
430986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
4310a473124SJohn Baldwin 		break;
432986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
433986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
434986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
435986dffafSJohn Baldwin 		    iosapic->Address);
4360a473124SJohn Baldwin 		break;
437986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
438986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
439986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
440986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
441986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
442986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
443986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
4440a473124SJohn Baldwin 		break;
445986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
446986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
447986dffafSJohn Baldwin 		if (isrc->Type < sizeof(platform_int_types) /
448986dffafSJohn Baldwin 		    sizeof(platform_int_types[0]))
449986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
450986dffafSJohn Baldwin 		else
451986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
452986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
453986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
454986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
455986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
456986dffafSJohn Baldwin 		break;
457986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
458986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
459986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
460986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
461986dffafSJohn Baldwin 		break;
462986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
463986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
464986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
465986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
4660a473124SJohn Baldwin 		break;
4670a473124SJohn Baldwin 	}
4680a473124SJohn Baldwin }
4690a473124SJohn Baldwin 
4700a473124SJohn Baldwin static void
471986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
4720a473124SJohn Baldwin {
473986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
4740a473124SJohn Baldwin 
475773b6454SNate Lawson 	printf(BEGIN_COMMENT);
476773b6454SNate Lawson 	acpi_print_sdt(sdp);
477986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
478986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
4790a473124SJohn Baldwin 	printf("\tFlags={");
480986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
4810a473124SJohn Baldwin 		printf("PC-AT");
4820a473124SJohn Baldwin 	printf("}\n");
483986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
4840a473124SJohn Baldwin 	printf(END_COMMENT);
4850a473124SJohn Baldwin }
4860a473124SJohn Baldwin 
4870a473124SJohn Baldwin static void
488986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
48979d7565cSPeter Wemm {
490986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
49179d7565cSPeter Wemm 
492773b6454SNate Lawson 	printf(BEGIN_COMMENT);
493773b6454SNate Lawson 	acpi_print_sdt(sdp);
494986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
495986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
49687f9f09aSTakanori Watanabe 	printf("\tADDR=");
497986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
498986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
499986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
500986dffafSJohn Baldwin 	    8);
501986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
502986dffafSJohn Baldwin 	    1 : 0);
50379d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
504986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
50579d7565cSPeter Wemm 		printf("TRUE}\n");
50679d7565cSPeter Wemm 	else
50779d7565cSPeter Wemm 		printf("FALSE}\n");
508986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
509986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
5109785e979SNeel Natu 	printf("\tFlags=0x%02x\n", hpet->Flags);
51179d7565cSPeter Wemm 	printf(END_COMMENT);
51279d7565cSPeter Wemm }
51379d7565cSPeter Wemm 
51479d7565cSPeter Wemm static void
515986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
51655d7ff9eSNate Lawson {
517986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
51855d7ff9eSNate Lawson 
51955d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
52055d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
521986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
52255d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
523986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
52455d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
525986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
526986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
527986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
528986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
52955d7ff9eSNate Lawson 	printf(END_COMMENT);
53055d7ff9eSNate Lawson }
53155d7ff9eSNate Lawson 
53255d7ff9eSNate Lawson static void
533986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
534a47e681bSScott Long {
535986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
536986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
537986dffafSJohn Baldwin 	u_int i, entries;
538a47e681bSScott Long 
539a47e681bSScott Long 	printf(BEGIN_COMMENT);
540a47e681bSScott Long 	acpi_print_sdt(sdp);
541986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
542986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
543986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
544986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
545986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
546a47e681bSScott Long 		printf("\n");
5470c10b85aSJung-uk Kim 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
548986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
549986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
550986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
551a47e681bSScott Long 	}
552a47e681bSScott Long 	printf(END_COMMENT);
553a47e681bSScott Long }
554a47e681bSScott Long 
555a47e681bSScott Long static void
55633866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
55733866658SJohn Baldwin {
55833866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
55933866658SJohn Baldwin 	UINT64 i, j;
56033866658SJohn Baldwin 
56133866658SJohn Baldwin 	printf(BEGIN_COMMENT);
56233866658SJohn Baldwin 	acpi_print_sdt(sdp);
56333866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
5640c10b85aSJung-uk Kim 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
56533866658SJohn Baldwin 	printf("\n\t      ");
56633866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
5670c10b85aSJung-uk Kim 		printf(" %3ju", (uintmax_t)i);
56833866658SJohn Baldwin 	printf("\n\t     +");
56933866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
57033866658SJohn Baldwin 		printf("----");
57133866658SJohn Baldwin 	printf("\n");
57233866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
5730c10b85aSJung-uk Kim 		printf("\t %3ju |", (uintmax_t)i);
57433866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
57533866658SJohn Baldwin 			printf(" %3d",
57633866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
57733866658SJohn Baldwin 		printf("\n");
57833866658SJohn Baldwin 	}
57933866658SJohn Baldwin 	printf(END_COMMENT);
58033866658SJohn Baldwin }
58133866658SJohn Baldwin 
58233866658SJohn Baldwin static void
583a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
584a0333ad1SJohn Baldwin     uint32_t flags)
585a0333ad1SJohn Baldwin {
586a0333ad1SJohn Baldwin 
587a0333ad1SJohn Baldwin 	printf("\tFlags={");
588a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
589a0333ad1SJohn Baldwin 		printf("ENABLED");
590a0333ad1SJohn Baldwin 	else
591a0333ad1SJohn Baldwin 		printf("DISABLED");
592a0333ad1SJohn Baldwin 	printf("}\n");
593a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
594a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
595a0333ad1SJohn Baldwin }
596a0333ad1SJohn Baldwin 
597c031c93bSTakanori Watanabe static char *
598c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
599c031c93bSTakanori Watanabe {
600c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
601c031c93bSTakanori Watanabe 	char *eventname = NULL;
602c031c93bSTakanori Watanabe 
603c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
604c031c93bSTakanori Watanabe 
605c031c93bSTakanori Watanabe 	switch(event->event_type) {
606c031c93bSTakanori Watanabe 	case PREBOOT:
607c031c93bSTakanori Watanabe 	case POST_CODE:
608c031c93bSTakanori Watanabe 	case UNUSED:
609c031c93bSTakanori Watanabe 	case NO_ACTION:
610c031c93bSTakanori Watanabe 	case SEPARATOR:
611c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
612c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
613c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
614c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
615c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
616c031c93bSTakanori Watanabe 	case COMPACT_HASH:
617c031c93bSTakanori Watanabe 	case IPL:
618c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
619c031c93bSTakanori Watanabe 	case NONHOST_CODE:
620c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
621c031c93bSTakanori Watanabe 	case NONHOST_INFO:
622c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
623c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
624c031c93bSTakanori Watanabe 		break;
625c031c93bSTakanori Watanabe 
626c031c93bSTakanori Watanabe 	case ACTION:
627c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
628c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
629c031c93bSTakanori Watanabe 		break;
630c031c93bSTakanori Watanabe 
631c031c93bSTakanori Watanabe 	case EVENT_TAG:
632c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
633c031c93bSTakanori Watanabe 		case SMBIOS:
634c031c93bSTakanori Watanabe 		case BIS_CERT:
635c031c93bSTakanori Watanabe 		case CMOS:
636c031c93bSTakanori Watanabe 		case NVRAM:
637c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
638c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
639c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
640c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
641c031c93bSTakanori Watanabe 		case ESCD:
642c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
643c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
644c031c93bSTakanori Watanabe 		case POST_CONTENTS:
645c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
646c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
647c031c93bSTakanori Watanabe 			break;
648c031c93bSTakanori Watanabe 
649c031c93bSTakanori Watanabe 		default:
650c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
651c031c93bSTakanori Watanabe 			    pc_event->event_id);
652c031c93bSTakanori Watanabe 			break;
653c031c93bSTakanori Watanabe 		}
654c031c93bSTakanori Watanabe 		break;
655c031c93bSTakanori Watanabe 
656c031c93bSTakanori Watanabe 	default:
657c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
658c031c93bSTakanori Watanabe 		break;
659c031c93bSTakanori Watanabe 	}
660c031c93bSTakanori Watanabe 
661c031c93bSTakanori Watanabe 	return eventname;
662c031c93bSTakanori Watanabe }
663c031c93bSTakanori Watanabe 
664c031c93bSTakanori Watanabe static void
665c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
666c031c93bSTakanori Watanabe {
667c031c93bSTakanori Watanabe 	int i;
668c031c93bSTakanori Watanabe 	char *eventname;
669c031c93bSTakanori Watanabe 
670c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
671c031c93bSTakanori Watanabe 
672c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
673c031c93bSTakanori Watanabe 	printf(" 0x");
674c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
675c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
676c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
677c031c93bSTakanori Watanabe 
678c031c93bSTakanori Watanabe 	free(eventname);
679c031c93bSTakanori Watanabe }
680c031c93bSTakanori Watanabe 
681c031c93bSTakanori Watanabe static void
682c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
683c031c93bSTakanori Watanabe {
684c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
685c031c93bSTakanori Watanabe 	struct TCPAevent *event;
686977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
687c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
688c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
689c031c93bSTakanori Watanabe 
690c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
691c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
692c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
693c031c93bSTakanori Watanabe 
694c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
695c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
696c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
697c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
698c031c93bSTakanori Watanabe 		break;
699c031c93bSTakanori Watanabe 
700c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
701c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
702c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
703c031c93bSTakanori Watanabe 		break;
704c031c93bSTakanori Watanabe 
705c031c93bSTakanori Watanabe 	default:
706c031c93bSTakanori Watanabe 		printf("XXX");
707c031c93bSTakanori Watanabe 		printf(END_COMMENT);
708c031c93bSTakanori Watanabe 		return;
709c031c93bSTakanori Watanabe 	}
7100e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
711c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
712c031c93bSTakanori Watanabe 
713c031c93bSTakanori Watanabe 	if (len == 0) {
714c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
715c031c93bSTakanori Watanabe 		printf(END_COMMENT);
716c031c93bSTakanori Watanabe 		return;
717c031c93bSTakanori Watanabe 	}
7182ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
7192ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
7202ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
7212ef23c6dSTakanori Watanabe 		return;
7222ef23c6dSTakanori Watanabe 	}
723c031c93bSTakanori Watanabe 
724c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
725c031c93bSTakanori Watanabe 	vend = vaddr + len;
726c031c93bSTakanori Watanabe 
727c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
7282ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
7292ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
730c031c93bSTakanori Watanabe 			break;
7310e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
732c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
733c031c93bSTakanori Watanabe 			break;
7342ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
7352ef23c6dSTakanori Watanabe 			break;
736c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
737c031c93bSTakanori Watanabe 			break;
738c031c93bSTakanori Watanabe #if 0
739c031c93bSTakanori Watanabe 		{
740c031c93bSTakanori Watanabe 		unsigned int i, j, k;
741c031c93bSTakanori Watanabe 
742c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
743c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
744c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
745c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
746c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
747c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
748c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
749c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
750c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
751c031c93bSTakanori Watanabe 				j = i + 1;
752c031c93bSTakanori Watanabe 			}
753c031c93bSTakanori Watanabe 		}
754c031c93bSTakanori Watanabe 		printf("\n"); }
755c031c93bSTakanori Watanabe #endif
756c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
757c031c93bSTakanori Watanabe 
758c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
759c031c93bSTakanori Watanabe 	}
760c031c93bSTakanori Watanabe 
761c031c93bSTakanori Watanabe 	printf(END_COMMENT);
762c031c93bSTakanori Watanabe }
763c031c93bSTakanori Watanabe 
764ec650989SNeel Natu static const char *
765ec650989SNeel Natu devscope_type2str(int type)
766ec650989SNeel Natu {
767ec650989SNeel Natu 	static char typebuf[16];
768ec650989SNeel Natu 
769ec650989SNeel Natu 	switch (type) {
770ec650989SNeel Natu 	case 1:
771ec650989SNeel Natu 		return ("PCI Endpoint Device");
772ec650989SNeel Natu 	case 2:
773ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
774ec650989SNeel Natu 	case 3:
775ec650989SNeel Natu 		return ("IOAPIC");
776ec650989SNeel Natu 	case 4:
777ec650989SNeel Natu 		return ("HPET");
778ec650989SNeel Natu 	default:
779ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
780ec650989SNeel Natu 		return (typebuf);
781ec650989SNeel Natu 	}
782ec650989SNeel Natu }
783ec650989SNeel Natu 
784ec650989SNeel Natu static int
785ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
786ec650989SNeel Natu {
787ec650989SNeel Natu 	char sep;
788ec650989SNeel Natu 	int pathlen;
789ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
790ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
791ec650989SNeel Natu 
792ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
793ec650989SNeel Natu 		return (-1);
794ec650989SNeel Natu 
795ec650989SNeel Natu 	if (remaining < devscope->Length)
796ec650989SNeel Natu 		return (-1);
797ec650989SNeel Natu 
798ec650989SNeel Natu 	printf("\n");
799ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
800ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
801ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
802ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
803ec650989SNeel Natu 
804ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
805ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
806ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
807ec650989SNeel Natu 	if (path < pathend) {
808ec650989SNeel Natu 		sep = '{';
809ec650989SNeel Natu 		printf("\t\tPath=");
810ec650989SNeel Natu 		do {
811ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
812ec650989SNeel Natu 			sep=',';
813ec650989SNeel Natu 			path++;
814ec650989SNeel Natu 		} while (path < pathend);
815ec650989SNeel Natu 		printf("}\n");
816ec650989SNeel Natu 	}
817ec650989SNeel Natu 
818ec650989SNeel Natu 	return (devscope->Length);
819ec650989SNeel Natu }
820ec650989SNeel Natu 
821ec650989SNeel Natu static void
822ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
823ec650989SNeel Natu {
824ec650989SNeel Natu 	char *cp;
825ec650989SNeel Natu 	int remaining, consumed;
826ec650989SNeel Natu 
827ec650989SNeel Natu 	printf("\n");
828ec650989SNeel Natu 	printf("\tType=DRHD\n");
829ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
830ec650989SNeel Natu 
831ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
832ec650989SNeel Natu 
833ec650989SNeel Natu 	printf("\tFlags=");
834ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
835ec650989SNeel Natu 	PRINTFLAG_END();
836ec650989SNeel Natu 
837ec650989SNeel Natu #undef PRINTFLAG
838ec650989SNeel Natu 
839ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
840*7d369c6eSJung-uk Kim 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
841ec650989SNeel Natu 
842ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
843ec650989SNeel Natu 	if (remaining > 0)
844ec650989SNeel Natu 		printf("\tDevice Scope:");
845ec650989SNeel Natu 	while (remaining > 0) {
846ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
847ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
848ec650989SNeel Natu 		if (consumed <= 0)
849ec650989SNeel Natu 			break;
850ec650989SNeel Natu 		else
851ec650989SNeel Natu 			remaining -= consumed;
852ec650989SNeel Natu 	}
853ec650989SNeel Natu }
854ec650989SNeel Natu 
855ec650989SNeel Natu static void
856ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
857ec650989SNeel Natu {
858ec650989SNeel Natu 	char *cp;
859ec650989SNeel Natu 	int remaining, consumed;
860ec650989SNeel Natu 
861ec650989SNeel Natu 	printf("\n");
862ec650989SNeel Natu 	printf("\tType=RMRR\n");
863ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
864ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
865*7d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
866*7d369c6eSJung-uk Kim 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
867ec650989SNeel Natu 
868ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
869ec650989SNeel Natu 	if (remaining > 0)
870ec650989SNeel Natu 		printf("\tDevice Scope:");
871ec650989SNeel Natu 	while (remaining > 0) {
872ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
873ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
874ec650989SNeel Natu 		if (consumed <= 0)
875ec650989SNeel Natu 			break;
876ec650989SNeel Natu 		else
877ec650989SNeel Natu 			remaining -= consumed;
878ec650989SNeel Natu 	}
879ec650989SNeel Natu }
880ec650989SNeel Natu 
881ec650989SNeel Natu static void
882ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
883ec650989SNeel Natu {
884ec650989SNeel Natu 	char *cp;
885ec650989SNeel Natu 	int remaining, consumed;
886ec650989SNeel Natu 
887ec650989SNeel Natu 	printf("\n");
888ec650989SNeel Natu 	printf("\tType=ATSR\n");
889ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
890ec650989SNeel Natu 
891ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
892ec650989SNeel Natu 
893ec650989SNeel Natu 	printf("\tFlags=");
894ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
895ec650989SNeel Natu 	PRINTFLAG_END();
896ec650989SNeel Natu 
897ec650989SNeel Natu #undef PRINTFLAG
898ec650989SNeel Natu 
899ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
900ec650989SNeel Natu 
901ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
902ec650989SNeel Natu 	if (remaining > 0)
903ec650989SNeel Natu 		printf("\tDevice Scope:");
904ec650989SNeel Natu 	while (remaining > 0) {
905ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
906ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
907ec650989SNeel Natu 		if (consumed <= 0)
908ec650989SNeel Natu 			break;
909ec650989SNeel Natu 		else
910ec650989SNeel Natu 			remaining -= consumed;
911ec650989SNeel Natu 	}
912ec650989SNeel Natu }
913ec650989SNeel Natu 
914ec650989SNeel Natu static void
915ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
916ec650989SNeel Natu {
917ec650989SNeel Natu 
918ec650989SNeel Natu 	printf("\n");
919ec650989SNeel Natu 	printf("\tType=RHSA\n");
920ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
921*7d369c6eSJung-uk Kim 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
922ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
923ec650989SNeel Natu }
924ec650989SNeel Natu 
925ec650989SNeel Natu static int
926ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
927ec650989SNeel Natu {
928ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
929ec650989SNeel Natu 
930ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
931ec650989SNeel Natu 		return (-1);
932ec650989SNeel Natu 
933ec650989SNeel Natu 	if (remaining < hdr->Length)
934ec650989SNeel Natu 		return (-1);
935ec650989SNeel Natu 
936ec650989SNeel Natu 	switch (hdr->Type) {
937ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
938ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
939ec650989SNeel Natu 		break;
940ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
941ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
942ec650989SNeel Natu 		break;
943313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_ROOT_ATS:
944ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
945ec650989SNeel Natu 		break;
946313a0c13SJung-uk Kim 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
947ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
948ec650989SNeel Natu 		break;
949ec650989SNeel Natu 	default:
950ec650989SNeel Natu 		printf("\n");
951ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
952ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
953ec650989SNeel Natu 		break;
954ec650989SNeel Natu 	}
955ec650989SNeel Natu 	return (hdr->Length);
956ec650989SNeel Natu }
957ec650989SNeel Natu 
958ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
959ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
960ec650989SNeel Natu #endif
961ec650989SNeel Natu 
962ec650989SNeel Natu static void
963ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
964ec650989SNeel Natu {
965ec650989SNeel Natu 	char *cp;
966ec650989SNeel Natu 	int remaining, consumed;
967ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
968ec650989SNeel Natu 
969ec650989SNeel Natu 	printf(BEGIN_COMMENT);
970ec650989SNeel Natu 	acpi_print_sdt(sdp);
971ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
972ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
973ec650989SNeel Natu 
974ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
975ec650989SNeel Natu 
976ec650989SNeel Natu 	printf("\tFlags=");
977ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
978ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
979ec650989SNeel Natu 	PRINTFLAG_END();
980ec650989SNeel Natu 
981ec650989SNeel Natu #undef PRINTFLAG
982ec650989SNeel Natu 
983ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
984ec650989SNeel Natu 	while (remaining > 0) {
985ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
986ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
987ec650989SNeel Natu 		if (consumed <= 0)
988ec650989SNeel Natu 			break;
989ec650989SNeel Natu 		else
990ec650989SNeel Natu 			remaining -= consumed;
991ec650989SNeel Natu 	}
992ec650989SNeel Natu 
993ec650989SNeel Natu 	printf(END_COMMENT);
994ec650989SNeel Natu }
995ec650989SNeel Natu 
996a0333ad1SJohn Baldwin static void
997986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
998a0333ad1SJohn Baldwin {
999a0333ad1SJohn Baldwin 
1000a0333ad1SJohn Baldwin 	printf("\tFlags={");
1001986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1002a0333ad1SJohn Baldwin 		printf("ENABLED");
1003a0333ad1SJohn Baldwin 	else
1004a0333ad1SJohn Baldwin 		printf("DISABLED");
1005986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1006a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1007986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1008a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1009a0333ad1SJohn Baldwin 	printf("}\n");
1010986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1011986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1012986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1013a0333ad1SJohn Baldwin }
1014a0333ad1SJohn Baldwin 
1015bf70beceSEd Schouten static const char *srat_types[] = { "CPU", "Memory", "X2APIC" };
1016a0333ad1SJohn Baldwin 
1017a0333ad1SJohn Baldwin static void
1018986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1019a0333ad1SJohn Baldwin {
1020986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1021986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
1022a0333ad1SJohn Baldwin 
1023986dffafSJohn Baldwin 	if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0]))
1024986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1025a0333ad1SJohn Baldwin 	else
1026986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1027986dffafSJohn Baldwin 	switch (srat->Type) {
1028a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1029986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1030986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1031986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1032986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1033986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1034986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1035a0333ad1SJohn Baldwin 		break;
1036a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1037986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1038a0333ad1SJohn Baldwin 		break;
1039a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1040986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1041986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1042986dffafSJohn Baldwin 		    x2apic->Flags);
1043a0333ad1SJohn Baldwin 		break;
1044a0333ad1SJohn Baldwin 	}
1045a0333ad1SJohn Baldwin }
1046a0333ad1SJohn Baldwin 
1047a0333ad1SJohn Baldwin static void
1048986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1049a0333ad1SJohn Baldwin {
1050986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1051a0333ad1SJohn Baldwin 
1052a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1053a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1054986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1055986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1056986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1057a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1058a0333ad1SJohn Baldwin }
1059a0333ad1SJohn Baldwin 
1060a0333ad1SJohn Baldwin static void
1061986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1062c62f1cccSMitsuru IWASAKI {
1063773b6454SNate Lawson 	printf("  ");
1064986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
1065c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1066986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1067e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1068986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1069e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1070986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1071986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1072e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1073986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
1074986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1075e1e9a4bfSMitsuru IWASAKI }
1076e1e9a4bfSMitsuru IWASAKI 
1077945137d9SNate Lawson static void
1078986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1079e1e9a4bfSMitsuru IWASAKI {
1080986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1081986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1082e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1083e1e9a4bfSMitsuru IWASAKI 
1084986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1085986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1086773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1087773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1088986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1089e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1090e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1091e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1092e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1093fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1094*7d369c6eSJung-uk Kim 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1095fe1d0c2dSJung-uk Kim 		else
1096*7d369c6eSJung-uk Kim 			printf("0x%016jx",
1097*7d369c6eSJung-uk Kim 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1098e1e9a4bfSMitsuru IWASAKI 	}
1099e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1100c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1101e1e9a4bfSMitsuru IWASAKI }
1102e1e9a4bfSMitsuru IWASAKI 
11038e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
11048e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
11058e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
11068e6a8737SNate Lawson };
11078e6a8737SNate Lawson 
1108945137d9SNate Lawson static void
1109986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1110e1e9a4bfSMitsuru IWASAKI {
1111986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
11128e6a8737SNate Lawson 	const char *pm;
1113e1e9a4bfSMitsuru IWASAKI 
1114986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1115c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
11162177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1117986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1118986dffafSJohn Baldwin 	       fadt->Dsdt);
1119986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1120986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
11218e6a8737SNate Lawson 		pm = "Reserved";
11228e6a8737SNate Lawson 	else
1123986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1124986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1125986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1126986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1127986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1128986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1129986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1130986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1131e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1132986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1133986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1134986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1135e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1136986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1137986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1138e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1139986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1140986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1141986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1142e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1143986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1144986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1145986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1146e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1147986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1148986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1149c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1150986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1151986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1152986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
11538e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1154986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1155986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1156986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
11578e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1158986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1159986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1160986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1161986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1162986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
116351c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1164986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1165e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1166986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1167e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1168986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1169e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1170986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1171e1e9a4bfSMitsuru IWASAKI 
1172ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1173e1e9a4bfSMitsuru IWASAKI 
11748e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1175986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1176986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1177986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1178986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1179986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1180ec650989SNeel Natu 	PRINTFLAG_END();
11818e6a8737SNate Lawson 
11828e6a8737SNate Lawson 	printf("\tFlags=");
1183986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1184986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1185986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1186986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1187986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1188986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1189986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1190986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1191986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1192986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1193986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1194986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1195986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1196986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1197986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1198986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1199986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1200986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1201986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1202986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1203ec650989SNeel Natu 	PRINTFLAG_END();
1204e1e9a4bfSMitsuru IWASAKI 
1205e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1206e1e9a4bfSMitsuru IWASAKI 
1207986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
12088e6a8737SNate Lawson 		printf("\tRESET_REG=");
1209986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1210986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
12118e6a8737SNate Lawson 	}
1212c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
1213*7d369c6eSJung-uk Kim 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
1214*7d369c6eSJung-uk Kim 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1215c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1216986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1217986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1218c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1219986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1220c08c4e81SNate Lawson 		}
1221c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1222986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1223986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1224c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1225986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1226c08c4e81SNate Lawson 		}
1227986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1228773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1229986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1230c08c4e81SNate Lawson 		}
1231773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1232986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1233986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1234773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1235986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1236c08c4e81SNate Lawson 		}
1237986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1238773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1239986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1240c08c4e81SNate Lawson 		}
1241773b6454SNate Lawson 		printf("\n");
1242773b6454SNate Lawson 	}
12438e6a8737SNate Lawson 
12448e6a8737SNate Lawson 	printf(END_COMMENT);
12458e6a8737SNate Lawson }
12468e6a8737SNate Lawson 
12478e6a8737SNate Lawson static void
1248986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
12498e6a8737SNate Lawson {
12508e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1251986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1252986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1253986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
12548e6a8737SNate Lawson 
1255773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1256986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1257986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
12588e6a8737SNate Lawson 			printf("PENDING,");
1259986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
12608e6a8737SNate Lawson 			printf("OWNED");
12618e6a8737SNate Lawson 	}
1262773b6454SNate Lawson 	printf("\n");
12638e6a8737SNate Lawson 
1264773b6454SNate Lawson 	printf("\tFlags=");
1265986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
12668e6a8737SNate Lawson 		printf("S4BIOS");
1267773b6454SNate Lawson 	printf("\n");
12688e6a8737SNate Lawson 
1269*7d369c6eSJung-uk Kim 	if (facs->XFirmwareWakingVector != 0)
1270*7d369c6eSJung-uk Kim 		printf("\tX_Firm_Wake_Vec=%016jx\n",
1271*7d369c6eSJung-uk Kim 		    (uintmax_t)facs->XFirmwareWakingVector);
1272986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
12738e6a8737SNate Lawson 
1274c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1275e1e9a4bfSMitsuru IWASAKI }
1276e1e9a4bfSMitsuru IWASAKI 
1277945137d9SNate Lawson static void
1278986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1279e1e9a4bfSMitsuru IWASAKI {
1280773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1281773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1282773b6454SNate Lawson 	printf(END_COMMENT);
1283e1e9a4bfSMitsuru IWASAKI }
1284e1e9a4bfSMitsuru IWASAKI 
1285e1e9a4bfSMitsuru IWASAKI int
1286e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1287e1e9a4bfSMitsuru IWASAKI {
1288986dffafSJohn Baldwin 	uint8_t *bp;
1289986dffafSJohn Baldwin 	uint8_t sum;
1290e1e9a4bfSMitsuru IWASAKI 
1291e1e9a4bfSMitsuru IWASAKI 	bp = p;
1292e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1293e1e9a4bfSMitsuru IWASAKI 	while (length--)
1294e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1295e1e9a4bfSMitsuru IWASAKI 
1296e1e9a4bfSMitsuru IWASAKI 	return (sum);
1297e1e9a4bfSMitsuru IWASAKI }
1298e1e9a4bfSMitsuru IWASAKI 
1299986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1300e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1301e1e9a4bfSMitsuru IWASAKI {
1302986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1303e1e9a4bfSMitsuru IWASAKI 
1304986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1305986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1306e1e9a4bfSMitsuru IWASAKI 	return (sp);
1307e1e9a4bfSMitsuru IWASAKI }
1308e1e9a4bfSMitsuru IWASAKI 
1309945137d9SNate Lawson static void
1310986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1311e1e9a4bfSMitsuru IWASAKI {
1312c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1313a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1314986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1315986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1316986dffafSJohn Baldwin 	       rp->Revision);
1317986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1318986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1319986dffafSJohn Baldwin 		    rp->Checksum);
1320a74172abSNate Lawson 	} else {
1321*7d369c6eSJung-uk Kim 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
1322*7d369c6eSJung-uk Kim 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
1323986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1324a74172abSNate Lawson 	}
1325c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1326e1e9a4bfSMitsuru IWASAKI }
1327e1e9a4bfSMitsuru IWASAKI 
1328945137d9SNate Lawson static void
1329986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1330e1e9a4bfSMitsuru IWASAKI {
1331986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1332986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1333986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1334a74172abSNate Lawson 	vm_offset_t addr;
1335a74172abSNate Lawson 	int entries, i;
1336e1e9a4bfSMitsuru IWASAKI 
1337e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1338986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1339986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1340986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1341e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1342fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1343986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1344fe1d0c2dSJung-uk Kim 		else
1345986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1346fe1d0c2dSJung-uk Kim 		if (addr == 0)
1347fe1d0c2dSJung-uk Kim 			continue;
1348986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1349986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
13505cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1351986dffafSJohn Baldwin 			    sdp->Signature);
13525cf6d493SNate Lawson 			continue;
13535cf6d493SNate Lawson 		}
1354986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
13552177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1356986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1357986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1358986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
135979d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1360986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
136155d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1362986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1363a47e681bSScott Long 			acpi_handle_mcfg(sdp);
136433866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
136533866658SJohn Baldwin 			acpi_handle_slit(sdp);
1366986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1367a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1368c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1369c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1370ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1371ec650989SNeel Natu 			acpi_handle_dmar(sdp);
1372773b6454SNate Lawson 		else {
1373773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1374773b6454SNate Lawson 			acpi_print_sdt(sdp);
1375773b6454SNate Lawson 			printf(END_COMMENT);
1376773b6454SNate Lawson 		}
1377e1e9a4bfSMitsuru IWASAKI 	}
1378e1e9a4bfSMitsuru IWASAKI }
1379c62f1cccSMitsuru IWASAKI 
1380986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1381476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1382945137d9SNate Lawson {
1383986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1384986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1385945137d9SNate Lawson 
1386945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1387945137d9SNate Lawson 	if (!rp)
1388945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1389945137d9SNate Lawson 
1390945137d9SNate Lawson 	if (tflag)
1391945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1392986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1393986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1394986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1395986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1396945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1397a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1398a74172abSNate Lawson 	} else {
1399986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1400986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1401986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1402a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1403a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1404a74172abSNate Lawson 	}
1405945137d9SNate Lawson 	return (rsdp);
1406945137d9SNate Lawson }
1407c62f1cccSMitsuru IWASAKI 
140862c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1409bfa3f012SMarcel Moolenaar static int
1410986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1411bfa3f012SMarcel Moolenaar {
1412986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1413986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1414bfa3f012SMarcel Moolenaar 	uint8_t sum;
1415bfa3f012SMarcel Moolenaar 
141662c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1417bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1418bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1419986dffafSJohn Baldwin 		sdt.Checksum = 0;
1420986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1421986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1422986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1423f7675a56SNate Lawson 		while (ssdt != NULL) {
1424986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1425986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1426986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1427986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1428bfa3f012SMarcel Moolenaar 		}
1429986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1430986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1431bfa3f012SMarcel Moolenaar 	}
143262c7bde1SNate Lawson 
143362c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1434986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1435986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
143662c7bde1SNate Lawson 
1437b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1438f7675a56SNate Lawson 	if (rsdt != NULL) {
1439bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1440bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1441986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1442986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1443bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1444bfa3f012SMarcel Moolenaar 		}
1445bfa3f012SMarcel Moolenaar 	}
1446bfa3f012SMarcel Moolenaar 	return (0);
1447bfa3f012SMarcel Moolenaar }
1448bfa3f012SMarcel Moolenaar 
1449c62f1cccSMitsuru IWASAKI void
1450986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1451c62f1cccSMitsuru IWASAKI {
1452945137d9SNate Lawson 	int	fd;
1453945137d9SNate Lawson 	mode_t	mode;
1454945137d9SNate Lawson 
1455945137d9SNate Lawson 	assert(outfile != NULL);
1456945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1457945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1458945137d9SNate Lawson 	if (fd == -1) {
1459945137d9SNate Lawson 		perror("dsdt_save_file");
1460945137d9SNate Lawson 		return;
1461945137d9SNate Lawson 	}
1462bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1463945137d9SNate Lawson 	close(fd);
1464c62f1cccSMitsuru IWASAKI }
1465c62f1cccSMitsuru IWASAKI 
1466945137d9SNate Lawson void
1467986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1468c62f1cccSMitsuru IWASAKI {
146999065116SJung-uk Kim 	char buf[PATH_MAX], tmpstr[PATH_MAX];
147099065116SJung-uk Kim 	const char *tmpdir;
147199065116SJung-uk Kim 	char *tmpext;
1472945137d9SNate Lawson 	FILE *fp;
147399065116SJung-uk Kim 	size_t len;
147499065116SJung-uk Kim 	int fd;
1475945137d9SNate Lawson 
147699065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
147799065116SJung-uk Kim 	if (tmpdir == NULL)
147899065116SJung-uk Kim 		tmpdir = _PATH_TMP;
147999065116SJung-uk Kim 	strncpy(tmpstr, tmpdir, sizeof(tmpstr));
148099065116SJung-uk Kim 	if (realpath(tmpstr, buf) == NULL) {
1481d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
148299065116SJung-uk Kim 		return;
148399065116SJung-uk Kim 	}
148499065116SJung-uk Kim 	strncpy(tmpstr, buf, sizeof(tmpstr));
1485d6a6e590SJung-uk Kim 	strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(buf));
1486d6a6e590SJung-uk Kim 	len = strlen(tmpstr);
148799065116SJung-uk Kim 	tmpext = tmpstr + len;
148899065116SJung-uk Kim 	strncpy(tmpext, "XXXXXX", sizeof(tmpstr) - len);
1489945137d9SNate Lawson 	fd = mkstemp(tmpstr);
1490945137d9SNate Lawson 	if (fd < 0) {
1491945137d9SNate Lawson 		perror("iasl tmp file");
1492945137d9SNate Lawson 		return;
1493c62f1cccSMitsuru IWASAKI 	}
1494bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1495945137d9SNate Lawson 	close(fd);
1496945137d9SNate Lawson 
1497945137d9SNate Lawson 	/* Run iasl -d on the temp file */
1498945137d9SNate Lawson 	if (fork() == 0) {
1499945137d9SNate Lawson 		close(STDOUT_FILENO);
1500945137d9SNate Lawson 		if (vflag == 0)
1501945137d9SNate Lawson 			close(STDERR_FILENO);
150299065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1503945137d9SNate Lawson 		err(1, "exec");
1504c62f1cccSMitsuru IWASAKI 	}
1505c62f1cccSMitsuru IWASAKI 
1506945137d9SNate Lawson 	wait(NULL);
1507945137d9SNate Lawson 	unlink(tmpstr);
1508945137d9SNate Lawson 
1509945137d9SNate Lawson 	/* Dump iasl's output to stdout */
151099065116SJung-uk Kim 	strncpy(tmpext, "dsl", sizeof(tmpstr) - len);
151199065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
151299065116SJung-uk Kim 	unlink(tmpstr);
1513945137d9SNate Lawson 	if (fp == NULL) {
1514945137d9SNate Lawson 		perror("iasl tmp file (read)");
1515945137d9SNate Lawson 		return;
1516945137d9SNate Lawson 	}
1517945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1518945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1519945137d9SNate Lawson 	fclose(fp);
1520c62f1cccSMitsuru IWASAKI }
1521c62f1cccSMitsuru IWASAKI 
1522945137d9SNate Lawson void
1523986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1524c62f1cccSMitsuru IWASAKI {
1525945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1526c62f1cccSMitsuru IWASAKI }
1527c62f1cccSMitsuru IWASAKI 
1528bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1529986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1530986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1531c62f1cccSMitsuru IWASAKI {
1532986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1533986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1534986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1535a74172abSNate Lawson 	vm_offset_t addr;
1536a74172abSNate Lawson 	int entries, i;
1537945137d9SNate Lawson 
1538986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1539986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1540986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1541945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1542fe1d0c2dSJung-uk Kim 		if (addr_size == 4)
1543986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1544fe1d0c2dSJung-uk Kim 		else
1545986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1546fe1d0c2dSJung-uk Kim 		if (addr == 0)
1547fe1d0c2dSJung-uk Kim 			continue;
1548986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1549bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1550bfa3f012SMarcel Moolenaar 			if (sdt == last)
1551bfa3f012SMarcel Moolenaar 				last = NULL;
1552bfa3f012SMarcel Moolenaar 			continue;
1553bfa3f012SMarcel Moolenaar 		}
1554986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1555a74172abSNate Lawson 			continue;
1556986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1557945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1558945137d9SNate Lawson 		return (sdt);
1559c62f1cccSMitsuru IWASAKI 	}
1560c62f1cccSMitsuru IWASAKI 
1561945137d9SNate Lawson 	return (NULL);
1562c62f1cccSMitsuru IWASAKI }
1563c62f1cccSMitsuru IWASAKI 
1564986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1565986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1566c62f1cccSMitsuru IWASAKI {
1567986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1568c62f1cccSMitsuru IWASAKI 
1569986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1570c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1571986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
15722e71eb12SNate Lawson 	else
1573986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1574986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1575945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1576945137d9SNate Lawson 	return (sdt);
1577c62f1cccSMitsuru IWASAKI }
1578