xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision 977fd9da579b7f88c9128d82c229a253c49fbb36)
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);
66a0333ad1SJohn Baldwin static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
67a0333ad1SJohn Baldwin 		    uint32_t flags);
68986dffafSJohn Baldwin static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
69986dffafSJohn Baldwin static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
70986dffafSJohn Baldwin static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
71c031c93bSTakanori Watanabe static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
72986dffafSJohn Baldwin static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
73986dffafSJohn Baldwin static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
74986dffafSJohn Baldwin static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
75986dffafSJohn Baldwin static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
76986dffafSJohn Baldwin static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
77986dffafSJohn Baldwin static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
78986dffafSJohn Baldwin static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
79986dffafSJohn Baldwin static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
80986dffafSJohn Baldwin 		    void (*action)(ACPI_SUBTABLE_HEADER *));
81c62f1cccSMitsuru IWASAKI 
82773b6454SNate Lawson /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
83a74172abSNate Lawson static int addr_size;
84a74172abSNate Lawson 
85c031c93bSTakanori Watanabe /* Strings used in the TCPA table */
86c031c93bSTakanori Watanabe static const char *tcpa_event_type_strings[] = {
87c031c93bSTakanori Watanabe 	"PREBOOT Certificate",
88c031c93bSTakanori Watanabe 	"POST Code",
89c031c93bSTakanori Watanabe 	"Unused",
90c031c93bSTakanori Watanabe 	"No Action",
91c031c93bSTakanori Watanabe 	"Separator",
92c031c93bSTakanori Watanabe 	"Action",
93c031c93bSTakanori Watanabe 	"Event Tag",
94c031c93bSTakanori Watanabe 	"S-CRTM Contents",
95c031c93bSTakanori Watanabe 	"S-CRTM Version",
96c031c93bSTakanori Watanabe 	"CPU Microcode",
97c031c93bSTakanori Watanabe 	"Platform Config Flags",
98c031c93bSTakanori Watanabe 	"Table of Devices",
99c031c93bSTakanori Watanabe 	"Compact Hash",
100c031c93bSTakanori Watanabe 	"IPL",
101c031c93bSTakanori Watanabe 	"IPL Partition Data",
102c031c93bSTakanori Watanabe 	"Non-Host Code",
103c031c93bSTakanori Watanabe 	"Non-Host Config",
104c031c93bSTakanori Watanabe 	"Non-Host Info"
105c031c93bSTakanori Watanabe };
106c031c93bSTakanori Watanabe 
107c031c93bSTakanori Watanabe static const char *TCPA_pcclient_strings[] = {
108c031c93bSTakanori Watanabe 	"<undefined>",
109c031c93bSTakanori Watanabe 	"SMBIOS",
110c031c93bSTakanori Watanabe 	"BIS Certificate",
111c031c93bSTakanori Watanabe 	"POST BIOS ROM Strings",
112c031c93bSTakanori Watanabe 	"ESCD",
113c031c93bSTakanori Watanabe 	"CMOS",
114c031c93bSTakanori Watanabe 	"NVRAM",
115c031c93bSTakanori Watanabe 	"Option ROM Execute",
116c031c93bSTakanori Watanabe 	"Option ROM Configurateion",
117c031c93bSTakanori Watanabe 	"<undefined>",
118c031c93bSTakanori Watanabe 	"Option ROM Microcode Update ",
119c031c93bSTakanori Watanabe 	"S-CRTM Version String",
120c031c93bSTakanori Watanabe 	"S-CRTM Contents",
121c031c93bSTakanori Watanabe 	"POST Contents",
122c031c93bSTakanori Watanabe 	"Table of Devices",
123c031c93bSTakanori Watanabe };
124c031c93bSTakanori Watanabe 
125e1e9a4bfSMitsuru IWASAKI static void
126e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
127e1e9a4bfSMitsuru IWASAKI {
128e1e9a4bfSMitsuru IWASAKI 	int	c;
129e1e9a4bfSMitsuru IWASAKI 
130e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
131e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
132e1e9a4bfSMitsuru IWASAKI 		length--;
133e1e9a4bfSMitsuru IWASAKI 
134e1e9a4bfSMitsuru IWASAKI 	while (length--) {
135e1e9a4bfSMitsuru IWASAKI 		c = *s++;
136e1e9a4bfSMitsuru IWASAKI 		putchar(c);
137e1e9a4bfSMitsuru IWASAKI 	}
138e1e9a4bfSMitsuru IWASAKI }
139e1e9a4bfSMitsuru IWASAKI 
140e1e9a4bfSMitsuru IWASAKI static void
141986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1428e6a8737SNate Lawson {
143986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1448e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
145986dffafSJohn Baldwin 		printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->Address,
146986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1478e6a8737SNate Lawson 		break;
1488e6a8737SNate Lawson 	case ACPI_GAS_IO:
149986dffafSJohn Baldwin 		printf("0x%02lx:%u[%u] (IO)", (u_long)gas->Address,
150986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1518e6a8737SNate Lawson 		break;
1528e6a8737SNate Lawson 	case ACPI_GAS_PCI:
153986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
154986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
155986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1568e6a8737SNate Lawson 		break;
1578e6a8737SNate Lawson 	/* XXX How to handle these below? */
1588e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
159986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
160986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1618e6a8737SNate Lawson 		break;
1628e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
163986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
164986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1658e6a8737SNate Lawson 		break;
166986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
167986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
168986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
1698e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
1708e6a8737SNate Lawson 	default:
171986dffafSJohn Baldwin 		printf("0x%08lx (?)", (u_long)gas->Address);
1728e6a8737SNate Lawson 		break;
1738e6a8737SNate Lawson 	}
1748e6a8737SNate Lawson }
1758e6a8737SNate Lawson 
176c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
177c2962974SNate Lawson static int
178986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
179e1e9a4bfSMitsuru IWASAKI {
180c2962974SNate Lawson 	int fadt_revision;
181e1e9a4bfSMitsuru IWASAKI 
182c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
183c83f0f99SNate Lawson 	if (addr_size == 8) {
184c83f0f99SNate Lawson 		fadt_revision = 2;
1858e6a8737SNate Lawson 
186773b6454SNate Lawson 		/*
187c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
188c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
189c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
190c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
191c83f0f99SNate Lawson 		 * version for all subsequent tables.
192773b6454SNate Lawson 		 */
193986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
194986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
195c83f0f99SNate Lawson 			fadt_revision = 1;
196c2962974SNate Lawson 	} else
197c83f0f99SNate Lawson 		fadt_revision = 1;
198c2962974SNate Lawson 	return (fadt_revision);
199c83f0f99SNate Lawson }
200c2962974SNate Lawson 
201c2962974SNate Lawson static void
202986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
203c2962974SNate Lawson {
204986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
205986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
206986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
207c2962974SNate Lawson 	int		fadt_revision;
208c2962974SNate Lawson 
209986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2102177d4e6SNate Lawson 	acpi_print_fadt(sdp);
211c83f0f99SNate Lawson 
212c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
213c83f0f99SNate Lawson 	if (fadt_revision == 1)
214986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
215773b6454SNate Lawson 	else
216986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
217986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2188e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2198e6a8737SNate Lawson 	acpi_print_facs(facs);
2208e6a8737SNate Lawson 
221c83f0f99SNate Lawson 	if (fadt_revision == 1)
222986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
223773b6454SNate Lawson 	else
224986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
225986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
226945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
227945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
228c62f1cccSMitsuru IWASAKI }
229c62f1cccSMitsuru IWASAKI 
230c62f1cccSMitsuru IWASAKI static void
231986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
232986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
233986dffafSJohn Baldwin {
234986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
235986dffafSJohn Baldwin 	char *end;
236986dffafSJohn Baldwin 
237986dffafSJohn Baldwin 	subtable = first;
238986dffafSJohn Baldwin 	end = (char *)table + table->Length;
239986dffafSJohn Baldwin 	while ((char *)subtable < end) {
240986dffafSJohn Baldwin 		printf("\n");
241986dffafSJohn Baldwin 		action(subtable);
242986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
243986dffafSJohn Baldwin 		    subtable->Length);
244986dffafSJohn Baldwin 	}
245986dffafSJohn Baldwin }
246986dffafSJohn Baldwin 
247986dffafSJohn Baldwin static void
2480a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
2490a473124SJohn Baldwin {
2500a473124SJohn Baldwin 
2510a473124SJohn Baldwin 	printf("\tACPI CPU=");
2520a473124SJohn Baldwin 	if (cpu_id == 0xff)
2530a473124SJohn Baldwin 		printf("ALL\n");
2540a473124SJohn Baldwin 	else
2550a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
2560a473124SJohn Baldwin }
2570a473124SJohn Baldwin 
2580a473124SJohn Baldwin static void
259986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
2600a473124SJohn Baldwin {
261986dffafSJohn Baldwin 
262986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
263986dffafSJohn Baldwin 	if (uid_string != NULL)
264986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
265986dffafSJohn Baldwin 	printf("\n");
266986dffafSJohn Baldwin }
267986dffafSJohn Baldwin 
268986dffafSJohn Baldwin static void
269986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
270986dffafSJohn Baldwin {
271986dffafSJohn Baldwin 
2720a473124SJohn Baldwin 	printf("\tFlags={");
273986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
2740a473124SJohn Baldwin 		printf("ENABLED");
2750a473124SJohn Baldwin 	else
2760a473124SJohn Baldwin 		printf("DISABLED");
2770a473124SJohn Baldwin 	printf("}\n");
278986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
2790a473124SJohn Baldwin }
2800a473124SJohn Baldwin 
2810a473124SJohn Baldwin static void
282986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
2830a473124SJohn Baldwin {
284986dffafSJohn Baldwin 
285986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
2860a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
287986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
2880a473124SJohn Baldwin }
2890a473124SJohn Baldwin 
2900a473124SJohn Baldwin static void
291986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
2920a473124SJohn Baldwin {
2930a473124SJohn Baldwin 
2940a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
295986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
296986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
2970a473124SJohn Baldwin 		printf("conforming");
2980a473124SJohn Baldwin 		break;
299986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3000a473124SJohn Baldwin 		printf("active-hi");
3010a473124SJohn Baldwin 		break;
302986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3030a473124SJohn Baldwin 		printf("active-lo");
3040a473124SJohn Baldwin 		break;
3050a473124SJohn Baldwin 	default:
306986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3070a473124SJohn Baldwin 		break;
3080a473124SJohn Baldwin 	}
3090a473124SJohn Baldwin 	printf(", Trigger=");
310986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
311986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3120a473124SJohn Baldwin 		printf("conforming");
3130a473124SJohn Baldwin 		break;
314986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3150a473124SJohn Baldwin 		printf("edge");
3160a473124SJohn Baldwin 		break;
317986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3180a473124SJohn Baldwin 		printf("level");
3190a473124SJohn Baldwin 		break;
3200a473124SJohn Baldwin 	default:
321986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3220a473124SJohn Baldwin 	}
3230a473124SJohn Baldwin 	printf("}\n");
3240a473124SJohn Baldwin }
3250a473124SJohn Baldwin 
3260a473124SJohn Baldwin static void
327986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
3280a473124SJohn Baldwin {
3290a473124SJohn Baldwin 
330986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
331986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
332986dffafSJohn Baldwin }
333986dffafSJohn Baldwin 
334986dffafSJohn Baldwin static void
335986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
336986dffafSJohn Baldwin {
337986dffafSJohn Baldwin 
338986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
3390a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
3400a473124SJohn Baldwin }
3410a473124SJohn Baldwin 
3420a473124SJohn Baldwin const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI",
343986dffafSJohn Baldwin 			     "Local APIC NMI", "Local APIC Override",
344986dffafSJohn Baldwin 			     "IO SAPIC", "Local SAPIC", "Platform Interrupt",
345986dffafSJohn Baldwin 			     "Local X2APIC", "Local X2APIC NMI" };
346986dffafSJohn Baldwin const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
3470a473124SJohn Baldwin 				     "Corrected Platform Error" };
3480a473124SJohn Baldwin 
3490a473124SJohn Baldwin static void
350986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
3510a473124SJohn Baldwin {
352986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
353986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
354986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
355986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
356986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
357986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
358986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
359986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
360986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
361986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
362986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
3630a473124SJohn Baldwin 
364986dffafSJohn Baldwin 	if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0]))
365986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
366a0333ad1SJohn Baldwin 	else
367986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
368986dffafSJohn Baldwin 	switch (mp->Type) {
369986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
370986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
371986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
372986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
3730a473124SJohn Baldwin 		break;
374986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
375986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
376986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
377986dffafSJohn Baldwin 		    ioapic->Address);
3780a473124SJohn Baldwin 		break;
379986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
380986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
381986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
382986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
383986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
3840a473124SJohn Baldwin 		break;
385986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
386986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
387986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
3880a473124SJohn Baldwin 		break;
389986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
390986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
391986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
392986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
3930a473124SJohn Baldwin 		break;
394986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
395986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
396945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
397986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
3980a473124SJohn Baldwin 		break;
399986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
400986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
401986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
402986dffafSJohn Baldwin 		    iosapic->Address);
4030a473124SJohn Baldwin 		break;
404986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
405986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
406986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
407986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
408986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
409986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
410986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
4110a473124SJohn Baldwin 		break;
412986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
413986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
414986dffafSJohn Baldwin 		if (isrc->Type < sizeof(platform_int_types) /
415986dffafSJohn Baldwin 		    sizeof(platform_int_types[0]))
416986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
417986dffafSJohn Baldwin 		else
418986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
419986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
420986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
421986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
422986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
423986dffafSJohn Baldwin 		break;
424986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
425986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
426986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
427986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
428986dffafSJohn Baldwin 		break;
429986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
430986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
431986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
432986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
4330a473124SJohn Baldwin 		break;
4340a473124SJohn Baldwin 	}
4350a473124SJohn Baldwin }
4360a473124SJohn Baldwin 
4370a473124SJohn Baldwin static void
438986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
4390a473124SJohn Baldwin {
440986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
4410a473124SJohn Baldwin 
442773b6454SNate Lawson 	printf(BEGIN_COMMENT);
443773b6454SNate Lawson 	acpi_print_sdt(sdp);
444986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
445986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
4460a473124SJohn Baldwin 	printf("\tFlags={");
447986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
4480a473124SJohn Baldwin 		printf("PC-AT");
4490a473124SJohn Baldwin 	printf("}\n");
450986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
4510a473124SJohn Baldwin 	printf(END_COMMENT);
4520a473124SJohn Baldwin }
4530a473124SJohn Baldwin 
4540a473124SJohn Baldwin static void
455986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
45679d7565cSPeter Wemm {
457986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
45879d7565cSPeter Wemm 
459773b6454SNate Lawson 	printf(BEGIN_COMMENT);
460773b6454SNate Lawson 	acpi_print_sdt(sdp);
461986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
462986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
46387f9f09aSTakanori Watanabe 	printf("\tADDR=");
464986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
465986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
466986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
467986dffafSJohn Baldwin 	    8);
468986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
469986dffafSJohn Baldwin 	    1 : 0);
47079d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
471986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
47279d7565cSPeter Wemm 		printf("TRUE}\n");
47379d7565cSPeter Wemm 	else
47479d7565cSPeter Wemm 		printf("FALSE}\n");
475986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
476986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
47779d7565cSPeter Wemm 	printf(END_COMMENT);
47879d7565cSPeter Wemm }
47979d7565cSPeter Wemm 
48079d7565cSPeter Wemm static void
481986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
48255d7ff9eSNate Lawson {
483986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
48455d7ff9eSNate Lawson 
48555d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
48655d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
487986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
48855d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
489986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
49055d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
491986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
492986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
493986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
494986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
49555d7ff9eSNate Lawson 	printf(END_COMMENT);
49655d7ff9eSNate Lawson }
49755d7ff9eSNate Lawson 
49855d7ff9eSNate Lawson static void
499986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
500a47e681bSScott Long {
501986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
502986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
503986dffafSJohn Baldwin 	u_int i, entries;
504a47e681bSScott Long 
505a47e681bSScott Long 	printf(BEGIN_COMMENT);
506a47e681bSScott Long 	acpi_print_sdt(sdp);
507986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
508986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
509986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
510986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
511986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
512a47e681bSScott Long 		printf("\n");
513986dffafSJohn Baldwin 		printf("\tBase Address=0x%016jx\n", alloc->Address);
514986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
515986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
516986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
517a47e681bSScott Long 	}
518a47e681bSScott Long 	printf(END_COMMENT);
519a47e681bSScott Long }
520a47e681bSScott Long 
521a47e681bSScott Long static void
522a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
523a0333ad1SJohn Baldwin     uint32_t flags)
524a0333ad1SJohn Baldwin {
525a0333ad1SJohn Baldwin 
526a0333ad1SJohn Baldwin 	printf("\tFlags={");
527a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
528a0333ad1SJohn Baldwin 		printf("ENABLED");
529a0333ad1SJohn Baldwin 	else
530a0333ad1SJohn Baldwin 		printf("DISABLED");
531a0333ad1SJohn Baldwin 	printf("}\n");
532a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
533a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
534a0333ad1SJohn Baldwin }
535a0333ad1SJohn Baldwin 
536c031c93bSTakanori Watanabe static char *
537c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
538c031c93bSTakanori Watanabe {
539c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
540c031c93bSTakanori Watanabe 	char *eventname = NULL;
541c031c93bSTakanori Watanabe 
542c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
543c031c93bSTakanori Watanabe 
544c031c93bSTakanori Watanabe 	switch(event->event_type) {
545c031c93bSTakanori Watanabe 	case PREBOOT:
546c031c93bSTakanori Watanabe 	case POST_CODE:
547c031c93bSTakanori Watanabe 	case UNUSED:
548c031c93bSTakanori Watanabe 	case NO_ACTION:
549c031c93bSTakanori Watanabe 	case SEPARATOR:
550c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
551c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
552c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
553c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
554c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
555c031c93bSTakanori Watanabe 	case COMPACT_HASH:
556c031c93bSTakanori Watanabe 	case IPL:
557c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
558c031c93bSTakanori Watanabe 	case NONHOST_CODE:
559c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
560c031c93bSTakanori Watanabe 	case NONHOST_INFO:
561c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
562c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
563c031c93bSTakanori Watanabe 		break;
564c031c93bSTakanori Watanabe 
565c031c93bSTakanori Watanabe 	case ACTION:
566c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
567c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
568c031c93bSTakanori Watanabe 		break;
569c031c93bSTakanori Watanabe 
570c031c93bSTakanori Watanabe 	case EVENT_TAG:
571c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
572c031c93bSTakanori Watanabe 		case SMBIOS:
573c031c93bSTakanori Watanabe 		case BIS_CERT:
574c031c93bSTakanori Watanabe 		case CMOS:
575c031c93bSTakanori Watanabe 		case NVRAM:
576c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
577c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
578c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
579c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
580c031c93bSTakanori Watanabe 		case ESCD:
581c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
582c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
583c031c93bSTakanori Watanabe 		case POST_CONTENTS:
584c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
585c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
586c031c93bSTakanori Watanabe 			break;
587c031c93bSTakanori Watanabe 
588c031c93bSTakanori Watanabe 		default:
589c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
590c031c93bSTakanori Watanabe 			    pc_event->event_id);
591c031c93bSTakanori Watanabe 			break;
592c031c93bSTakanori Watanabe 		}
593c031c93bSTakanori Watanabe 		break;
594c031c93bSTakanori Watanabe 
595c031c93bSTakanori Watanabe 	default:
596c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
597c031c93bSTakanori Watanabe 		break;
598c031c93bSTakanori Watanabe 	}
599c031c93bSTakanori Watanabe 
600c031c93bSTakanori Watanabe 	return eventname;
601c031c93bSTakanori Watanabe }
602c031c93bSTakanori Watanabe 
603c031c93bSTakanori Watanabe static void
604c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
605c031c93bSTakanori Watanabe {
606c031c93bSTakanori Watanabe 	int i;
607c031c93bSTakanori Watanabe 	char *eventname;
608c031c93bSTakanori Watanabe 
609c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
610c031c93bSTakanori Watanabe 
611c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
612c031c93bSTakanori Watanabe 	printf(" 0x");
613c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
614c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
615c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
616c031c93bSTakanori Watanabe 
617c031c93bSTakanori Watanabe 	free(eventname);
618c031c93bSTakanori Watanabe }
619c031c93bSTakanori Watanabe 
620c031c93bSTakanori Watanabe static void
621c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
622c031c93bSTakanori Watanabe {
623c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
624c031c93bSTakanori Watanabe 	struct TCPAevent *event;
625*977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
626c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
627c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
628c031c93bSTakanori Watanabe 
629c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
630c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
631c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
632c031c93bSTakanori Watanabe 
633c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
634c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
635c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
636c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
637c031c93bSTakanori Watanabe 		break;
638c031c93bSTakanori Watanabe 
639c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
640c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
641c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
642c031c93bSTakanori Watanabe 		break;
643c031c93bSTakanori Watanabe 
644c031c93bSTakanori Watanabe 	default:
645c031c93bSTakanori Watanabe 		printf("XXX");
646c031c93bSTakanori Watanabe 		printf(END_COMMENT);
647c031c93bSTakanori Watanabe 		return;
648c031c93bSTakanori Watanabe 	}
6490e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
650c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
651c031c93bSTakanori Watanabe 
652c031c93bSTakanori Watanabe 	if (len == 0) {
653c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
654c031c93bSTakanori Watanabe 		printf(END_COMMENT);
655c031c93bSTakanori Watanabe 		return;
656c031c93bSTakanori Watanabe 	}
657c031c93bSTakanori Watanabe 
658c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
659c031c93bSTakanori Watanabe 	vend = vaddr + len;
660c031c93bSTakanori Watanabe 
661c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
662c031c93bSTakanori Watanabe 		if (vaddr + sizeof(struct TCPAevent) >= vend)
663c031c93bSTakanori Watanabe 			break;
6640e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
665c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
666c031c93bSTakanori Watanabe 			break;
667c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
668c031c93bSTakanori Watanabe 			break;
669c031c93bSTakanori Watanabe #if 0
670c031c93bSTakanori Watanabe 		{
671c031c93bSTakanori Watanabe 		unsigned int i, j, k;
672c031c93bSTakanori Watanabe 
673c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
674c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
675c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
676c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
677c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
678c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
679c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
680c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
681c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
682c031c93bSTakanori Watanabe 				j = i + 1;
683c031c93bSTakanori Watanabe 			}
684c031c93bSTakanori Watanabe 		}
685c031c93bSTakanori Watanabe 		printf("\n"); }
686c031c93bSTakanori Watanabe #endif
687c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
688c031c93bSTakanori Watanabe 
689c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
690c031c93bSTakanori Watanabe 	}
691c031c93bSTakanori Watanabe 
692c031c93bSTakanori Watanabe 	printf(END_COMMENT);
693c031c93bSTakanori Watanabe }
694c031c93bSTakanori Watanabe 
695a0333ad1SJohn Baldwin static void
696986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
697a0333ad1SJohn Baldwin {
698a0333ad1SJohn Baldwin 
699a0333ad1SJohn Baldwin 	printf("\tFlags={");
700986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
701a0333ad1SJohn Baldwin 		printf("ENABLED");
702a0333ad1SJohn Baldwin 	else
703a0333ad1SJohn Baldwin 		printf("DISABLED");
704986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
705a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
706986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
707a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
708a0333ad1SJohn Baldwin 	printf("}\n");
709986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
710986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
711986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
712a0333ad1SJohn Baldwin }
713a0333ad1SJohn Baldwin 
714a0333ad1SJohn Baldwin const char *srat_types[] = { "CPU", "Memory", "X2APIC" };
715a0333ad1SJohn Baldwin 
716a0333ad1SJohn Baldwin static void
717986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
718a0333ad1SJohn Baldwin {
719986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
720986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
721a0333ad1SJohn Baldwin 
722986dffafSJohn Baldwin 	if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0]))
723986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
724a0333ad1SJohn Baldwin 	else
725986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
726986dffafSJohn Baldwin 	switch (srat->Type) {
727a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
728986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
729986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
730986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
731986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
732986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
733986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
734a0333ad1SJohn Baldwin 		break;
735a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
736986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
737a0333ad1SJohn Baldwin 		break;
738a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
739986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
740986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
741986dffafSJohn Baldwin 		    x2apic->Flags);
742a0333ad1SJohn Baldwin 		break;
743a0333ad1SJohn Baldwin 	}
744a0333ad1SJohn Baldwin }
745a0333ad1SJohn Baldwin 
746a0333ad1SJohn Baldwin static void
747986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
748a0333ad1SJohn Baldwin {
749986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
750a0333ad1SJohn Baldwin 
751a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
752a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
753986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
754986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
755986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
756a0333ad1SJohn Baldwin 	printf(END_COMMENT);
757a0333ad1SJohn Baldwin }
758a0333ad1SJohn Baldwin 
759a0333ad1SJohn Baldwin static void
760986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
761c62f1cccSMitsuru IWASAKI {
762773b6454SNate Lawson 	printf("  ");
763986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
764c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
765986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
766e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
767986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
768e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
769986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
770986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
771e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
772986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
773986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
774e1e9a4bfSMitsuru IWASAKI }
775e1e9a4bfSMitsuru IWASAKI 
776945137d9SNate Lawson static void
777986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
778e1e9a4bfSMitsuru IWASAKI {
779986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
780986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
781e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
782a74172abSNate Lawson 	u_long	addr;
783e1e9a4bfSMitsuru IWASAKI 
784986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
785986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
786773b6454SNate Lawson 	printf(BEGIN_COMMENT);
787773b6454SNate Lawson 	acpi_print_sdt(rsdp);
788986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
789e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
790e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
791e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
792e1e9a4bfSMitsuru IWASAKI 			printf(", ");
793a74172abSNate Lawson 		switch (addr_size) {
794a74172abSNate Lawson 		case 4:
795986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
796a74172abSNate Lawson 			break;
797a74172abSNate Lawson 		case 8:
798986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
799a74172abSNate Lawson 			break;
800a74172abSNate Lawson 		default:
801a74172abSNate Lawson 			addr = 0;
802a74172abSNate Lawson 		}
803a74172abSNate Lawson 		assert(addr != 0);
804a74172abSNate Lawson 		printf("0x%08lx", addr);
805e1e9a4bfSMitsuru IWASAKI 	}
806e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
807c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
808e1e9a4bfSMitsuru IWASAKI }
809e1e9a4bfSMitsuru IWASAKI 
8108e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
8118e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
8128e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
8138e6a8737SNate Lawson };
8148e6a8737SNate Lawson 
815945137d9SNate Lawson static void
816986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
817e1e9a4bfSMitsuru IWASAKI {
818986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
8198e6a8737SNate Lawson 	const char *pm;
820e1e9a4bfSMitsuru IWASAKI 	char	    sep;
821e1e9a4bfSMitsuru IWASAKI 
822986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
823c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
8242177d4e6SNate Lawson 	acpi_print_sdt(sdp);
825986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
826986dffafSJohn Baldwin 	       fadt->Dsdt);
827986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
828986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
8298e6a8737SNate Lawson 		pm = "Reserved";
8308e6a8737SNate Lawson 	else
831986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
832986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
833986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
834986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
835986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
836986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
837986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
838986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
839e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
840986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
841986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
842986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
843e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
844986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
845986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
846e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
847986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
848986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
849986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
850e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
851986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
852986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
853986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
854e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
855986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
856986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
857c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
858986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
859986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
860986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
8618e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
862986dffafSJohn Baldwin 		       fadt->Gpe0Block,
863986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
864986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
8658e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
866986dffafSJohn Baldwin 		       fadt->Gpe1Block,
867986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
868986dffafSJohn Baldwin 		       fadt->Gpe1Base);
869986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
870986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
87151c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
872986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
873e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
874986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
875e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
876986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
877e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
878986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
879e1e9a4bfSMitsuru IWASAKI 
8808e6a8737SNate Lawson #define PRINTFLAG(var, flag) do {			\
881986dffafSJohn Baldwin 	if ((var) & ACPI_FADT_## flag) {		\
8828e6a8737SNate Lawson 		printf("%c%s", sep, #flag); sep = ',';	\
883e1e9a4bfSMitsuru IWASAKI 	}						\
884e1e9a4bfSMitsuru IWASAKI } while (0)
885e1e9a4bfSMitsuru IWASAKI 
8868e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
8878e6a8737SNate Lawson 	sep = '{';
888986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
889986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
890986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
891986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
892986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
893986dffafSJohn Baldwin 	if (fadt->BootFlags != 0)
8944e36f5a1SNate Lawson 		printf("}");
8954e36f5a1SNate Lawson 	printf("\n");
8968e6a8737SNate Lawson 
8978e6a8737SNate Lawson 	printf("\tFlags=");
8988e6a8737SNate Lawson 	sep = '{';
899986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
900986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
901986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
902986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
903986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
904986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
905986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
906986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
907986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
908986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
909986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
910986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
911986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
912986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
913986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
914986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
915986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
916986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
917986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
918986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
919986dffafSJohn Baldwin 	if (fadt->Flags != 0)
9208e6a8737SNate Lawson 		printf("}\n");
921e1e9a4bfSMitsuru IWASAKI 
922e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
923e1e9a4bfSMitsuru IWASAKI 
924986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
9258e6a8737SNate Lawson 		printf("\tRESET_REG=");
926986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
927986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
9288e6a8737SNate Lawson 	}
929c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
930986dffafSJohn Baldwin 		printf("\tX_FACS=0x%08lx, ", (u_long)fadt->XFacs);
931986dffafSJohn Baldwin 		printf("X_DSDT=0x%08lx\n", (u_long)fadt->XDsdt);
932c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
933986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
934986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
935c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
936986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
937c08c4e81SNate Lawson 		}
938c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
939986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
940986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
941c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
942986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
943c08c4e81SNate Lawson 		}
944986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
945773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
946986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
947c08c4e81SNate Lawson 		}
948773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
949986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
950986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
951773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
952986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
953c08c4e81SNate Lawson 		}
954986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
955773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
956986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
957c08c4e81SNate Lawson 		}
958773b6454SNate Lawson 		printf("\n");
959773b6454SNate Lawson 	}
9608e6a8737SNate Lawson 
9618e6a8737SNate Lawson 	printf(END_COMMENT);
9628e6a8737SNate Lawson }
9638e6a8737SNate Lawson 
9648e6a8737SNate Lawson static void
965986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
9668e6a8737SNate Lawson {
9678e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
968986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
969986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
970986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
9718e6a8737SNate Lawson 
972773b6454SNate Lawson 	printf("\tGlobal_Lock=");
973986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
974986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
9758e6a8737SNate Lawson 			printf("PENDING,");
976986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
9778e6a8737SNate Lawson 			printf("OWNED");
9788e6a8737SNate Lawson 	}
979773b6454SNate Lawson 	printf("\n");
9808e6a8737SNate Lawson 
981773b6454SNate Lawson 	printf("\tFlags=");
982986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
9838e6a8737SNate Lawson 		printf("S4BIOS");
984773b6454SNate Lawson 	printf("\n");
9858e6a8737SNate Lawson 
986986dffafSJohn Baldwin 	if (facs->XFirmwareWakingVector != 0) {
9878e6a8737SNate Lawson 		printf("\tX_Firm_Wake_Vec=%08lx\n",
988986dffafSJohn Baldwin 		       (u_long)facs->XFirmwareWakingVector);
9898e6a8737SNate Lawson 	}
990986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
9918e6a8737SNate Lawson 
992c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
993e1e9a4bfSMitsuru IWASAKI }
994e1e9a4bfSMitsuru IWASAKI 
995945137d9SNate Lawson static void
996986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
997e1e9a4bfSMitsuru IWASAKI {
998773b6454SNate Lawson 	printf(BEGIN_COMMENT);
999773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1000773b6454SNate Lawson 	printf(END_COMMENT);
1001e1e9a4bfSMitsuru IWASAKI }
1002e1e9a4bfSMitsuru IWASAKI 
1003e1e9a4bfSMitsuru IWASAKI int
1004e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1005e1e9a4bfSMitsuru IWASAKI {
1006986dffafSJohn Baldwin 	uint8_t *bp;
1007986dffafSJohn Baldwin 	uint8_t sum;
1008e1e9a4bfSMitsuru IWASAKI 
1009e1e9a4bfSMitsuru IWASAKI 	bp = p;
1010e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1011e1e9a4bfSMitsuru IWASAKI 	while (length--)
1012e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1013e1e9a4bfSMitsuru IWASAKI 
1014e1e9a4bfSMitsuru IWASAKI 	return (sum);
1015e1e9a4bfSMitsuru IWASAKI }
1016e1e9a4bfSMitsuru IWASAKI 
1017986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1018e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1019e1e9a4bfSMitsuru IWASAKI {
1020986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1021e1e9a4bfSMitsuru IWASAKI 
1022986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1023986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1024e1e9a4bfSMitsuru IWASAKI 	return (sp);
1025e1e9a4bfSMitsuru IWASAKI }
1026e1e9a4bfSMitsuru IWASAKI 
1027945137d9SNate Lawson static void
1028986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1029e1e9a4bfSMitsuru IWASAKI {
1030c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1031a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1032986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1033986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1034986dffafSJohn Baldwin 	       rp->Revision);
1035986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1036986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1037986dffafSJohn Baldwin 		    rp->Checksum);
1038a74172abSNate Lawson 	} else {
1039a74172abSNate Lawson 		printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n",
1040986dffafSJohn Baldwin 		    (u_long)rp->XsdtPhysicalAddress, rp->Length,
1041986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1042a74172abSNate Lawson 	}
1043c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1044e1e9a4bfSMitsuru IWASAKI }
1045e1e9a4bfSMitsuru IWASAKI 
1046945137d9SNate Lawson static void
1047986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1048e1e9a4bfSMitsuru IWASAKI {
1049986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1050986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1051986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1052a74172abSNate Lawson 	vm_offset_t addr;
1053a74172abSNate Lawson 	int entries, i;
1054e1e9a4bfSMitsuru IWASAKI 
1055e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1056986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1057986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1058986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1059e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1060a74172abSNate Lawson 		switch (addr_size) {
1061a74172abSNate Lawson 		case 4:
1062986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1063a74172abSNate Lawson 			break;
1064a74172abSNate Lawson 		case 8:
1065986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1066a74172abSNate Lawson 			break;
1067a74172abSNate Lawson 		default:
1068a74172abSNate Lawson 			assert((addr = 0));
1069a74172abSNate Lawson 		}
1070a74172abSNate Lawson 
1071986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1072986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
10735cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1074986dffafSJohn Baldwin 			    sdp->Signature);
10755cf6d493SNate Lawson 			continue;
10765cf6d493SNate Lawson 		}
1077986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
10782177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1079986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1080986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1081986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
108279d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1083986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
108455d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1085986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1086a47e681bSScott Long 			acpi_handle_mcfg(sdp);
1087986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1088a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1089c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1090c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1091773b6454SNate Lawson 		else {
1092773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1093773b6454SNate Lawson 			acpi_print_sdt(sdp);
1094773b6454SNate Lawson 			printf(END_COMMENT);
1095773b6454SNate Lawson 		}
1096e1e9a4bfSMitsuru IWASAKI 	}
1097e1e9a4bfSMitsuru IWASAKI }
1098c62f1cccSMitsuru IWASAKI 
1099986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1100476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1101945137d9SNate Lawson {
1102986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1103986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1104945137d9SNate Lawson 
1105945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1106945137d9SNate Lawson 	if (!rp)
1107945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1108945137d9SNate Lawson 
1109945137d9SNate Lawson 	if (tflag)
1110945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1111986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1112986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1113986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1114986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1115945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1116a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1117a74172abSNate Lawson 	} else {
1118986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1119986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1120986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1121a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1122a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1123a74172abSNate Lawson 	}
1124945137d9SNate Lawson 	return (rsdp);
1125945137d9SNate Lawson }
1126c62f1cccSMitsuru IWASAKI 
112762c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1128bfa3f012SMarcel Moolenaar static int
1129986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1130bfa3f012SMarcel Moolenaar {
1131986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1132986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1133bfa3f012SMarcel Moolenaar 	uint8_t sum;
1134bfa3f012SMarcel Moolenaar 
113562c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1136bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1137bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1138986dffafSJohn Baldwin 		sdt.Checksum = 0;
1139986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1140986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1141986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1142f7675a56SNate Lawson 		while (ssdt != NULL) {
1143986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1144986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1145986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1146986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1147bfa3f012SMarcel Moolenaar 		}
1148986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1149986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1150bfa3f012SMarcel Moolenaar 	}
115162c7bde1SNate Lawson 
115262c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1153986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1154986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
115562c7bde1SNate Lawson 
1156b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1157f7675a56SNate Lawson 	if (rsdt != NULL) {
1158bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1159bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1160986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1161986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1162bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1163bfa3f012SMarcel Moolenaar 		}
1164bfa3f012SMarcel Moolenaar 	}
1165bfa3f012SMarcel Moolenaar 	return (0);
1166bfa3f012SMarcel Moolenaar }
1167bfa3f012SMarcel Moolenaar 
1168c62f1cccSMitsuru IWASAKI void
1169986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1170c62f1cccSMitsuru IWASAKI {
1171945137d9SNate Lawson 	int	fd;
1172945137d9SNate Lawson 	mode_t	mode;
1173945137d9SNate Lawson 
1174945137d9SNate Lawson 	assert(outfile != NULL);
1175945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1176945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1177945137d9SNate Lawson 	if (fd == -1) {
1178945137d9SNate Lawson 		perror("dsdt_save_file");
1179945137d9SNate Lawson 		return;
1180945137d9SNate Lawson 	}
1181bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1182945137d9SNate Lawson 	close(fd);
1183c62f1cccSMitsuru IWASAKI }
1184c62f1cccSMitsuru IWASAKI 
1185945137d9SNate Lawson void
1186986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1187c62f1cccSMitsuru IWASAKI {
118899065116SJung-uk Kim 	char buf[PATH_MAX], tmpstr[PATH_MAX];
118999065116SJung-uk Kim 	const char *tmpdir;
119099065116SJung-uk Kim 	char *tmpext;
1191945137d9SNate Lawson 	FILE *fp;
119299065116SJung-uk Kim 	size_t len;
119399065116SJung-uk Kim 	int fd;
1194945137d9SNate Lawson 
119599065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
119699065116SJung-uk Kim 	if (tmpdir == NULL)
119799065116SJung-uk Kim 		tmpdir = _PATH_TMP;
119899065116SJung-uk Kim 	strncpy(tmpstr, tmpdir, sizeof(tmpstr));
119999065116SJung-uk Kim 	strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(tmpdir));
120099065116SJung-uk Kim 	if (realpath(tmpstr, buf) == NULL) {
120199065116SJung-uk Kim 		perror("realpath tmp file");
120299065116SJung-uk Kim 		return;
120399065116SJung-uk Kim 	}
120499065116SJung-uk Kim 	strncpy(tmpstr, buf, sizeof(tmpstr));
120599065116SJung-uk Kim 	len = strlen(buf);
120699065116SJung-uk Kim 	tmpext = tmpstr + len;
120799065116SJung-uk Kim 	strncpy(tmpext, "XXXXXX", sizeof(tmpstr) - len);
1208945137d9SNate Lawson 	fd = mkstemp(tmpstr);
1209945137d9SNate Lawson 	if (fd < 0) {
1210945137d9SNate Lawson 		perror("iasl tmp file");
1211945137d9SNate Lawson 		return;
1212c62f1cccSMitsuru IWASAKI 	}
1213bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1214945137d9SNate Lawson 	close(fd);
1215945137d9SNate Lawson 
1216945137d9SNate Lawson 	/* Run iasl -d on the temp file */
1217945137d9SNate Lawson 	if (fork() == 0) {
1218945137d9SNate Lawson 		close(STDOUT_FILENO);
1219945137d9SNate Lawson 		if (vflag == 0)
1220945137d9SNate Lawson 			close(STDERR_FILENO);
122199065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1222945137d9SNate Lawson 		err(1, "exec");
1223c62f1cccSMitsuru IWASAKI 	}
1224c62f1cccSMitsuru IWASAKI 
1225945137d9SNate Lawson 	wait(NULL);
1226945137d9SNate Lawson 	unlink(tmpstr);
1227945137d9SNate Lawson 
1228945137d9SNate Lawson 	/* Dump iasl's output to stdout */
122999065116SJung-uk Kim 	strncpy(tmpext, "dsl", sizeof(tmpstr) - len);
123099065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
123199065116SJung-uk Kim 	unlink(tmpstr);
1232945137d9SNate Lawson 	if (fp == NULL) {
1233945137d9SNate Lawson 		perror("iasl tmp file (read)");
1234945137d9SNate Lawson 		return;
1235945137d9SNate Lawson 	}
1236945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1237945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1238945137d9SNate Lawson 	fclose(fp);
1239c62f1cccSMitsuru IWASAKI }
1240c62f1cccSMitsuru IWASAKI 
1241945137d9SNate Lawson void
1242986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1243c62f1cccSMitsuru IWASAKI {
1244945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1245c62f1cccSMitsuru IWASAKI }
1246c62f1cccSMitsuru IWASAKI 
1247bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1248986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1249986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1250c62f1cccSMitsuru IWASAKI {
1251986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1252986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1253986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1254a74172abSNate Lawson 	vm_offset_t addr;
1255a74172abSNate Lawson 	int entries, i;
1256945137d9SNate Lawson 
1257986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1258986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1259986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1260945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1261a74172abSNate Lawson 		switch (addr_size) {
1262a74172abSNate Lawson 		case 4:
1263986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1264a74172abSNate Lawson 			break;
1265a74172abSNate Lawson 		case 8:
1266986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1267a74172abSNate Lawson 			break;
1268a74172abSNate Lawson 		default:
1269a74172abSNate Lawson 			assert((addr = 0));
1270a74172abSNate Lawson 		}
1271986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1272bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1273bfa3f012SMarcel Moolenaar 			if (sdt == last)
1274bfa3f012SMarcel Moolenaar 				last = NULL;
1275bfa3f012SMarcel Moolenaar 			continue;
1276bfa3f012SMarcel Moolenaar 		}
1277986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1278a74172abSNate Lawson 			continue;
1279986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1280945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1281945137d9SNate Lawson 		return (sdt);
1282c62f1cccSMitsuru IWASAKI 	}
1283c62f1cccSMitsuru IWASAKI 
1284945137d9SNate Lawson 	return (NULL);
1285c62f1cccSMitsuru IWASAKI }
1286c62f1cccSMitsuru IWASAKI 
1287986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1288986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1289c62f1cccSMitsuru IWASAKI {
1290986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1291c62f1cccSMitsuru IWASAKI 
1292986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1293c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1294986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
12952e71eb12SNate Lawson 	else
1296986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1297986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1298945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1299945137d9SNate Lawson 	return (sdt);
1300c62f1cccSMitsuru IWASAKI }
1301