xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision ec6509897a60f1ee51f96239f376dba968a2e8d4)
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 
126*ec650989SNeel Natu #define	PRINTFLAG_END()		printflag_end()
127*ec650989SNeel Natu 
128*ec650989SNeel Natu static char pf_sep = '{';
129*ec650989SNeel Natu 
130*ec650989SNeel Natu static void
131*ec650989SNeel Natu printflag_end(void)
132*ec650989SNeel Natu {
133*ec650989SNeel Natu 
134*ec650989SNeel Natu 	if (pf_sep != '{') {
135*ec650989SNeel Natu 		printf("}");
136*ec650989SNeel Natu 		pf_sep = '{';
137*ec650989SNeel Natu 	}
138*ec650989SNeel Natu 	printf("\n");
139*ec650989SNeel Natu }
140*ec650989SNeel Natu 
141*ec650989SNeel Natu static void
142*ec650989SNeel Natu printflag(uint64_t var, uint64_t mask, const char *name)
143*ec650989SNeel Natu {
144*ec650989SNeel Natu 
145*ec650989SNeel Natu 	if (var & mask) {
146*ec650989SNeel Natu 		printf("%c%s", pf_sep, name);
147*ec650989SNeel Natu 		pf_sep = ',';
148*ec650989SNeel Natu 	}
149*ec650989SNeel Natu }
150*ec650989SNeel 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:
171986dffafSJohn Baldwin 		printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->Address,
172986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1738e6a8737SNate Lawson 		break;
1748e6a8737SNate Lawson 	case ACPI_GAS_IO:
175986dffafSJohn Baldwin 		printf("0x%02lx:%u[%u] (IO)", (u_long)gas->Address,
176986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1778e6a8737SNate Lawson 		break;
1788e6a8737SNate Lawson 	case ACPI_GAS_PCI:
179986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
180986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
181986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1828e6a8737SNate Lawson 		break;
1838e6a8737SNate Lawson 	/* XXX How to handle these below? */
1848e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
185986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
186986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1878e6a8737SNate Lawson 		break;
1888e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
189986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
190986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1918e6a8737SNate Lawson 		break;
192986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
193986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
194986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
1958e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
1968e6a8737SNate Lawson 	default:
197986dffafSJohn Baldwin 		printf("0x%08lx (?)", (u_long)gas->Address);
1988e6a8737SNate Lawson 		break;
1998e6a8737SNate Lawson 	}
2008e6a8737SNate Lawson }
2018e6a8737SNate Lawson 
202c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
203c2962974SNate Lawson static int
204986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
205e1e9a4bfSMitsuru IWASAKI {
206c2962974SNate Lawson 	int fadt_revision;
207e1e9a4bfSMitsuru IWASAKI 
208c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
209c83f0f99SNate Lawson 	if (addr_size == 8) {
210c83f0f99SNate Lawson 		fadt_revision = 2;
2118e6a8737SNate Lawson 
212773b6454SNate Lawson 		/*
213c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
214c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
215c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
216c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
217c83f0f99SNate Lawson 		 * version for all subsequent tables.
218773b6454SNate Lawson 		 */
219986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
220986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
221c83f0f99SNate Lawson 			fadt_revision = 1;
222c2962974SNate Lawson 	} else
223c83f0f99SNate Lawson 		fadt_revision = 1;
224c2962974SNate Lawson 	return (fadt_revision);
225c83f0f99SNate Lawson }
226c2962974SNate Lawson 
227c2962974SNate Lawson static void
228986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
229c2962974SNate Lawson {
230986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
231986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
232986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
233c2962974SNate Lawson 	int		fadt_revision;
234c2962974SNate Lawson 
235986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2362177d4e6SNate Lawson 	acpi_print_fadt(sdp);
237c83f0f99SNate Lawson 
238c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
239c83f0f99SNate Lawson 	if (fadt_revision == 1)
240986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
241773b6454SNate Lawson 	else
242986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
243986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2448e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2458e6a8737SNate Lawson 	acpi_print_facs(facs);
2468e6a8737SNate Lawson 
247c83f0f99SNate Lawson 	if (fadt_revision == 1)
248986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
249773b6454SNate Lawson 	else
250986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
251986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
252945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
253945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
254c62f1cccSMitsuru IWASAKI }
255c62f1cccSMitsuru IWASAKI 
256c62f1cccSMitsuru IWASAKI static void
257986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
258986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
259986dffafSJohn Baldwin {
260986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
261986dffafSJohn Baldwin 	char *end;
262986dffafSJohn Baldwin 
263986dffafSJohn Baldwin 	subtable = first;
264986dffafSJohn Baldwin 	end = (char *)table + table->Length;
265986dffafSJohn Baldwin 	while ((char *)subtable < end) {
266986dffafSJohn Baldwin 		printf("\n");
267986dffafSJohn Baldwin 		action(subtable);
268986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
269986dffafSJohn Baldwin 		    subtable->Length);
270986dffafSJohn Baldwin 	}
271986dffafSJohn Baldwin }
272986dffafSJohn Baldwin 
273986dffafSJohn Baldwin static void
2740a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
2750a473124SJohn Baldwin {
2760a473124SJohn Baldwin 
2770a473124SJohn Baldwin 	printf("\tACPI CPU=");
2780a473124SJohn Baldwin 	if (cpu_id == 0xff)
2790a473124SJohn Baldwin 		printf("ALL\n");
2800a473124SJohn Baldwin 	else
2810a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
2820a473124SJohn Baldwin }
2830a473124SJohn Baldwin 
2840a473124SJohn Baldwin static void
285986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
2860a473124SJohn Baldwin {
287986dffafSJohn Baldwin 
288986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
289986dffafSJohn Baldwin 	if (uid_string != NULL)
290986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
291986dffafSJohn Baldwin 	printf("\n");
292986dffafSJohn Baldwin }
293986dffafSJohn Baldwin 
294986dffafSJohn Baldwin static void
295986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
296986dffafSJohn Baldwin {
297986dffafSJohn Baldwin 
2980a473124SJohn Baldwin 	printf("\tFlags={");
299986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
3000a473124SJohn Baldwin 		printf("ENABLED");
3010a473124SJohn Baldwin 	else
3020a473124SJohn Baldwin 		printf("DISABLED");
3030a473124SJohn Baldwin 	printf("}\n");
304986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3050a473124SJohn Baldwin }
3060a473124SJohn Baldwin 
3070a473124SJohn Baldwin static void
308986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
3090a473124SJohn Baldwin {
310986dffafSJohn Baldwin 
311986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
3120a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
313986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
3140a473124SJohn Baldwin }
3150a473124SJohn Baldwin 
3160a473124SJohn Baldwin static void
317986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
3180a473124SJohn Baldwin {
3190a473124SJohn Baldwin 
3200a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
321986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
322986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
3230a473124SJohn Baldwin 		printf("conforming");
3240a473124SJohn Baldwin 		break;
325986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3260a473124SJohn Baldwin 		printf("active-hi");
3270a473124SJohn Baldwin 		break;
328986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3290a473124SJohn Baldwin 		printf("active-lo");
3300a473124SJohn Baldwin 		break;
3310a473124SJohn Baldwin 	default:
332986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3330a473124SJohn Baldwin 		break;
3340a473124SJohn Baldwin 	}
3350a473124SJohn Baldwin 	printf(", Trigger=");
336986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
337986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3380a473124SJohn Baldwin 		printf("conforming");
3390a473124SJohn Baldwin 		break;
340986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3410a473124SJohn Baldwin 		printf("edge");
3420a473124SJohn Baldwin 		break;
343986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3440a473124SJohn Baldwin 		printf("level");
3450a473124SJohn Baldwin 		break;
3460a473124SJohn Baldwin 	default:
347986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3480a473124SJohn Baldwin 	}
3490a473124SJohn Baldwin 	printf("}\n");
3500a473124SJohn Baldwin }
3510a473124SJohn Baldwin 
3520a473124SJohn Baldwin static void
353986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
3540a473124SJohn Baldwin {
3550a473124SJohn Baldwin 
356986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
357986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
358986dffafSJohn Baldwin }
359986dffafSJohn Baldwin 
360986dffafSJohn Baldwin static void
361986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
362986dffafSJohn Baldwin {
363986dffafSJohn Baldwin 
364986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
3650a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
3660a473124SJohn Baldwin }
3670a473124SJohn Baldwin 
368bf70beceSEd Schouten static const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override",
369bf70beceSEd Schouten 				    "NMI", "Local APIC NMI",
370bf70beceSEd Schouten 				    "Local APIC Override", "IO SAPIC",
371bf70beceSEd Schouten 				    "Local SAPIC", "Platform Interrupt",
372986dffafSJohn Baldwin 				    "Local X2APIC", "Local X2APIC NMI" };
373bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
3740a473124SJohn Baldwin 					    "Corrected Platform Error" };
3750a473124SJohn Baldwin 
3760a473124SJohn Baldwin static void
377986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
3780a473124SJohn Baldwin {
379986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
380986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
381986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
382986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
383986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
384986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
385986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
386986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
387986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
388986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
389986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
3900a473124SJohn Baldwin 
391986dffafSJohn Baldwin 	if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0]))
392986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
393a0333ad1SJohn Baldwin 	else
394986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
395986dffafSJohn Baldwin 	switch (mp->Type) {
396986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
397986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
398986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
399986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
4000a473124SJohn Baldwin 		break;
401986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
402986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
403986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
404986dffafSJohn Baldwin 		    ioapic->Address);
4050a473124SJohn Baldwin 		break;
406986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
407986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
408986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
409986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
410986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
4110a473124SJohn Baldwin 		break;
412986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
413986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
414986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
4150a473124SJohn Baldwin 		break;
416986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
417986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
418986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
419986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
4200a473124SJohn Baldwin 		break;
421986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
422986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
423945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
424986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
4250a473124SJohn Baldwin 		break;
426986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
427986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
428986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
429986dffafSJohn Baldwin 		    iosapic->Address);
4300a473124SJohn Baldwin 		break;
431986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
432986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
433986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
434986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
435986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
436986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
437986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
4380a473124SJohn Baldwin 		break;
439986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
440986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
441986dffafSJohn Baldwin 		if (isrc->Type < sizeof(platform_int_types) /
442986dffafSJohn Baldwin 		    sizeof(platform_int_types[0]))
443986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
444986dffafSJohn Baldwin 		else
445986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
446986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
447986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
448986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
449986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
450986dffafSJohn Baldwin 		break;
451986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
452986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
453986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
454986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
455986dffafSJohn Baldwin 		break;
456986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
457986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
458986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
459986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
4600a473124SJohn Baldwin 		break;
4610a473124SJohn Baldwin 	}
4620a473124SJohn Baldwin }
4630a473124SJohn Baldwin 
4640a473124SJohn Baldwin static void
465986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
4660a473124SJohn Baldwin {
467986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
4680a473124SJohn Baldwin 
469773b6454SNate Lawson 	printf(BEGIN_COMMENT);
470773b6454SNate Lawson 	acpi_print_sdt(sdp);
471986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
472986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
4730a473124SJohn Baldwin 	printf("\tFlags={");
474986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
4750a473124SJohn Baldwin 		printf("PC-AT");
4760a473124SJohn Baldwin 	printf("}\n");
477986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
4780a473124SJohn Baldwin 	printf(END_COMMENT);
4790a473124SJohn Baldwin }
4800a473124SJohn Baldwin 
4810a473124SJohn Baldwin static void
482986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
48379d7565cSPeter Wemm {
484986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
48579d7565cSPeter Wemm 
486773b6454SNate Lawson 	printf(BEGIN_COMMENT);
487773b6454SNate Lawson 	acpi_print_sdt(sdp);
488986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
489986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
49087f9f09aSTakanori Watanabe 	printf("\tADDR=");
491986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
492986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
493986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
494986dffafSJohn Baldwin 	    8);
495986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
496986dffafSJohn Baldwin 	    1 : 0);
49779d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
498986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
49979d7565cSPeter Wemm 		printf("TRUE}\n");
50079d7565cSPeter Wemm 	else
50179d7565cSPeter Wemm 		printf("FALSE}\n");
502986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
503986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
50479d7565cSPeter Wemm 	printf(END_COMMENT);
50579d7565cSPeter Wemm }
50679d7565cSPeter Wemm 
50779d7565cSPeter Wemm static void
508986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
50955d7ff9eSNate Lawson {
510986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
51155d7ff9eSNate Lawson 
51255d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
51355d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
514986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
51555d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
516986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
51755d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
518986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
519986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
520986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
521986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
52255d7ff9eSNate Lawson 	printf(END_COMMENT);
52355d7ff9eSNate Lawson }
52455d7ff9eSNate Lawson 
52555d7ff9eSNate Lawson static void
526986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
527a47e681bSScott Long {
528986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
529986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
530986dffafSJohn Baldwin 	u_int i, entries;
531a47e681bSScott Long 
532a47e681bSScott Long 	printf(BEGIN_COMMENT);
533a47e681bSScott Long 	acpi_print_sdt(sdp);
534986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
535986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
536986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
537986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
538986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
539a47e681bSScott Long 		printf("\n");
540986dffafSJohn Baldwin 		printf("\tBase Address=0x%016jx\n", alloc->Address);
541986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
542986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
543986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
544a47e681bSScott Long 	}
545a47e681bSScott Long 	printf(END_COMMENT);
546a47e681bSScott Long }
547a47e681bSScott Long 
548a47e681bSScott Long static void
54933866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
55033866658SJohn Baldwin {
55133866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
55233866658SJohn Baldwin 	UINT64 i, j;
55333866658SJohn Baldwin 
55433866658SJohn Baldwin 	printf(BEGIN_COMMENT);
55533866658SJohn Baldwin 	acpi_print_sdt(sdp);
55633866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
55733866658SJohn Baldwin 	printf("\tLocality Count=%jd\n", slit->LocalityCount);
55833866658SJohn Baldwin 	printf("\n\t      ");
55933866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
56033866658SJohn Baldwin 		printf(" %3jd", i);
56133866658SJohn Baldwin 	printf("\n\t     +");
56233866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
56333866658SJohn Baldwin 		printf("----");
56433866658SJohn Baldwin 	printf("\n");
56533866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
56633866658SJohn Baldwin 		printf("\t %3jd |", i);
56733866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
56833866658SJohn Baldwin 			printf(" %3d",
56933866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
57033866658SJohn Baldwin 		printf("\n");
57133866658SJohn Baldwin 	}
57233866658SJohn Baldwin 	printf(END_COMMENT);
57333866658SJohn Baldwin }
57433866658SJohn Baldwin 
57533866658SJohn Baldwin static void
576a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
577a0333ad1SJohn Baldwin     uint32_t flags)
578a0333ad1SJohn Baldwin {
579a0333ad1SJohn Baldwin 
580a0333ad1SJohn Baldwin 	printf("\tFlags={");
581a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
582a0333ad1SJohn Baldwin 		printf("ENABLED");
583a0333ad1SJohn Baldwin 	else
584a0333ad1SJohn Baldwin 		printf("DISABLED");
585a0333ad1SJohn Baldwin 	printf("}\n");
586a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
587a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
588a0333ad1SJohn Baldwin }
589a0333ad1SJohn Baldwin 
590c031c93bSTakanori Watanabe static char *
591c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
592c031c93bSTakanori Watanabe {
593c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
594c031c93bSTakanori Watanabe 	char *eventname = NULL;
595c031c93bSTakanori Watanabe 
596c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
597c031c93bSTakanori Watanabe 
598c031c93bSTakanori Watanabe 	switch(event->event_type) {
599c031c93bSTakanori Watanabe 	case PREBOOT:
600c031c93bSTakanori Watanabe 	case POST_CODE:
601c031c93bSTakanori Watanabe 	case UNUSED:
602c031c93bSTakanori Watanabe 	case NO_ACTION:
603c031c93bSTakanori Watanabe 	case SEPARATOR:
604c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
605c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
606c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
607c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
608c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
609c031c93bSTakanori Watanabe 	case COMPACT_HASH:
610c031c93bSTakanori Watanabe 	case IPL:
611c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
612c031c93bSTakanori Watanabe 	case NONHOST_CODE:
613c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
614c031c93bSTakanori Watanabe 	case NONHOST_INFO:
615c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
616c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
617c031c93bSTakanori Watanabe 		break;
618c031c93bSTakanori Watanabe 
619c031c93bSTakanori Watanabe 	case ACTION:
620c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
621c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
622c031c93bSTakanori Watanabe 		break;
623c031c93bSTakanori Watanabe 
624c031c93bSTakanori Watanabe 	case EVENT_TAG:
625c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
626c031c93bSTakanori Watanabe 		case SMBIOS:
627c031c93bSTakanori Watanabe 		case BIS_CERT:
628c031c93bSTakanori Watanabe 		case CMOS:
629c031c93bSTakanori Watanabe 		case NVRAM:
630c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
631c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
632c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
633c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
634c031c93bSTakanori Watanabe 		case ESCD:
635c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
636c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
637c031c93bSTakanori Watanabe 		case POST_CONTENTS:
638c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
639c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
640c031c93bSTakanori Watanabe 			break;
641c031c93bSTakanori Watanabe 
642c031c93bSTakanori Watanabe 		default:
643c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
644c031c93bSTakanori Watanabe 			    pc_event->event_id);
645c031c93bSTakanori Watanabe 			break;
646c031c93bSTakanori Watanabe 		}
647c031c93bSTakanori Watanabe 		break;
648c031c93bSTakanori Watanabe 
649c031c93bSTakanori Watanabe 	default:
650c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
651c031c93bSTakanori Watanabe 		break;
652c031c93bSTakanori Watanabe 	}
653c031c93bSTakanori Watanabe 
654c031c93bSTakanori Watanabe 	return eventname;
655c031c93bSTakanori Watanabe }
656c031c93bSTakanori Watanabe 
657c031c93bSTakanori Watanabe static void
658c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
659c031c93bSTakanori Watanabe {
660c031c93bSTakanori Watanabe 	int i;
661c031c93bSTakanori Watanabe 	char *eventname;
662c031c93bSTakanori Watanabe 
663c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
664c031c93bSTakanori Watanabe 
665c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
666c031c93bSTakanori Watanabe 	printf(" 0x");
667c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
668c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
669c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
670c031c93bSTakanori Watanabe 
671c031c93bSTakanori Watanabe 	free(eventname);
672c031c93bSTakanori Watanabe }
673c031c93bSTakanori Watanabe 
674c031c93bSTakanori Watanabe static void
675c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
676c031c93bSTakanori Watanabe {
677c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
678c031c93bSTakanori Watanabe 	struct TCPAevent *event;
679977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
680c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
681c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
682c031c93bSTakanori Watanabe 
683c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
684c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
685c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
686c031c93bSTakanori Watanabe 
687c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
688c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
689c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
690c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
691c031c93bSTakanori Watanabe 		break;
692c031c93bSTakanori Watanabe 
693c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
694c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
695c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
696c031c93bSTakanori Watanabe 		break;
697c031c93bSTakanori Watanabe 
698c031c93bSTakanori Watanabe 	default:
699c031c93bSTakanori Watanabe 		printf("XXX");
700c031c93bSTakanori Watanabe 		printf(END_COMMENT);
701c031c93bSTakanori Watanabe 		return;
702c031c93bSTakanori Watanabe 	}
7030e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
704c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
705c031c93bSTakanori Watanabe 
706c031c93bSTakanori Watanabe 	if (len == 0) {
707c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
708c031c93bSTakanori Watanabe 		printf(END_COMMENT);
709c031c93bSTakanori Watanabe 		return;
710c031c93bSTakanori Watanabe 	}
7112ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
7122ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
7132ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
7142ef23c6dSTakanori Watanabe 		return;
7152ef23c6dSTakanori Watanabe 	}
716c031c93bSTakanori Watanabe 
717c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
718c031c93bSTakanori Watanabe 	vend = vaddr + len;
719c031c93bSTakanori Watanabe 
720c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
7212ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
7222ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
723c031c93bSTakanori Watanabe 			break;
7240e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
725c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
726c031c93bSTakanori Watanabe 			break;
7272ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
7282ef23c6dSTakanori Watanabe 			break;
729c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
730c031c93bSTakanori Watanabe 			break;
731c031c93bSTakanori Watanabe #if 0
732c031c93bSTakanori Watanabe 		{
733c031c93bSTakanori Watanabe 		unsigned int i, j, k;
734c031c93bSTakanori Watanabe 
735c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
736c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
737c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
738c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
739c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
740c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
741c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
742c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
743c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
744c031c93bSTakanori Watanabe 				j = i + 1;
745c031c93bSTakanori Watanabe 			}
746c031c93bSTakanori Watanabe 		}
747c031c93bSTakanori Watanabe 		printf("\n"); }
748c031c93bSTakanori Watanabe #endif
749c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
750c031c93bSTakanori Watanabe 
751c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
752c031c93bSTakanori Watanabe 	}
753c031c93bSTakanori Watanabe 
754c031c93bSTakanori Watanabe 	printf(END_COMMENT);
755c031c93bSTakanori Watanabe }
756c031c93bSTakanori Watanabe 
757*ec650989SNeel Natu static const char *
758*ec650989SNeel Natu devscope_type2str(int type)
759*ec650989SNeel Natu {
760*ec650989SNeel Natu 	static char typebuf[16];
761*ec650989SNeel Natu 
762*ec650989SNeel Natu 	switch (type) {
763*ec650989SNeel Natu 	case 1:
764*ec650989SNeel Natu 		return ("PCI Endpoint Device");
765*ec650989SNeel Natu 	case 2:
766*ec650989SNeel Natu 		return ("PCI Sub-Hierarchy");
767*ec650989SNeel Natu 	case 3:
768*ec650989SNeel Natu 		return ("IOAPIC");
769*ec650989SNeel Natu 	case 4:
770*ec650989SNeel Natu 		return ("HPET");
771*ec650989SNeel Natu 	default:
772*ec650989SNeel Natu 		snprintf(typebuf, sizeof(typebuf), "%d", type);
773*ec650989SNeel Natu 		return (typebuf);
774*ec650989SNeel Natu 	}
775*ec650989SNeel Natu }
776*ec650989SNeel Natu 
777*ec650989SNeel Natu static int
778*ec650989SNeel Natu acpi_handle_dmar_devscope(void *addr, int remaining)
779*ec650989SNeel Natu {
780*ec650989SNeel Natu 	char sep;
781*ec650989SNeel Natu 	int pathlen;
782*ec650989SNeel Natu 	ACPI_DMAR_PCI_PATH *path, *pathend;
783*ec650989SNeel Natu 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
784*ec650989SNeel Natu 
785*ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
786*ec650989SNeel Natu 		return (-1);
787*ec650989SNeel Natu 
788*ec650989SNeel Natu 	if (remaining < devscope->Length)
789*ec650989SNeel Natu 		return (-1);
790*ec650989SNeel Natu 
791*ec650989SNeel Natu 	printf("\n");
792*ec650989SNeel Natu 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
793*ec650989SNeel Natu 	printf("\t\tLength=%d\n", devscope->Length);
794*ec650989SNeel Natu 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
795*ec650989SNeel Natu 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
796*ec650989SNeel Natu 
797*ec650989SNeel Natu 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
798*ec650989SNeel Natu 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
799*ec650989SNeel Natu 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
800*ec650989SNeel Natu 	if (path < pathend) {
801*ec650989SNeel Natu 		sep = '{';
802*ec650989SNeel Natu 		printf("\t\tPath=");
803*ec650989SNeel Natu 		do {
804*ec650989SNeel Natu 			printf("%c%d:%d", sep, path->Device, path->Function);
805*ec650989SNeel Natu 			sep=',';
806*ec650989SNeel Natu 			path++;
807*ec650989SNeel Natu 		} while (path < pathend);
808*ec650989SNeel Natu 		printf("}\n");
809*ec650989SNeel Natu 	}
810*ec650989SNeel Natu 
811*ec650989SNeel Natu 	return (devscope->Length);
812*ec650989SNeel Natu }
813*ec650989SNeel Natu 
814*ec650989SNeel Natu static void
815*ec650989SNeel Natu acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
816*ec650989SNeel Natu {
817*ec650989SNeel Natu 	char *cp;
818*ec650989SNeel Natu 	int remaining, consumed;
819*ec650989SNeel Natu 
820*ec650989SNeel Natu 	printf("\n");
821*ec650989SNeel Natu 	printf("\tType=DRHD\n");
822*ec650989SNeel Natu 	printf("\tLength=%d\n", drhd->Header.Length);
823*ec650989SNeel Natu 
824*ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
825*ec650989SNeel Natu 
826*ec650989SNeel Natu 	printf("\tFlags=");
827*ec650989SNeel Natu 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
828*ec650989SNeel Natu 	PRINTFLAG_END();
829*ec650989SNeel Natu 
830*ec650989SNeel Natu #undef PRINTFLAG
831*ec650989SNeel Natu 
832*ec650989SNeel Natu 	printf("\tSegment=%d\n", drhd->Segment);
833*ec650989SNeel Natu 	printf("\tAddress=0x%0jx\n", drhd->Address);
834*ec650989SNeel Natu 
835*ec650989SNeel Natu 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
836*ec650989SNeel Natu 	if (remaining > 0)
837*ec650989SNeel Natu 		printf("\tDevice Scope:");
838*ec650989SNeel Natu 	while (remaining > 0) {
839*ec650989SNeel Natu 		cp = (char *)drhd + drhd->Header.Length - remaining;
840*ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
841*ec650989SNeel Natu 		if (consumed <= 0)
842*ec650989SNeel Natu 			break;
843*ec650989SNeel Natu 		else
844*ec650989SNeel Natu 			remaining -= consumed;
845*ec650989SNeel Natu 	}
846*ec650989SNeel Natu }
847*ec650989SNeel Natu 
848*ec650989SNeel Natu static void
849*ec650989SNeel Natu acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
850*ec650989SNeel Natu {
851*ec650989SNeel Natu 	char *cp;
852*ec650989SNeel Natu 	int remaining, consumed;
853*ec650989SNeel Natu 
854*ec650989SNeel Natu 	printf("\n");
855*ec650989SNeel Natu 	printf("\tType=RMRR\n");
856*ec650989SNeel Natu 	printf("\tLength=%d\n", rmrr->Header.Length);
857*ec650989SNeel Natu 	printf("\tSegment=%d\n", rmrr->Segment);
858*ec650989SNeel Natu 	printf("\tBaseAddress=0x%0jx\n", rmrr->BaseAddress);
859*ec650989SNeel Natu 	printf("\tLimitAddress=0x%0jx\n", rmrr->EndAddress);
860*ec650989SNeel Natu 
861*ec650989SNeel Natu 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
862*ec650989SNeel Natu 	if (remaining > 0)
863*ec650989SNeel Natu 		printf("\tDevice Scope:");
864*ec650989SNeel Natu 	while (remaining > 0) {
865*ec650989SNeel Natu 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
866*ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
867*ec650989SNeel Natu 		if (consumed <= 0)
868*ec650989SNeel Natu 			break;
869*ec650989SNeel Natu 		else
870*ec650989SNeel Natu 			remaining -= consumed;
871*ec650989SNeel Natu 	}
872*ec650989SNeel Natu }
873*ec650989SNeel Natu 
874*ec650989SNeel Natu static void
875*ec650989SNeel Natu acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
876*ec650989SNeel Natu {
877*ec650989SNeel Natu 	char *cp;
878*ec650989SNeel Natu 	int remaining, consumed;
879*ec650989SNeel Natu 
880*ec650989SNeel Natu 	printf("\n");
881*ec650989SNeel Natu 	printf("\tType=ATSR\n");
882*ec650989SNeel Natu 	printf("\tLength=%d\n", atsr->Header.Length);
883*ec650989SNeel Natu 
884*ec650989SNeel Natu #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
885*ec650989SNeel Natu 
886*ec650989SNeel Natu 	printf("\tFlags=");
887*ec650989SNeel Natu 	PRINTFLAG(atsr->Flags, ALL_PORTS);
888*ec650989SNeel Natu 	PRINTFLAG_END();
889*ec650989SNeel Natu 
890*ec650989SNeel Natu #undef PRINTFLAG
891*ec650989SNeel Natu 
892*ec650989SNeel Natu 	printf("\tSegment=%d\n", atsr->Segment);
893*ec650989SNeel Natu 
894*ec650989SNeel Natu 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
895*ec650989SNeel Natu 	if (remaining > 0)
896*ec650989SNeel Natu 		printf("\tDevice Scope:");
897*ec650989SNeel Natu 	while (remaining > 0) {
898*ec650989SNeel Natu 		cp = (char *)atsr + atsr->Header.Length - remaining;
899*ec650989SNeel Natu 		consumed = acpi_handle_dmar_devscope(cp, remaining);
900*ec650989SNeel Natu 		if (consumed <= 0)
901*ec650989SNeel Natu 			break;
902*ec650989SNeel Natu 		else
903*ec650989SNeel Natu 			remaining -= consumed;
904*ec650989SNeel Natu 	}
905*ec650989SNeel Natu }
906*ec650989SNeel Natu 
907*ec650989SNeel Natu static void
908*ec650989SNeel Natu acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
909*ec650989SNeel Natu {
910*ec650989SNeel Natu 
911*ec650989SNeel Natu 	printf("\n");
912*ec650989SNeel Natu 	printf("\tType=RHSA\n");
913*ec650989SNeel Natu 	printf("\tLength=%d\n", rhsa->Header.Length);
914*ec650989SNeel Natu 	printf("\tBaseAddress=0x%0jx\n", rhsa->BaseAddress);
915*ec650989SNeel Natu 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
916*ec650989SNeel Natu }
917*ec650989SNeel Natu 
918*ec650989SNeel Natu static int
919*ec650989SNeel Natu acpi_handle_dmar_remapping_structure(void *addr, int remaining)
920*ec650989SNeel Natu {
921*ec650989SNeel Natu 	ACPI_DMAR_HEADER *hdr = addr;
922*ec650989SNeel Natu 
923*ec650989SNeel Natu 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
924*ec650989SNeel Natu 		return (-1);
925*ec650989SNeel Natu 
926*ec650989SNeel Natu 	if (remaining < hdr->Length)
927*ec650989SNeel Natu 		return (-1);
928*ec650989SNeel Natu 
929*ec650989SNeel Natu 	switch (hdr->Type) {
930*ec650989SNeel Natu 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
931*ec650989SNeel Natu 		acpi_handle_dmar_drhd(addr);
932*ec650989SNeel Natu 		break;
933*ec650989SNeel Natu 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
934*ec650989SNeel Natu 		acpi_handle_dmar_rmrr(addr);
935*ec650989SNeel Natu 		break;
936*ec650989SNeel Natu 	case ACPI_DMAR_TYPE_ATSR:
937*ec650989SNeel Natu 		acpi_handle_dmar_atsr(addr);
938*ec650989SNeel Natu 		break;
939*ec650989SNeel Natu 	case ACPI_DMAR_HARDWARE_AFFINITY:
940*ec650989SNeel Natu 		acpi_handle_dmar_rhsa(addr);
941*ec650989SNeel Natu 		break;
942*ec650989SNeel Natu 	default:
943*ec650989SNeel Natu 		printf("\n");
944*ec650989SNeel Natu 		printf("\tType=%d\n", hdr->Type);
945*ec650989SNeel Natu 		printf("\tLength=%d\n", hdr->Length);
946*ec650989SNeel Natu 		break;
947*ec650989SNeel Natu 	}
948*ec650989SNeel Natu 	return (hdr->Length);
949*ec650989SNeel Natu }
950*ec650989SNeel Natu 
951*ec650989SNeel Natu #ifndef ACPI_DMAR_X2APIC_OPT_OUT
952*ec650989SNeel Natu #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
953*ec650989SNeel Natu #endif
954*ec650989SNeel Natu 
955*ec650989SNeel Natu static void
956*ec650989SNeel Natu acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
957*ec650989SNeel Natu {
958*ec650989SNeel Natu 	char *cp;
959*ec650989SNeel Natu 	int remaining, consumed;
960*ec650989SNeel Natu 	ACPI_TABLE_DMAR *dmar;
961*ec650989SNeel Natu 
962*ec650989SNeel Natu 	printf(BEGIN_COMMENT);
963*ec650989SNeel Natu 	acpi_print_sdt(sdp);
964*ec650989SNeel Natu 	dmar = (ACPI_TABLE_DMAR *)sdp;
965*ec650989SNeel Natu 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
966*ec650989SNeel Natu 
967*ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
968*ec650989SNeel Natu 
969*ec650989SNeel Natu 	printf("\tFlags=");
970*ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, INTR_REMAP);
971*ec650989SNeel Natu 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
972*ec650989SNeel Natu 	PRINTFLAG_END();
973*ec650989SNeel Natu 
974*ec650989SNeel Natu #undef PRINTFLAG
975*ec650989SNeel Natu 
976*ec650989SNeel Natu 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
977*ec650989SNeel Natu 	while (remaining > 0) {
978*ec650989SNeel Natu 		cp = (char *)sdp + sdp->Length - remaining;
979*ec650989SNeel Natu 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
980*ec650989SNeel Natu 		if (consumed <= 0)
981*ec650989SNeel Natu 			break;
982*ec650989SNeel Natu 		else
983*ec650989SNeel Natu 			remaining -= consumed;
984*ec650989SNeel Natu 	}
985*ec650989SNeel Natu 
986*ec650989SNeel Natu 	printf(END_COMMENT);
987*ec650989SNeel Natu }
988*ec650989SNeel Natu 
989a0333ad1SJohn Baldwin static void
990986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
991a0333ad1SJohn Baldwin {
992a0333ad1SJohn Baldwin 
993a0333ad1SJohn Baldwin 	printf("\tFlags={");
994986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
995a0333ad1SJohn Baldwin 		printf("ENABLED");
996a0333ad1SJohn Baldwin 	else
997a0333ad1SJohn Baldwin 		printf("DISABLED");
998986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
999a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
1000986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1001a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
1002a0333ad1SJohn Baldwin 	printf("}\n");
1003986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1004986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1005986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1006a0333ad1SJohn Baldwin }
1007a0333ad1SJohn Baldwin 
1008bf70beceSEd Schouten static const char *srat_types[] = { "CPU", "Memory", "X2APIC" };
1009a0333ad1SJohn Baldwin 
1010a0333ad1SJohn Baldwin static void
1011986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1012a0333ad1SJohn Baldwin {
1013986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
1014986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
1015a0333ad1SJohn Baldwin 
1016986dffafSJohn Baldwin 	if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0]))
1017986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
1018a0333ad1SJohn Baldwin 	else
1019986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
1020986dffafSJohn Baldwin 	switch (srat->Type) {
1021a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1022986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1023986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
1024986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
1025986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
1026986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
1027986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
1028a0333ad1SJohn Baldwin 		break;
1029a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1030986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1031a0333ad1SJohn Baldwin 		break;
1032a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1033986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1034986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1035986dffafSJohn Baldwin 		    x2apic->Flags);
1036a0333ad1SJohn Baldwin 		break;
1037a0333ad1SJohn Baldwin 	}
1038a0333ad1SJohn Baldwin }
1039a0333ad1SJohn Baldwin 
1040a0333ad1SJohn Baldwin static void
1041986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1042a0333ad1SJohn Baldwin {
1043986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
1044a0333ad1SJohn Baldwin 
1045a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
1046a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
1047986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
1048986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
1049986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1050a0333ad1SJohn Baldwin 	printf(END_COMMENT);
1051a0333ad1SJohn Baldwin }
1052a0333ad1SJohn Baldwin 
1053a0333ad1SJohn Baldwin static void
1054986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1055c62f1cccSMitsuru IWASAKI {
1056773b6454SNate Lawson 	printf("  ");
1057986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
1058c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1059986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
1060e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
1061986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1062e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
1063986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1064986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1065e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
1066986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
1067986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1068e1e9a4bfSMitsuru IWASAKI }
1069e1e9a4bfSMitsuru IWASAKI 
1070945137d9SNate Lawson static void
1071986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1072e1e9a4bfSMitsuru IWASAKI {
1073986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1074986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1075e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
1076a74172abSNate Lawson 	u_long	addr;
1077e1e9a4bfSMitsuru IWASAKI 
1078986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1079986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1080773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1081773b6454SNate Lawson 	acpi_print_sdt(rsdp);
1082986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1083e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
1084e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1085e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
1086e1e9a4bfSMitsuru IWASAKI 			printf(", ");
1087a74172abSNate Lawson 		switch (addr_size) {
1088a74172abSNate Lawson 		case 4:
1089986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1090a74172abSNate Lawson 			break;
1091a74172abSNate Lawson 		case 8:
1092986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1093a74172abSNate Lawson 			break;
1094a74172abSNate Lawson 		default:
1095a74172abSNate Lawson 			addr = 0;
1096a74172abSNate Lawson 		}
1097a74172abSNate Lawson 		assert(addr != 0);
1098a74172abSNate Lawson 		printf("0x%08lx", addr);
1099e1e9a4bfSMitsuru IWASAKI 	}
1100e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
1101c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1102e1e9a4bfSMitsuru IWASAKI }
1103e1e9a4bfSMitsuru IWASAKI 
11048e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
11058e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
11068e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
11078e6a8737SNate Lawson };
11088e6a8737SNate Lawson 
1109945137d9SNate Lawson static void
1110986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1111e1e9a4bfSMitsuru IWASAKI {
1112986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
11138e6a8737SNate Lawson 	const char *pm;
1114e1e9a4bfSMitsuru IWASAKI 
1115986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
1116c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
11172177d4e6SNate Lawson 	acpi_print_sdt(sdp);
1118986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1119986dffafSJohn Baldwin 	       fadt->Dsdt);
1120986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1121986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
11228e6a8737SNate Lawson 		pm = "Reserved";
11238e6a8737SNate Lawson 	else
1124986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1125986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1126986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1127986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1128986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1129986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1130986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1131986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1132e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1133986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
1134986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1135986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
1136e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1137986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
1138986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1139e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1140986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
1141986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1142986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
1143e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1144986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
1145986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1146986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
1147e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1148986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
1149986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1150c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1151986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
1152986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1153986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
11548e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1155986dffafSJohn Baldwin 		       fadt->Gpe0Block,
1156986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1157986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
11588e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1159986dffafSJohn Baldwin 		       fadt->Gpe1Block,
1160986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1161986dffafSJohn Baldwin 		       fadt->Gpe1Base);
1162986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
1163986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
116451c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1165986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
1166e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1167986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
1168e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1169986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
1170e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1171986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1172e1e9a4bfSMitsuru IWASAKI 
1173*ec650989SNeel Natu #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1174e1e9a4bfSMitsuru IWASAKI 
11758e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
1176986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1177986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
1178986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1179986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1180986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1181*ec650989SNeel Natu 	PRINTFLAG_END();
11828e6a8737SNate Lawson 
11838e6a8737SNate Lawson 	printf("\tFlags=");
1184986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
1185986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1186986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1187986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1188986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1189986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1190986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1191986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1192986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1193986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1194986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1195986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1196986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
1197986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1198986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1199986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1200986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1201986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1202986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1203986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1204*ec650989SNeel Natu 	PRINTFLAG_END();
1205e1e9a4bfSMitsuru IWASAKI 
1206e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
1207e1e9a4bfSMitsuru IWASAKI 
1208986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
12098e6a8737SNate Lawson 		printf("\tRESET_REG=");
1210986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
1211986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
12128e6a8737SNate Lawson 	}
1213c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
1214986dffafSJohn Baldwin 		printf("\tX_FACS=0x%08lx, ", (u_long)fadt->XFacs);
1215986dffafSJohn Baldwin 		printf("X_DSDT=0x%08lx\n", (u_long)fadt->XDsdt);
1216c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
1217986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
1218986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
1219c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
1220986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
1221c08c4e81SNate Lawson 		}
1222c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
1223986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
1224986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
1225c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
1226986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
1227c08c4e81SNate Lawson 		}
1228986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
1229773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
1230986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
1231c08c4e81SNate Lawson 		}
1232773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
1233986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
1234986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
1235773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
1236986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
1237c08c4e81SNate Lawson 		}
1238986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
1239773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
1240986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
1241c08c4e81SNate Lawson 		}
1242773b6454SNate Lawson 		printf("\n");
1243773b6454SNate Lawson 	}
12448e6a8737SNate Lawson 
12458e6a8737SNate Lawson 	printf(END_COMMENT);
12468e6a8737SNate Lawson }
12478e6a8737SNate Lawson 
12488e6a8737SNate Lawson static void
1249986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
12508e6a8737SNate Lawson {
12518e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1252986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1253986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1254986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
12558e6a8737SNate Lawson 
1256773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1257986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1258986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
12598e6a8737SNate Lawson 			printf("PENDING,");
1260986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
12618e6a8737SNate Lawson 			printf("OWNED");
12628e6a8737SNate Lawson 	}
1263773b6454SNate Lawson 	printf("\n");
12648e6a8737SNate Lawson 
1265773b6454SNate Lawson 	printf("\tFlags=");
1266986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
12678e6a8737SNate Lawson 		printf("S4BIOS");
1268773b6454SNate Lawson 	printf("\n");
12698e6a8737SNate Lawson 
1270986dffafSJohn Baldwin 	if (facs->XFirmwareWakingVector != 0) {
12718e6a8737SNate Lawson 		printf("\tX_Firm_Wake_Vec=%08lx\n",
1272986dffafSJohn Baldwin 		       (u_long)facs->XFirmwareWakingVector);
12738e6a8737SNate Lawson 	}
1274986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
12758e6a8737SNate Lawson 
1276c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1277e1e9a4bfSMitsuru IWASAKI }
1278e1e9a4bfSMitsuru IWASAKI 
1279945137d9SNate Lawson static void
1280986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1281e1e9a4bfSMitsuru IWASAKI {
1282773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1283773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1284773b6454SNate Lawson 	printf(END_COMMENT);
1285e1e9a4bfSMitsuru IWASAKI }
1286e1e9a4bfSMitsuru IWASAKI 
1287e1e9a4bfSMitsuru IWASAKI int
1288e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1289e1e9a4bfSMitsuru IWASAKI {
1290986dffafSJohn Baldwin 	uint8_t *bp;
1291986dffafSJohn Baldwin 	uint8_t sum;
1292e1e9a4bfSMitsuru IWASAKI 
1293e1e9a4bfSMitsuru IWASAKI 	bp = p;
1294e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1295e1e9a4bfSMitsuru IWASAKI 	while (length--)
1296e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1297e1e9a4bfSMitsuru IWASAKI 
1298e1e9a4bfSMitsuru IWASAKI 	return (sum);
1299e1e9a4bfSMitsuru IWASAKI }
1300e1e9a4bfSMitsuru IWASAKI 
1301986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1302e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1303e1e9a4bfSMitsuru IWASAKI {
1304986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1305e1e9a4bfSMitsuru IWASAKI 
1306986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1307986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1308e1e9a4bfSMitsuru IWASAKI 	return (sp);
1309e1e9a4bfSMitsuru IWASAKI }
1310e1e9a4bfSMitsuru IWASAKI 
1311945137d9SNate Lawson static void
1312986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1313e1e9a4bfSMitsuru IWASAKI {
1314c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1315a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1316986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1317986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1318986dffafSJohn Baldwin 	       rp->Revision);
1319986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1320986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1321986dffafSJohn Baldwin 		    rp->Checksum);
1322a74172abSNate Lawson 	} else {
1323a74172abSNate Lawson 		printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n",
1324986dffafSJohn Baldwin 		    (u_long)rp->XsdtPhysicalAddress, rp->Length,
1325986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1326a74172abSNate Lawson 	}
1327c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1328e1e9a4bfSMitsuru IWASAKI }
1329e1e9a4bfSMitsuru IWASAKI 
1330945137d9SNate Lawson static void
1331986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1332e1e9a4bfSMitsuru IWASAKI {
1333986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1334986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1335986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1336a74172abSNate Lawson 	vm_offset_t addr;
1337a74172abSNate Lawson 	int entries, i;
1338e1e9a4bfSMitsuru IWASAKI 
1339e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1340986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1341986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1342986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1343e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1344a74172abSNate Lawson 		switch (addr_size) {
1345a74172abSNate Lawson 		case 4:
1346986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1347a74172abSNate Lawson 			break;
1348a74172abSNate Lawson 		case 8:
1349986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1350a74172abSNate Lawson 			break;
1351a74172abSNate Lawson 		default:
1352a74172abSNate Lawson 			assert((addr = 0));
1353a74172abSNate Lawson 		}
1354a74172abSNate Lawson 
1355986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1356986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
13575cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1358986dffafSJohn Baldwin 			    sdp->Signature);
13595cf6d493SNate Lawson 			continue;
13605cf6d493SNate Lawson 		}
1361986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
13622177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1363986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1364986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1365986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
136679d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1367986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
136855d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1369986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1370a47e681bSScott Long 			acpi_handle_mcfg(sdp);
137133866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
137233866658SJohn Baldwin 			acpi_handle_slit(sdp);
1373986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1374a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1375c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1376c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1377*ec650989SNeel Natu 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1378*ec650989SNeel Natu 			acpi_handle_dmar(sdp);
1379773b6454SNate Lawson 		else {
1380773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1381773b6454SNate Lawson 			acpi_print_sdt(sdp);
1382773b6454SNate Lawson 			printf(END_COMMENT);
1383773b6454SNate Lawson 		}
1384e1e9a4bfSMitsuru IWASAKI 	}
1385e1e9a4bfSMitsuru IWASAKI }
1386c62f1cccSMitsuru IWASAKI 
1387986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1388476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1389945137d9SNate Lawson {
1390986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1391986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1392945137d9SNate Lawson 
1393945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1394945137d9SNate Lawson 	if (!rp)
1395945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1396945137d9SNate Lawson 
1397945137d9SNate Lawson 	if (tflag)
1398945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1399986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1400986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1401986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1402986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1403945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1404a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1405a74172abSNate Lawson 	} else {
1406986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1407986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1408986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1409a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1410a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1411a74172abSNate Lawson 	}
1412945137d9SNate Lawson 	return (rsdp);
1413945137d9SNate Lawson }
1414c62f1cccSMitsuru IWASAKI 
141562c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1416bfa3f012SMarcel Moolenaar static int
1417986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1418bfa3f012SMarcel Moolenaar {
1419986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1420986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1421bfa3f012SMarcel Moolenaar 	uint8_t sum;
1422bfa3f012SMarcel Moolenaar 
142362c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1424bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1425bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1426986dffafSJohn Baldwin 		sdt.Checksum = 0;
1427986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1428986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1429986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1430f7675a56SNate Lawson 		while (ssdt != NULL) {
1431986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1432986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1433986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1434986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1435bfa3f012SMarcel Moolenaar 		}
1436986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1437986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1438bfa3f012SMarcel Moolenaar 	}
143962c7bde1SNate Lawson 
144062c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1441986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1442986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
144362c7bde1SNate Lawson 
1444b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1445f7675a56SNate Lawson 	if (rsdt != NULL) {
1446bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1447bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1448986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1449986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1450bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1451bfa3f012SMarcel Moolenaar 		}
1452bfa3f012SMarcel Moolenaar 	}
1453bfa3f012SMarcel Moolenaar 	return (0);
1454bfa3f012SMarcel Moolenaar }
1455bfa3f012SMarcel Moolenaar 
1456c62f1cccSMitsuru IWASAKI void
1457986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1458c62f1cccSMitsuru IWASAKI {
1459945137d9SNate Lawson 	int	fd;
1460945137d9SNate Lawson 	mode_t	mode;
1461945137d9SNate Lawson 
1462945137d9SNate Lawson 	assert(outfile != NULL);
1463945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1464945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1465945137d9SNate Lawson 	if (fd == -1) {
1466945137d9SNate Lawson 		perror("dsdt_save_file");
1467945137d9SNate Lawson 		return;
1468945137d9SNate Lawson 	}
1469bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1470945137d9SNate Lawson 	close(fd);
1471c62f1cccSMitsuru IWASAKI }
1472c62f1cccSMitsuru IWASAKI 
1473945137d9SNate Lawson void
1474986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1475c62f1cccSMitsuru IWASAKI {
147699065116SJung-uk Kim 	char buf[PATH_MAX], tmpstr[PATH_MAX];
147799065116SJung-uk Kim 	const char *tmpdir;
147899065116SJung-uk Kim 	char *tmpext;
1479945137d9SNate Lawson 	FILE *fp;
148099065116SJung-uk Kim 	size_t len;
148199065116SJung-uk Kim 	int fd;
1482945137d9SNate Lawson 
148399065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
148499065116SJung-uk Kim 	if (tmpdir == NULL)
148599065116SJung-uk Kim 		tmpdir = _PATH_TMP;
148699065116SJung-uk Kim 	strncpy(tmpstr, tmpdir, sizeof(tmpstr));
148799065116SJung-uk Kim 	if (realpath(tmpstr, buf) == NULL) {
1488d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
148999065116SJung-uk Kim 		return;
149099065116SJung-uk Kim 	}
149199065116SJung-uk Kim 	strncpy(tmpstr, buf, sizeof(tmpstr));
1492d6a6e590SJung-uk Kim 	strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(buf));
1493d6a6e590SJung-uk Kim 	len = strlen(tmpstr);
149499065116SJung-uk Kim 	tmpext = tmpstr + len;
149599065116SJung-uk Kim 	strncpy(tmpext, "XXXXXX", sizeof(tmpstr) - len);
1496945137d9SNate Lawson 	fd = mkstemp(tmpstr);
1497945137d9SNate Lawson 	if (fd < 0) {
1498945137d9SNate Lawson 		perror("iasl tmp file");
1499945137d9SNate Lawson 		return;
1500c62f1cccSMitsuru IWASAKI 	}
1501bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1502945137d9SNate Lawson 	close(fd);
1503945137d9SNate Lawson 
1504945137d9SNate Lawson 	/* Run iasl -d on the temp file */
1505945137d9SNate Lawson 	if (fork() == 0) {
1506945137d9SNate Lawson 		close(STDOUT_FILENO);
1507945137d9SNate Lawson 		if (vflag == 0)
1508945137d9SNate Lawson 			close(STDERR_FILENO);
150999065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1510945137d9SNate Lawson 		err(1, "exec");
1511c62f1cccSMitsuru IWASAKI 	}
1512c62f1cccSMitsuru IWASAKI 
1513945137d9SNate Lawson 	wait(NULL);
1514945137d9SNate Lawson 	unlink(tmpstr);
1515945137d9SNate Lawson 
1516945137d9SNate Lawson 	/* Dump iasl's output to stdout */
151799065116SJung-uk Kim 	strncpy(tmpext, "dsl", sizeof(tmpstr) - len);
151899065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
151999065116SJung-uk Kim 	unlink(tmpstr);
1520945137d9SNate Lawson 	if (fp == NULL) {
1521945137d9SNate Lawson 		perror("iasl tmp file (read)");
1522945137d9SNate Lawson 		return;
1523945137d9SNate Lawson 	}
1524945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1525945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1526945137d9SNate Lawson 	fclose(fp);
1527c62f1cccSMitsuru IWASAKI }
1528c62f1cccSMitsuru IWASAKI 
1529945137d9SNate Lawson void
1530986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1531c62f1cccSMitsuru IWASAKI {
1532945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1533c62f1cccSMitsuru IWASAKI }
1534c62f1cccSMitsuru IWASAKI 
1535bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1536986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1537986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1538c62f1cccSMitsuru IWASAKI {
1539986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1540986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1541986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1542a74172abSNate Lawson 	vm_offset_t addr;
1543a74172abSNate Lawson 	int entries, i;
1544945137d9SNate Lawson 
1545986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1546986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1547986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1548945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1549a74172abSNate Lawson 		switch (addr_size) {
1550a74172abSNate Lawson 		case 4:
1551986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1552a74172abSNate Lawson 			break;
1553a74172abSNate Lawson 		case 8:
1554986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1555a74172abSNate Lawson 			break;
1556a74172abSNate Lawson 		default:
1557a74172abSNate Lawson 			assert((addr = 0));
1558a74172abSNate Lawson 		}
1559986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1560bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1561bfa3f012SMarcel Moolenaar 			if (sdt == last)
1562bfa3f012SMarcel Moolenaar 				last = NULL;
1563bfa3f012SMarcel Moolenaar 			continue;
1564bfa3f012SMarcel Moolenaar 		}
1565986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1566a74172abSNate Lawson 			continue;
1567986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1568945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1569945137d9SNate Lawson 		return (sdt);
1570c62f1cccSMitsuru IWASAKI 	}
1571c62f1cccSMitsuru IWASAKI 
1572945137d9SNate Lawson 	return (NULL);
1573c62f1cccSMitsuru IWASAKI }
1574c62f1cccSMitsuru IWASAKI 
1575986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1576986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1577c62f1cccSMitsuru IWASAKI {
1578986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1579c62f1cccSMitsuru IWASAKI 
1580986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1581c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1582986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
15832e71eb12SNate Lawson 	else
1584986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1585986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1586945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1587945137d9SNate Lawson 	return (sdt);
1588c62f1cccSMitsuru IWASAKI }
1589