xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision bf70becee6ff4798acdcfd586a88ad38b7b17495)
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 
126e1e9a4bfSMitsuru IWASAKI static void
127e1e9a4bfSMitsuru IWASAKI acpi_print_string(char *s, size_t length)
128e1e9a4bfSMitsuru IWASAKI {
129e1e9a4bfSMitsuru IWASAKI 	int	c;
130e1e9a4bfSMitsuru IWASAKI 
131e1e9a4bfSMitsuru IWASAKI 	/* Trim trailing spaces and NULLs */
132e1e9a4bfSMitsuru IWASAKI 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
133e1e9a4bfSMitsuru IWASAKI 		length--;
134e1e9a4bfSMitsuru IWASAKI 
135e1e9a4bfSMitsuru IWASAKI 	while (length--) {
136e1e9a4bfSMitsuru IWASAKI 		c = *s++;
137e1e9a4bfSMitsuru IWASAKI 		putchar(c);
138e1e9a4bfSMitsuru IWASAKI 	}
139e1e9a4bfSMitsuru IWASAKI }
140e1e9a4bfSMitsuru IWASAKI 
141e1e9a4bfSMitsuru IWASAKI static void
142986dffafSJohn Baldwin acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
1438e6a8737SNate Lawson {
144986dffafSJohn Baldwin 	switch(gas->SpaceId) {
1458e6a8737SNate Lawson 	case ACPI_GAS_MEMORY:
146986dffafSJohn Baldwin 		printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->Address,
147986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1488e6a8737SNate Lawson 		break;
1498e6a8737SNate Lawson 	case ACPI_GAS_IO:
150986dffafSJohn Baldwin 		printf("0x%02lx:%u[%u] (IO)", (u_long)gas->Address,
151986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1528e6a8737SNate Lawson 		break;
1538e6a8737SNate Lawson 	case ACPI_GAS_PCI:
154986dffafSJohn Baldwin 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
155986dffafSJohn Baldwin 		       (uint16_t)((gas->Address >> 16) & 0xffff),
156986dffafSJohn Baldwin 		       (uint16_t)gas->Address);
1578e6a8737SNate Lawson 		break;
1588e6a8737SNate Lawson 	/* XXX How to handle these below? */
1598e6a8737SNate Lawson 	case ACPI_GAS_EMBEDDED:
160986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
161986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1628e6a8737SNate Lawson 		break;
1638e6a8737SNate Lawson 	case ACPI_GAS_SMBUS:
164986dffafSJohn Baldwin 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
165986dffafSJohn Baldwin 		       gas->BitOffset, gas->BitWidth);
1668e6a8737SNate Lawson 		break;
167986dffafSJohn Baldwin 	case ACPI_GAS_CMOS:
168986dffafSJohn Baldwin 	case ACPI_GAS_PCIBAR:
169986dffafSJohn Baldwin 	case ACPI_GAS_DATATABLE:
1708e6a8737SNate Lawson 	case ACPI_GAS_FIXED:
1718e6a8737SNate Lawson 	default:
172986dffafSJohn Baldwin 		printf("0x%08lx (?)", (u_long)gas->Address);
1738e6a8737SNate Lawson 		break;
1748e6a8737SNate Lawson 	}
1758e6a8737SNate Lawson }
1768e6a8737SNate Lawson 
177c2962974SNate Lawson /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
178c2962974SNate Lawson static int
179986dffafSJohn Baldwin acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
180e1e9a4bfSMitsuru IWASAKI {
181c2962974SNate Lawson 	int fadt_revision;
182e1e9a4bfSMitsuru IWASAKI 
183c83f0f99SNate Lawson 	/* Set the FADT revision separately from the RSDP version. */
184c83f0f99SNate Lawson 	if (addr_size == 8) {
185c83f0f99SNate Lawson 		fadt_revision = 2;
1868e6a8737SNate Lawson 
187773b6454SNate Lawson 		/*
188c83f0f99SNate Lawson 		 * A few systems (e.g., IBM T23) have an RSDP that claims
189c83f0f99SNate Lawson 		 * revision 2 but the 64 bit addresses are invalid.  If
190c83f0f99SNate Lawson 		 * revision 2 and the 32 bit address is non-zero but the
191c83f0f99SNate Lawson 		 * 32 and 64 bit versions don't match, prefer the 32 bit
192c83f0f99SNate Lawson 		 * version for all subsequent tables.
193773b6454SNate Lawson 		 */
194986dffafSJohn Baldwin 		if (fadt->Facs != 0 &&
195986dffafSJohn Baldwin 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
196c83f0f99SNate Lawson 			fadt_revision = 1;
197c2962974SNate Lawson 	} else
198c83f0f99SNate Lawson 		fadt_revision = 1;
199c2962974SNate Lawson 	return (fadt_revision);
200c83f0f99SNate Lawson }
201c2962974SNate Lawson 
202c2962974SNate Lawson static void
203986dffafSJohn Baldwin acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
204c2962974SNate Lawson {
205986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *dsdp;
206986dffafSJohn Baldwin 	ACPI_TABLE_FACS	*facs;
207986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
208c2962974SNate Lawson 	int		fadt_revision;
209c2962974SNate Lawson 
210986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
2112177d4e6SNate Lawson 	acpi_print_fadt(sdp);
212c83f0f99SNate Lawson 
213c2962974SNate Lawson 	fadt_revision = acpi_get_fadt_revision(fadt);
214c83f0f99SNate Lawson 	if (fadt_revision == 1)
215986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
216773b6454SNate Lawson 	else
217986dffafSJohn Baldwin 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
218986dffafSJohn Baldwin 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
2198e6a8737SNate Lawson 		errx(1, "FACS is corrupt");
2208e6a8737SNate Lawson 	acpi_print_facs(facs);
2218e6a8737SNate Lawson 
222c83f0f99SNate Lawson 	if (fadt_revision == 1)
223986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
224773b6454SNate Lawson 	else
225986dffafSJohn Baldwin 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
226986dffafSJohn Baldwin 	if (acpi_checksum(dsdp, dsdp->Length))
227945137d9SNate Lawson 		errx(1, "DSDT is corrupt");
228945137d9SNate Lawson 	acpi_print_dsdt(dsdp);
229c62f1cccSMitsuru IWASAKI }
230c62f1cccSMitsuru IWASAKI 
231c62f1cccSMitsuru IWASAKI static void
232986dffafSJohn Baldwin acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
233986dffafSJohn Baldwin     void (*action)(ACPI_SUBTABLE_HEADER *))
234986dffafSJohn Baldwin {
235986dffafSJohn Baldwin 	ACPI_SUBTABLE_HEADER *subtable;
236986dffafSJohn Baldwin 	char *end;
237986dffafSJohn Baldwin 
238986dffafSJohn Baldwin 	subtable = first;
239986dffafSJohn Baldwin 	end = (char *)table + table->Length;
240986dffafSJohn Baldwin 	while ((char *)subtable < end) {
241986dffafSJohn Baldwin 		printf("\n");
242986dffafSJohn Baldwin 		action(subtable);
243986dffafSJohn Baldwin 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
244986dffafSJohn Baldwin 		    subtable->Length);
245986dffafSJohn Baldwin 	}
246986dffafSJohn Baldwin }
247986dffafSJohn Baldwin 
248986dffafSJohn Baldwin static void
2490a473124SJohn Baldwin acpi_print_cpu(u_char cpu_id)
2500a473124SJohn Baldwin {
2510a473124SJohn Baldwin 
2520a473124SJohn Baldwin 	printf("\tACPI CPU=");
2530a473124SJohn Baldwin 	if (cpu_id == 0xff)
2540a473124SJohn Baldwin 		printf("ALL\n");
2550a473124SJohn Baldwin 	else
2560a473124SJohn Baldwin 		printf("%d\n", (u_int)cpu_id);
2570a473124SJohn Baldwin }
2580a473124SJohn Baldwin 
2590a473124SJohn Baldwin static void
260986dffafSJohn Baldwin acpi_print_cpu_uid(uint32_t uid, char *uid_string)
2610a473124SJohn Baldwin {
262986dffafSJohn Baldwin 
263986dffafSJohn Baldwin 	printf("\tUID=%d", uid);
264986dffafSJohn Baldwin 	if (uid_string != NULL)
265986dffafSJohn Baldwin 		printf(" (%s)", uid_string);
266986dffafSJohn Baldwin 	printf("\n");
267986dffafSJohn Baldwin }
268986dffafSJohn Baldwin 
269986dffafSJohn Baldwin static void
270986dffafSJohn Baldwin acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
271986dffafSJohn Baldwin {
272986dffafSJohn Baldwin 
2730a473124SJohn Baldwin 	printf("\tFlags={");
274986dffafSJohn Baldwin 	if (flags & ACPI_MADT_ENABLED)
2750a473124SJohn Baldwin 		printf("ENABLED");
2760a473124SJohn Baldwin 	else
2770a473124SJohn Baldwin 		printf("DISABLED");
2780a473124SJohn Baldwin 	printf("}\n");
279986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
2800a473124SJohn Baldwin }
2810a473124SJohn Baldwin 
2820a473124SJohn Baldwin static void
283986dffafSJohn Baldwin acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
2840a473124SJohn Baldwin {
285986dffafSJohn Baldwin 
286986dffafSJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
2870a473124SJohn Baldwin 	printf("\tINT BASE=%d\n", int_base);
288986dffafSJohn Baldwin 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
2890a473124SJohn Baldwin }
2900a473124SJohn Baldwin 
2910a473124SJohn Baldwin static void
292986dffafSJohn Baldwin acpi_print_mps_flags(uint16_t flags)
2930a473124SJohn Baldwin {
2940a473124SJohn Baldwin 
2950a473124SJohn Baldwin 	printf("\tFlags={Polarity=");
296986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_POLARITY_MASK) {
297986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_CONFORMS:
2980a473124SJohn Baldwin 		printf("conforming");
2990a473124SJohn Baldwin 		break;
300986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
3010a473124SJohn Baldwin 		printf("active-hi");
3020a473124SJohn Baldwin 		break;
303986dffafSJohn Baldwin 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
3040a473124SJohn Baldwin 		printf("active-lo");
3050a473124SJohn Baldwin 		break;
3060a473124SJohn Baldwin 	default:
307986dffafSJohn Baldwin 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
3080a473124SJohn Baldwin 		break;
3090a473124SJohn Baldwin 	}
3100a473124SJohn Baldwin 	printf(", Trigger=");
311986dffafSJohn Baldwin 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
312986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_CONFORMS:
3130a473124SJohn Baldwin 		printf("conforming");
3140a473124SJohn Baldwin 		break;
315986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_EDGE:
3160a473124SJohn Baldwin 		printf("edge");
3170a473124SJohn Baldwin 		break;
318986dffafSJohn Baldwin 	case ACPI_MADT_TRIGGER_LEVEL:
3190a473124SJohn Baldwin 		printf("level");
3200a473124SJohn Baldwin 		break;
3210a473124SJohn Baldwin 	default:
322986dffafSJohn Baldwin 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
3230a473124SJohn Baldwin 	}
3240a473124SJohn Baldwin 	printf("}\n");
3250a473124SJohn Baldwin }
3260a473124SJohn Baldwin 
3270a473124SJohn Baldwin static void
328986dffafSJohn Baldwin acpi_print_intr(uint32_t intr, uint16_t mps_flags)
3290a473124SJohn Baldwin {
3300a473124SJohn Baldwin 
331986dffafSJohn Baldwin 	printf("\tINTR=%d\n", intr);
332986dffafSJohn Baldwin 	acpi_print_mps_flags(mps_flags);
333986dffafSJohn Baldwin }
334986dffafSJohn Baldwin 
335986dffafSJohn Baldwin static void
336986dffafSJohn Baldwin acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
337986dffafSJohn Baldwin {
338986dffafSJohn Baldwin 
339986dffafSJohn Baldwin 	printf("\tLINT Pin=%d\n", lint);
3400a473124SJohn Baldwin 	acpi_print_mps_flags(mps_flags);
3410a473124SJohn Baldwin }
3420a473124SJohn Baldwin 
343*bf70beceSEd Schouten static const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override",
344*bf70beceSEd Schouten 				    "NMI", "Local APIC NMI",
345*bf70beceSEd Schouten 				    "Local APIC Override", "IO SAPIC",
346*bf70beceSEd Schouten 				    "Local SAPIC", "Platform Interrupt",
347986dffafSJohn Baldwin 				    "Local X2APIC", "Local X2APIC NMI" };
348*bf70beceSEd Schouten static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
3490a473124SJohn Baldwin 					    "Corrected Platform Error" };
3500a473124SJohn Baldwin 
3510a473124SJohn Baldwin static void
352986dffafSJohn Baldwin acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
3530a473124SJohn Baldwin {
354986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC *lapic;
355986dffafSJohn Baldwin 	ACPI_MADT_IO_APIC *ioapic;
356986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
357986dffafSJohn Baldwin 	ACPI_MADT_NMI_SOURCE *nmi;
358986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
359986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
360986dffafSJohn Baldwin 	ACPI_MADT_IO_SAPIC *iosapic;
361986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_SAPIC *lsapic;
362986dffafSJohn Baldwin 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
363986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC *x2apic;
364986dffafSJohn Baldwin 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
3650a473124SJohn Baldwin 
366986dffafSJohn Baldwin 	if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0]))
367986dffafSJohn Baldwin 		printf("\tType=%s\n", apic_types[mp->Type]);
368a0333ad1SJohn Baldwin 	else
369986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", mp->Type);
370986dffafSJohn Baldwin 	switch (mp->Type) {
371986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC:
372986dffafSJohn Baldwin 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
373986dffafSJohn Baldwin 		acpi_print_cpu(lapic->ProcessorId);
374986dffafSJohn Baldwin 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
3750a473124SJohn Baldwin 		break;
376986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_APIC:
377986dffafSJohn Baldwin 		ioapic = (ACPI_MADT_IO_APIC *)mp;
378986dffafSJohn Baldwin 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
379986dffafSJohn Baldwin 		    ioapic->Address);
3800a473124SJohn Baldwin 		break;
381986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
382986dffafSJohn Baldwin 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
383986dffafSJohn Baldwin 		printf("\tBUS=%d\n", (u_int)over->Bus);
384986dffafSJohn Baldwin 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
385986dffafSJohn Baldwin 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
3860a473124SJohn Baldwin 		break;
387986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_NMI_SOURCE:
388986dffafSJohn Baldwin 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
389986dffafSJohn Baldwin 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
3900a473124SJohn Baldwin 		break;
391986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
392986dffafSJohn Baldwin 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
393986dffafSJohn Baldwin 		acpi_print_cpu(lapic_nmi->ProcessorId);
394986dffafSJohn Baldwin 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
3950a473124SJohn Baldwin 		break;
396986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
397986dffafSJohn Baldwin 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
398945137d9SNate Lawson 		printf("\tLocal APIC ADDR=0x%016jx\n",
399986dffafSJohn Baldwin 		    (uintmax_t)lapic_over->Address);
4000a473124SJohn Baldwin 		break;
401986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_IO_SAPIC:
402986dffafSJohn Baldwin 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
403986dffafSJohn Baldwin 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
404986dffafSJohn Baldwin 		    iosapic->Address);
4050a473124SJohn Baldwin 		break;
406986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
407986dffafSJohn Baldwin 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
408986dffafSJohn Baldwin 		acpi_print_cpu(lsapic->ProcessorId);
409986dffafSJohn Baldwin 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
410986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
411986dffafSJohn Baldwin 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
412986dffafSJohn Baldwin 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
4130a473124SJohn Baldwin 		break;
414986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
415986dffafSJohn Baldwin 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
416986dffafSJohn Baldwin 		if (isrc->Type < sizeof(platform_int_types) /
417986dffafSJohn Baldwin 		    sizeof(platform_int_types[0]))
418986dffafSJohn Baldwin 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
419986dffafSJohn Baldwin 		else
420986dffafSJohn Baldwin 			printf("\tType=%d (unknown)\n", isrc->Type);
421986dffafSJohn Baldwin 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
422986dffafSJohn Baldwin 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
423986dffafSJohn Baldwin 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
424986dffafSJohn Baldwin 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
425986dffafSJohn Baldwin 		break;
426986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
427986dffafSJohn Baldwin 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
428986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic->Uid, NULL);
429986dffafSJohn Baldwin 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
430986dffafSJohn Baldwin 		break;
431986dffafSJohn Baldwin 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
432986dffafSJohn Baldwin 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
433986dffafSJohn Baldwin 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
434986dffafSJohn Baldwin 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
4350a473124SJohn Baldwin 		break;
4360a473124SJohn Baldwin 	}
4370a473124SJohn Baldwin }
4380a473124SJohn Baldwin 
4390a473124SJohn Baldwin static void
440986dffafSJohn Baldwin acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
4410a473124SJohn Baldwin {
442986dffafSJohn Baldwin 	ACPI_TABLE_MADT *madt;
4430a473124SJohn Baldwin 
444773b6454SNate Lawson 	printf(BEGIN_COMMENT);
445773b6454SNate Lawson 	acpi_print_sdt(sdp);
446986dffafSJohn Baldwin 	madt = (ACPI_TABLE_MADT *)sdp;
447986dffafSJohn Baldwin 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
4480a473124SJohn Baldwin 	printf("\tFlags={");
449986dffafSJohn Baldwin 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
4500a473124SJohn Baldwin 		printf("PC-AT");
4510a473124SJohn Baldwin 	printf("}\n");
452986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
4530a473124SJohn Baldwin 	printf(END_COMMENT);
4540a473124SJohn Baldwin }
4550a473124SJohn Baldwin 
4560a473124SJohn Baldwin static void
457986dffafSJohn Baldwin acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
45879d7565cSPeter Wemm {
459986dffafSJohn Baldwin 	ACPI_TABLE_HPET *hpet;
46079d7565cSPeter Wemm 
461773b6454SNate Lawson 	printf(BEGIN_COMMENT);
462773b6454SNate Lawson 	acpi_print_sdt(sdp);
463986dffafSJohn Baldwin 	hpet = (ACPI_TABLE_HPET *)sdp;
464986dffafSJohn Baldwin 	printf("\tHPET Number=%d\n", hpet->Sequence);
46587f9f09aSTakanori Watanabe 	printf("\tADDR=");
466986dffafSJohn Baldwin 	acpi_print_gas(&hpet->Address);
467986dffafSJohn Baldwin 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
468986dffafSJohn Baldwin 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
469986dffafSJohn Baldwin 	    8);
470986dffafSJohn Baldwin 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
471986dffafSJohn Baldwin 	    1 : 0);
47279d7565cSPeter Wemm 	printf("\tLegacy IRQ routing capable={");
473986dffafSJohn Baldwin 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
47479d7565cSPeter Wemm 		printf("TRUE}\n");
47579d7565cSPeter Wemm 	else
47679d7565cSPeter Wemm 		printf("FALSE}\n");
477986dffafSJohn Baldwin 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
478986dffafSJohn Baldwin 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
47979d7565cSPeter Wemm 	printf(END_COMMENT);
48079d7565cSPeter Wemm }
48179d7565cSPeter Wemm 
48279d7565cSPeter Wemm static void
483986dffafSJohn Baldwin acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
48455d7ff9eSNate Lawson {
485986dffafSJohn Baldwin 	ACPI_TABLE_ECDT *ecdt;
48655d7ff9eSNate Lawson 
48755d7ff9eSNate Lawson 	printf(BEGIN_COMMENT);
48855d7ff9eSNate Lawson 	acpi_print_sdt(sdp);
489986dffafSJohn Baldwin 	ecdt = (ACPI_TABLE_ECDT *)sdp;
49055d7ff9eSNate Lawson 	printf("\tEC_CONTROL=");
491986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Control);
49255d7ff9eSNate Lawson 	printf("\n\tEC_DATA=");
493986dffafSJohn Baldwin 	acpi_print_gas(&ecdt->Data);
494986dffafSJohn Baldwin 	printf("\n\tUID=%#x, ", ecdt->Uid);
495986dffafSJohn Baldwin 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
496986dffafSJohn Baldwin 	printf("\tEC_ID=%s\n", ecdt->Id);
49755d7ff9eSNate Lawson 	printf(END_COMMENT);
49855d7ff9eSNate Lawson }
49955d7ff9eSNate Lawson 
50055d7ff9eSNate Lawson static void
501986dffafSJohn Baldwin acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
502a47e681bSScott Long {
503986dffafSJohn Baldwin 	ACPI_TABLE_MCFG *mcfg;
504986dffafSJohn Baldwin 	ACPI_MCFG_ALLOCATION *alloc;
505986dffafSJohn Baldwin 	u_int i, entries;
506a47e681bSScott Long 
507a47e681bSScott Long 	printf(BEGIN_COMMENT);
508a47e681bSScott Long 	acpi_print_sdt(sdp);
509986dffafSJohn Baldwin 	mcfg = (ACPI_TABLE_MCFG *)sdp;
510986dffafSJohn Baldwin 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
511986dffafSJohn Baldwin 	    sizeof(ACPI_MCFG_ALLOCATION);
512986dffafSJohn Baldwin 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
513986dffafSJohn Baldwin 	for (i = 0; i < entries; i++, alloc++) {
514a47e681bSScott Long 		printf("\n");
515986dffafSJohn Baldwin 		printf("\tBase Address=0x%016jx\n", alloc->Address);
516986dffafSJohn Baldwin 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
517986dffafSJohn Baldwin 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
518986dffafSJohn Baldwin 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
519a47e681bSScott Long 	}
520a47e681bSScott Long 	printf(END_COMMENT);
521a47e681bSScott Long }
522a47e681bSScott Long 
523a47e681bSScott Long static void
52433866658SJohn Baldwin acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
52533866658SJohn Baldwin {
52633866658SJohn Baldwin 	ACPI_TABLE_SLIT *slit;
52733866658SJohn Baldwin 	UINT64 i, j;
52833866658SJohn Baldwin 
52933866658SJohn Baldwin 	printf(BEGIN_COMMENT);
53033866658SJohn Baldwin 	acpi_print_sdt(sdp);
53133866658SJohn Baldwin 	slit = (ACPI_TABLE_SLIT *)sdp;
53233866658SJohn Baldwin 	printf("\tLocality Count=%jd\n", slit->LocalityCount);
53333866658SJohn Baldwin 	printf("\n\t      ");
53433866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
53533866658SJohn Baldwin 		printf(" %3jd", i);
53633866658SJohn Baldwin 	printf("\n\t     +");
53733866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++)
53833866658SJohn Baldwin 		printf("----");
53933866658SJohn Baldwin 	printf("\n");
54033866658SJohn Baldwin 	for (i = 0; i < slit->LocalityCount; i++) {
54133866658SJohn Baldwin 		printf("\t %3jd |", i);
54233866658SJohn Baldwin 		for (j = 0; j < slit->LocalityCount; j++)
54333866658SJohn Baldwin 			printf(" %3d",
54433866658SJohn Baldwin 			    slit->Entry[i * slit->LocalityCount + j]);
54533866658SJohn Baldwin 		printf("\n");
54633866658SJohn Baldwin 	}
54733866658SJohn Baldwin 	printf(END_COMMENT);
54833866658SJohn Baldwin }
54933866658SJohn Baldwin 
55033866658SJohn Baldwin static void
551a0333ad1SJohn Baldwin acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
552a0333ad1SJohn Baldwin     uint32_t flags)
553a0333ad1SJohn Baldwin {
554a0333ad1SJohn Baldwin 
555a0333ad1SJohn Baldwin 	printf("\tFlags={");
556a0333ad1SJohn Baldwin 	if (flags & ACPI_SRAT_CPU_ENABLED)
557a0333ad1SJohn Baldwin 		printf("ENABLED");
558a0333ad1SJohn Baldwin 	else
559a0333ad1SJohn Baldwin 		printf("DISABLED");
560a0333ad1SJohn Baldwin 	printf("}\n");
561a0333ad1SJohn Baldwin 	printf("\tAPIC ID=%d\n", apic_id);
562a0333ad1SJohn Baldwin 	printf("\tProximity Domain=%d\n", proximity_domain);
563a0333ad1SJohn Baldwin }
564a0333ad1SJohn Baldwin 
565c031c93bSTakanori Watanabe static char *
566c031c93bSTakanori Watanabe acpi_tcpa_evname(struct TCPAevent *event)
567c031c93bSTakanori Watanabe {
568c031c93bSTakanori Watanabe 	struct TCPApc_event *pc_event;
569c031c93bSTakanori Watanabe 	char *eventname = NULL;
570c031c93bSTakanori Watanabe 
571c031c93bSTakanori Watanabe 	pc_event = (struct TCPApc_event *)(event + 1);
572c031c93bSTakanori Watanabe 
573c031c93bSTakanori Watanabe 	switch(event->event_type) {
574c031c93bSTakanori Watanabe 	case PREBOOT:
575c031c93bSTakanori Watanabe 	case POST_CODE:
576c031c93bSTakanori Watanabe 	case UNUSED:
577c031c93bSTakanori Watanabe 	case NO_ACTION:
578c031c93bSTakanori Watanabe 	case SEPARATOR:
579c031c93bSTakanori Watanabe 	case SCRTM_CONTENTS:
580c031c93bSTakanori Watanabe 	case SCRTM_VERSION:
581c031c93bSTakanori Watanabe 	case CPU_MICROCODE:
582c031c93bSTakanori Watanabe 	case PLATFORM_CONFIG_FLAGS:
583c031c93bSTakanori Watanabe 	case TABLE_OF_DEVICES:
584c031c93bSTakanori Watanabe 	case COMPACT_HASH:
585c031c93bSTakanori Watanabe 	case IPL:
586c031c93bSTakanori Watanabe 	case IPL_PARTITION_DATA:
587c031c93bSTakanori Watanabe 	case NONHOST_CODE:
588c031c93bSTakanori Watanabe 	case NONHOST_CONFIG:
589c031c93bSTakanori Watanabe 	case NONHOST_INFO:
590c031c93bSTakanori Watanabe 		asprintf(&eventname, "%s",
591c031c93bSTakanori Watanabe 		    tcpa_event_type_strings[event->event_type]);
592c031c93bSTakanori Watanabe 		break;
593c031c93bSTakanori Watanabe 
594c031c93bSTakanori Watanabe 	case ACTION:
595c031c93bSTakanori Watanabe 		eventname = calloc(event->event_size + 1, sizeof(char));
596c031c93bSTakanori Watanabe 		memcpy(eventname, pc_event, event->event_size);
597c031c93bSTakanori Watanabe 		break;
598c031c93bSTakanori Watanabe 
599c031c93bSTakanori Watanabe 	case EVENT_TAG:
600c031c93bSTakanori Watanabe 		switch (pc_event->event_id) {
601c031c93bSTakanori Watanabe 		case SMBIOS:
602c031c93bSTakanori Watanabe 		case BIS_CERT:
603c031c93bSTakanori Watanabe 		case CMOS:
604c031c93bSTakanori Watanabe 		case NVRAM:
605c031c93bSTakanori Watanabe 		case OPTION_ROM_EXEC:
606c031c93bSTakanori Watanabe 		case OPTION_ROM_CONFIG:
607c031c93bSTakanori Watanabe 		case S_CRTM_VERSION:
608c031c93bSTakanori Watanabe 		case POST_BIOS_ROM:
609c031c93bSTakanori Watanabe 		case ESCD:
610c031c93bSTakanori Watanabe 		case OPTION_ROM_MICROCODE:
611c031c93bSTakanori Watanabe 		case S_CRTM_CONTENTS:
612c031c93bSTakanori Watanabe 		case POST_CONTENTS:
613c031c93bSTakanori Watanabe 			asprintf(&eventname, "%s",
614c031c93bSTakanori Watanabe 			    TCPA_pcclient_strings[pc_event->event_id]);
615c031c93bSTakanori Watanabe 			break;
616c031c93bSTakanori Watanabe 
617c031c93bSTakanori Watanabe 		default:
618c031c93bSTakanori Watanabe 			asprintf(&eventname, "<unknown tag 0x%02x>",
619c031c93bSTakanori Watanabe 			    pc_event->event_id);
620c031c93bSTakanori Watanabe 			break;
621c031c93bSTakanori Watanabe 		}
622c031c93bSTakanori Watanabe 		break;
623c031c93bSTakanori Watanabe 
624c031c93bSTakanori Watanabe 	default:
625c031c93bSTakanori Watanabe 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
626c031c93bSTakanori Watanabe 		break;
627c031c93bSTakanori Watanabe 	}
628c031c93bSTakanori Watanabe 
629c031c93bSTakanori Watanabe 	return eventname;
630c031c93bSTakanori Watanabe }
631c031c93bSTakanori Watanabe 
632c031c93bSTakanori Watanabe static void
633c031c93bSTakanori Watanabe acpi_print_tcpa(struct TCPAevent *event)
634c031c93bSTakanori Watanabe {
635c031c93bSTakanori Watanabe 	int i;
636c031c93bSTakanori Watanabe 	char *eventname;
637c031c93bSTakanori Watanabe 
638c031c93bSTakanori Watanabe 	eventname = acpi_tcpa_evname(event);
639c031c93bSTakanori Watanabe 
640c031c93bSTakanori Watanabe 	printf("\t%d", event->pcr_index);
641c031c93bSTakanori Watanabe 	printf(" 0x");
642c031c93bSTakanori Watanabe 	for (i = 0; i < 20; i++)
643c031c93bSTakanori Watanabe 		printf("%02x", event->pcr_value[i]);
644c031c93bSTakanori Watanabe 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
645c031c93bSTakanori Watanabe 
646c031c93bSTakanori Watanabe 	free(eventname);
647c031c93bSTakanori Watanabe }
648c031c93bSTakanori Watanabe 
649c031c93bSTakanori Watanabe static void
650c031c93bSTakanori Watanabe acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
651c031c93bSTakanori Watanabe {
652c031c93bSTakanori Watanabe 	struct TCPAbody *tcpa;
653c031c93bSTakanori Watanabe 	struct TCPAevent *event;
654977fd9daSTakanori Watanabe 	uintmax_t len, paddr;
655c031c93bSTakanori Watanabe 	unsigned char *vaddr = NULL;
656c031c93bSTakanori Watanabe 	unsigned char *vend = NULL;
657c031c93bSTakanori Watanabe 
658c031c93bSTakanori Watanabe 	printf(BEGIN_COMMENT);
659c031c93bSTakanori Watanabe 	acpi_print_sdt(sdp);
660c031c93bSTakanori Watanabe 	tcpa = (struct TCPAbody *) sdp;
661c031c93bSTakanori Watanabe 
662c031c93bSTakanori Watanabe 	switch (tcpa->platform_class) {
663c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_CLIENT:
664c031c93bSTakanori Watanabe 		len = tcpa->client.log_max_len;
665c031c93bSTakanori Watanabe 		paddr = tcpa->client.log_start_addr;
666c031c93bSTakanori Watanabe 		break;
667c031c93bSTakanori Watanabe 
668c031c93bSTakanori Watanabe 	case ACPI_TCPA_BIOS_SERVER:
669c031c93bSTakanori Watanabe 		len = tcpa->server.log_max_len;
670c031c93bSTakanori Watanabe 		paddr = tcpa->server.log_start_addr;
671c031c93bSTakanori Watanabe 		break;
672c031c93bSTakanori Watanabe 
673c031c93bSTakanori Watanabe 	default:
674c031c93bSTakanori Watanabe 		printf("XXX");
675c031c93bSTakanori Watanabe 		printf(END_COMMENT);
676c031c93bSTakanori Watanabe 		return;
677c031c93bSTakanori Watanabe 	}
6780e1982f4STakanori Watanabe 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
679c031c93bSTakanori Watanabe 	    tcpa->platform_class, paddr, len);
680c031c93bSTakanori Watanabe 
681c031c93bSTakanori Watanabe 	if (len == 0) {
682c031c93bSTakanori Watanabe 		printf("\tEmpty TCPA table\n");
683c031c93bSTakanori Watanabe 		printf(END_COMMENT);
684c031c93bSTakanori Watanabe 		return;
685c031c93bSTakanori Watanabe 	}
6862ef23c6dSTakanori Watanabe 	if(sdp->Revision == 1){
6872ef23c6dSTakanori Watanabe 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
6882ef23c6dSTakanori Watanabe 		printf(END_COMMENT);
6892ef23c6dSTakanori Watanabe 		return;
6902ef23c6dSTakanori Watanabe 	}
691c031c93bSTakanori Watanabe 
692c031c93bSTakanori Watanabe 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
693c031c93bSTakanori Watanabe 	vend = vaddr + len;
694c031c93bSTakanori Watanabe 
695c031c93bSTakanori Watanabe 	while (vaddr != NULL) {
6962ef23c6dSTakanori Watanabe 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
6972ef23c6dSTakanori Watanabe 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
698c031c93bSTakanori Watanabe 			break;
6990e1982f4STakanori Watanabe 		event = (struct TCPAevent *)(void *)vaddr;
700c031c93bSTakanori Watanabe 		if (vaddr + event->event_size >= vend)
701c031c93bSTakanori Watanabe 			break;
7022ef23c6dSTakanori Watanabe 		if (vaddr + event->event_size < vaddr)
7032ef23c6dSTakanori Watanabe 			break;
704c031c93bSTakanori Watanabe 		if (event->event_type == 0 && event->event_size == 0)
705c031c93bSTakanori Watanabe 			break;
706c031c93bSTakanori Watanabe #if 0
707c031c93bSTakanori Watanabe 		{
708c031c93bSTakanori Watanabe 		unsigned int i, j, k;
709c031c93bSTakanori Watanabe 
710c031c93bSTakanori Watanabe 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
711c031c93bSTakanori Watanabe 		for (j = 0, i = 0; i <
712c031c93bSTakanori Watanabe 		    sizeof(struct TCPAevent) + event->event_size; i++) {
713c031c93bSTakanori Watanabe 			printf("%02x ", vaddr[i]);
714c031c93bSTakanori Watanabe 			if ((i+1) % 8 == 0) {
715c031c93bSTakanori Watanabe 				for (k = 0; k < 8; k++)
716c031c93bSTakanori Watanabe 					printf("%c", isprint(vaddr[j+k]) ?
717c031c93bSTakanori Watanabe 					    vaddr[j+k] : '.');
718c031c93bSTakanori Watanabe 				printf("\n\t\t%p ", &vaddr[i + 1]);
719c031c93bSTakanori Watanabe 				j = i + 1;
720c031c93bSTakanori Watanabe 			}
721c031c93bSTakanori Watanabe 		}
722c031c93bSTakanori Watanabe 		printf("\n"); }
723c031c93bSTakanori Watanabe #endif
724c031c93bSTakanori Watanabe 		acpi_print_tcpa(event);
725c031c93bSTakanori Watanabe 
726c031c93bSTakanori Watanabe 		vaddr += sizeof(struct TCPAevent) + event->event_size;
727c031c93bSTakanori Watanabe 	}
728c031c93bSTakanori Watanabe 
729c031c93bSTakanori Watanabe 	printf(END_COMMENT);
730c031c93bSTakanori Watanabe }
731c031c93bSTakanori Watanabe 
732a0333ad1SJohn Baldwin static void
733986dffafSJohn Baldwin acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
734a0333ad1SJohn Baldwin {
735a0333ad1SJohn Baldwin 
736a0333ad1SJohn Baldwin 	printf("\tFlags={");
737986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
738a0333ad1SJohn Baldwin 		printf("ENABLED");
739a0333ad1SJohn Baldwin 	else
740a0333ad1SJohn Baldwin 		printf("DISABLED");
741986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
742a0333ad1SJohn Baldwin 		printf(",HOT_PLUGGABLE");
743986dffafSJohn Baldwin 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
744a0333ad1SJohn Baldwin 		printf(",NON_VOLATILE");
745a0333ad1SJohn Baldwin 	printf("}\n");
746986dffafSJohn Baldwin 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
747986dffafSJohn Baldwin 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
748986dffafSJohn Baldwin 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
749a0333ad1SJohn Baldwin }
750a0333ad1SJohn Baldwin 
751*bf70beceSEd Schouten static const char *srat_types[] = { "CPU", "Memory", "X2APIC" };
752a0333ad1SJohn Baldwin 
753a0333ad1SJohn Baldwin static void
754986dffafSJohn Baldwin acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
755a0333ad1SJohn Baldwin {
756986dffafSJohn Baldwin 	ACPI_SRAT_CPU_AFFINITY *cpu;
757986dffafSJohn Baldwin 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
758a0333ad1SJohn Baldwin 
759986dffafSJohn Baldwin 	if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0]))
760986dffafSJohn Baldwin 		printf("\tType=%s\n", srat_types[srat->Type]);
761a0333ad1SJohn Baldwin 	else
762986dffafSJohn Baldwin 		printf("\tType=%d (unknown)\n", srat->Type);
763986dffafSJohn Baldwin 	switch (srat->Type) {
764a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
765986dffafSJohn Baldwin 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
766986dffafSJohn Baldwin 		acpi_print_srat_cpu(cpu->ApicId,
767986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[2] << 24 |
768986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[1] << 16 |
769986dffafSJohn Baldwin 		    cpu->ProximityDomainHi[0] << 0 |
770986dffafSJohn Baldwin 		    cpu->ProximityDomainLo, cpu->Flags);
771a0333ad1SJohn Baldwin 		break;
772a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
773986dffafSJohn Baldwin 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
774a0333ad1SJohn Baldwin 		break;
775a0333ad1SJohn Baldwin 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
776986dffafSJohn Baldwin 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
777986dffafSJohn Baldwin 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
778986dffafSJohn Baldwin 		    x2apic->Flags);
779a0333ad1SJohn Baldwin 		break;
780a0333ad1SJohn Baldwin 	}
781a0333ad1SJohn Baldwin }
782a0333ad1SJohn Baldwin 
783a0333ad1SJohn Baldwin static void
784986dffafSJohn Baldwin acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
785a0333ad1SJohn Baldwin {
786986dffafSJohn Baldwin 	ACPI_TABLE_SRAT *srat;
787a0333ad1SJohn Baldwin 
788a0333ad1SJohn Baldwin 	printf(BEGIN_COMMENT);
789a0333ad1SJohn Baldwin 	acpi_print_sdt(sdp);
790986dffafSJohn Baldwin 	srat = (ACPI_TABLE_SRAT *)sdp;
791986dffafSJohn Baldwin 	printf("\tTable Revision=%d\n", srat->TableRevision);
792986dffafSJohn Baldwin 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
793a0333ad1SJohn Baldwin 	printf(END_COMMENT);
794a0333ad1SJohn Baldwin }
795a0333ad1SJohn Baldwin 
796a0333ad1SJohn Baldwin static void
797986dffafSJohn Baldwin acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
798c62f1cccSMitsuru IWASAKI {
799773b6454SNate Lawson 	printf("  ");
800986dffafSJohn Baldwin 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
801c62f1cccSMitsuru IWASAKI 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
802986dffafSJohn Baldwin 	       sdp->Length, sdp->Revision, sdp->Checksum);
803e1e9a4bfSMitsuru IWASAKI 	printf("\tOEMID=");
804986dffafSJohn Baldwin 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
805e1e9a4bfSMitsuru IWASAKI 	printf(", OEM Table ID=");
806986dffafSJohn Baldwin 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
807986dffafSJohn Baldwin 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
808e1e9a4bfSMitsuru IWASAKI 	printf("\tCreator ID=");
809986dffafSJohn Baldwin 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
810986dffafSJohn Baldwin 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
811e1e9a4bfSMitsuru IWASAKI }
812e1e9a4bfSMitsuru IWASAKI 
813945137d9SNate Lawson static void
814986dffafSJohn Baldwin acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
815e1e9a4bfSMitsuru IWASAKI {
816986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
817986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
818e1e9a4bfSMitsuru IWASAKI 	int	i, entries;
819a74172abSNate Lawson 	u_long	addr;
820e1e9a4bfSMitsuru IWASAKI 
821986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
822986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
823773b6454SNate Lawson 	printf(BEGIN_COMMENT);
824773b6454SNate Lawson 	acpi_print_sdt(rsdp);
825986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
826e1e9a4bfSMitsuru IWASAKI 	printf("\tEntries={ ");
827e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
828e1e9a4bfSMitsuru IWASAKI 		if (i > 0)
829e1e9a4bfSMitsuru IWASAKI 			printf(", ");
830a74172abSNate Lawson 		switch (addr_size) {
831a74172abSNate Lawson 		case 4:
832986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
833a74172abSNate Lawson 			break;
834a74172abSNate Lawson 		case 8:
835986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
836a74172abSNate Lawson 			break;
837a74172abSNate Lawson 		default:
838a74172abSNate Lawson 			addr = 0;
839a74172abSNate Lawson 		}
840a74172abSNate Lawson 		assert(addr != 0);
841a74172abSNate Lawson 		printf("0x%08lx", addr);
842e1e9a4bfSMitsuru IWASAKI 	}
843e1e9a4bfSMitsuru IWASAKI 	printf(" }\n");
844c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
845e1e9a4bfSMitsuru IWASAKI }
846e1e9a4bfSMitsuru IWASAKI 
8478e6a8737SNate Lawson static const char *acpi_pm_profiles[] = {
8488e6a8737SNate Lawson 	"Unspecified", "Desktop", "Mobile", "Workstation",
8498e6a8737SNate Lawson 	"Enterprise Server", "SOHO Server", "Appliance PC"
8508e6a8737SNate Lawson };
8518e6a8737SNate Lawson 
852945137d9SNate Lawson static void
853986dffafSJohn Baldwin acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
854e1e9a4bfSMitsuru IWASAKI {
855986dffafSJohn Baldwin 	ACPI_TABLE_FADT *fadt;
8568e6a8737SNate Lawson 	const char *pm;
857e1e9a4bfSMitsuru IWASAKI 	char	    sep;
858e1e9a4bfSMitsuru IWASAKI 
859986dffafSJohn Baldwin 	fadt = (ACPI_TABLE_FADT *)sdp;
860c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
8612177d4e6SNate Lawson 	acpi_print_sdt(sdp);
862986dffafSJohn Baldwin 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
863986dffafSJohn Baldwin 	       fadt->Dsdt);
864986dffafSJohn Baldwin 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
865986dffafSJohn Baldwin 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
8668e6a8737SNate Lawson 		pm = "Reserved";
8678e6a8737SNate Lawson 	else
868986dffafSJohn Baldwin 		pm = acpi_pm_profiles[fadt->PreferredProfile];
869986dffafSJohn Baldwin 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
870986dffafSJohn Baldwin 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
871986dffafSJohn Baldwin 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
872986dffafSJohn Baldwin 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
873986dffafSJohn Baldwin 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
874986dffafSJohn Baldwin 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
875986dffafSJohn Baldwin 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
876e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
877986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock,
878986dffafSJohn Baldwin 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
879986dffafSJohn Baldwin 	if (fadt->Pm1bEventBlock != 0)
880e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
881986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock,
882986dffafSJohn Baldwin 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
883e1e9a4bfSMitsuru IWASAKI 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
884986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock,
885986dffafSJohn Baldwin 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
886986dffafSJohn Baldwin 	if (fadt->Pm1bControlBlock != 0)
887e1e9a4bfSMitsuru IWASAKI 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
888986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock,
889986dffafSJohn Baldwin 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
890986dffafSJohn Baldwin 	if (fadt->Pm2ControlBlock != 0)
891e1e9a4bfSMitsuru IWASAKI 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
892986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock,
893986dffafSJohn Baldwin 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
894c08c4e81SNate Lawson 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
895986dffafSJohn Baldwin 	       fadt->PmTimerBlock,
896986dffafSJohn Baldwin 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
897986dffafSJohn Baldwin 	if (fadt->Gpe0Block != 0)
8988e6a8737SNate Lawson 		printf("\tGPE0_BLK=0x%x-0x%x\n",
899986dffafSJohn Baldwin 		       fadt->Gpe0Block,
900986dffafSJohn Baldwin 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
901986dffafSJohn Baldwin 	if (fadt->Gpe1Block != 0)
9028e6a8737SNate Lawson 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
903986dffafSJohn Baldwin 		       fadt->Gpe1Block,
904986dffafSJohn Baldwin 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
905986dffafSJohn Baldwin 		       fadt->Gpe1Base);
906986dffafSJohn Baldwin 	if (fadt->CstControl != 0)
907986dffafSJohn Baldwin 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
90851c1824fSNate Lawson 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
909986dffafSJohn Baldwin 	       fadt->C2Latency, fadt->C3Latency);
910e1e9a4bfSMitsuru IWASAKI 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
911986dffafSJohn Baldwin 	       fadt->FlushSize, fadt->FlushStride);
912e1e9a4bfSMitsuru IWASAKI 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
913986dffafSJohn Baldwin 	       fadt->DutyOffset, fadt->DutyWidth);
914e1e9a4bfSMitsuru IWASAKI 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
915986dffafSJohn Baldwin 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
916e1e9a4bfSMitsuru IWASAKI 
9178e6a8737SNate Lawson #define PRINTFLAG(var, flag) do {			\
918986dffafSJohn Baldwin 	if ((var) & ACPI_FADT_## flag) {		\
9198e6a8737SNate Lawson 		printf("%c%s", sep, #flag); sep = ',';	\
920e1e9a4bfSMitsuru IWASAKI 	}						\
921e1e9a4bfSMitsuru IWASAKI } while (0)
922e1e9a4bfSMitsuru IWASAKI 
9238e6a8737SNate Lawson 	printf("\tIAPC_BOOT_ARCH=");
9248e6a8737SNate Lawson 	sep = '{';
925986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
926986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, 8042);
927986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_VGA);
928986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_MSI);
929986dffafSJohn Baldwin 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
930986dffafSJohn Baldwin 	if (fadt->BootFlags != 0)
9314e36f5a1SNate Lawson 		printf("}");
9324e36f5a1SNate Lawson 	printf("\n");
9338e6a8737SNate Lawson 
9348e6a8737SNate Lawson 	printf("\tFlags=");
9358e6a8737SNate Lawson 	sep = '{';
936986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD);
937986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
938986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
939986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
940986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
941986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
942986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, FIXED_RTC);
943986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
944986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
945986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
946986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
947986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SEALED_CASE);
948986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, HEADLESS);
949986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
950986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
951986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
952986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
953986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
954986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
955986dffafSJohn Baldwin 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
956986dffafSJohn Baldwin 	if (fadt->Flags != 0)
9578e6a8737SNate Lawson 		printf("}\n");
958e1e9a4bfSMitsuru IWASAKI 
959e1e9a4bfSMitsuru IWASAKI #undef PRINTFLAG
960e1e9a4bfSMitsuru IWASAKI 
961986dffafSJohn Baldwin 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
9628e6a8737SNate Lawson 		printf("\tRESET_REG=");
963986dffafSJohn Baldwin 		acpi_print_gas(&fadt->ResetRegister);
964986dffafSJohn Baldwin 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
9658e6a8737SNate Lawson 	}
966c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) > 1) {
967986dffafSJohn Baldwin 		printf("\tX_FACS=0x%08lx, ", (u_long)fadt->XFacs);
968986dffafSJohn Baldwin 		printf("X_DSDT=0x%08lx\n", (u_long)fadt->XDsdt);
969c08c4e81SNate Lawson 		printf("\tX_PM1a_EVT_BLK=");
970986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aEventBlock);
971986dffafSJohn Baldwin 		if (fadt->XPm1bEventBlock.Address != 0) {
972c08c4e81SNate Lawson 			printf("\n\tX_PM1b_EVT_BLK=");
973986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bEventBlock);
974c08c4e81SNate Lawson 		}
975c08c4e81SNate Lawson 		printf("\n\tX_PM1a_CNT_BLK=");
976986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPm1aControlBlock);
977986dffafSJohn Baldwin 		if (fadt->XPm1bControlBlock.Address != 0) {
978c08c4e81SNate Lawson 			printf("\n\tX_PM1b_CNT_BLK=");
979986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm1bControlBlock);
980c08c4e81SNate Lawson 		}
981986dffafSJohn Baldwin 		if (fadt->XPm2ControlBlock.Address != 0) {
982773b6454SNate Lawson 			printf("\n\tX_PM2_CNT_BLK=");
983986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XPm2ControlBlock);
984c08c4e81SNate Lawson 		}
985773b6454SNate Lawson 		printf("\n\tX_PM_TMR_BLK=");
986986dffafSJohn Baldwin 		acpi_print_gas(&fadt->XPmTimerBlock);
987986dffafSJohn Baldwin 		if (fadt->XGpe0Block.Address != 0) {
988773b6454SNate Lawson 			printf("\n\tX_GPE0_BLK=");
989986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe0Block);
990c08c4e81SNate Lawson 		}
991986dffafSJohn Baldwin 		if (fadt->XGpe1Block.Address != 0) {
992773b6454SNate Lawson 			printf("\n\tX_GPE1_BLK=");
993986dffafSJohn Baldwin 			acpi_print_gas(&fadt->XGpe1Block);
994c08c4e81SNate Lawson 		}
995773b6454SNate Lawson 		printf("\n");
996773b6454SNate Lawson 	}
9978e6a8737SNate Lawson 
9988e6a8737SNate Lawson 	printf(END_COMMENT);
9998e6a8737SNate Lawson }
10008e6a8737SNate Lawson 
10018e6a8737SNate Lawson static void
1002986dffafSJohn Baldwin acpi_print_facs(ACPI_TABLE_FACS *facs)
10038e6a8737SNate Lawson {
10048e6a8737SNate Lawson 	printf(BEGIN_COMMENT);
1005986dffafSJohn Baldwin 	printf("  FACS:\tLength=%u, ", facs->Length);
1006986dffafSJohn Baldwin 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1007986dffafSJohn Baldwin 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
10088e6a8737SNate Lawson 
1009773b6454SNate Lawson 	printf("\tGlobal_Lock=");
1010986dffafSJohn Baldwin 	if (facs->GlobalLock != 0) {
1011986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
10128e6a8737SNate Lawson 			printf("PENDING,");
1013986dffafSJohn Baldwin 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
10148e6a8737SNate Lawson 			printf("OWNED");
10158e6a8737SNate Lawson 	}
1016773b6454SNate Lawson 	printf("\n");
10178e6a8737SNate Lawson 
1018773b6454SNate Lawson 	printf("\tFlags=");
1019986dffafSJohn Baldwin 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
10208e6a8737SNate Lawson 		printf("S4BIOS");
1021773b6454SNate Lawson 	printf("\n");
10228e6a8737SNate Lawson 
1023986dffafSJohn Baldwin 	if (facs->XFirmwareWakingVector != 0) {
10248e6a8737SNate Lawson 		printf("\tX_Firm_Wake_Vec=%08lx\n",
1025986dffafSJohn Baldwin 		       (u_long)facs->XFirmwareWakingVector);
10268e6a8737SNate Lawson 	}
1027986dffafSJohn Baldwin 	printf("\tVersion=%u\n", facs->Version);
10288e6a8737SNate Lawson 
1029c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1030e1e9a4bfSMitsuru IWASAKI }
1031e1e9a4bfSMitsuru IWASAKI 
1032945137d9SNate Lawson static void
1033986dffafSJohn Baldwin acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1034e1e9a4bfSMitsuru IWASAKI {
1035773b6454SNate Lawson 	printf(BEGIN_COMMENT);
1036773b6454SNate Lawson 	acpi_print_sdt(dsdp);
1037773b6454SNate Lawson 	printf(END_COMMENT);
1038e1e9a4bfSMitsuru IWASAKI }
1039e1e9a4bfSMitsuru IWASAKI 
1040e1e9a4bfSMitsuru IWASAKI int
1041e1e9a4bfSMitsuru IWASAKI acpi_checksum(void *p, size_t length)
1042e1e9a4bfSMitsuru IWASAKI {
1043986dffafSJohn Baldwin 	uint8_t *bp;
1044986dffafSJohn Baldwin 	uint8_t sum;
1045e1e9a4bfSMitsuru IWASAKI 
1046e1e9a4bfSMitsuru IWASAKI 	bp = p;
1047e1e9a4bfSMitsuru IWASAKI 	sum = 0;
1048e1e9a4bfSMitsuru IWASAKI 	while (length--)
1049e1e9a4bfSMitsuru IWASAKI 		sum += *bp++;
1050e1e9a4bfSMitsuru IWASAKI 
1051e1e9a4bfSMitsuru IWASAKI 	return (sum);
1052e1e9a4bfSMitsuru IWASAKI }
1053e1e9a4bfSMitsuru IWASAKI 
1054986dffafSJohn Baldwin static ACPI_TABLE_HEADER *
1055e1e9a4bfSMitsuru IWASAKI acpi_map_sdt(vm_offset_t pa)
1056e1e9a4bfSMitsuru IWASAKI {
1057986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sp;
1058e1e9a4bfSMitsuru IWASAKI 
1059986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1060986dffafSJohn Baldwin 	sp = acpi_map_physical(pa, sp->Length);
1061e1e9a4bfSMitsuru IWASAKI 	return (sp);
1062e1e9a4bfSMitsuru IWASAKI }
1063e1e9a4bfSMitsuru IWASAKI 
1064945137d9SNate Lawson static void
1065986dffafSJohn Baldwin acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1066e1e9a4bfSMitsuru IWASAKI {
1067c62f1cccSMitsuru IWASAKI 	printf(BEGIN_COMMENT);
1068a74172abSNate Lawson 	printf("  RSD PTR: OEM=");
1069986dffafSJohn Baldwin 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1070986dffafSJohn Baldwin 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1071986dffafSJohn Baldwin 	       rp->Revision);
1072986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1073986dffafSJohn Baldwin 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1074986dffafSJohn Baldwin 		    rp->Checksum);
1075a74172abSNate Lawson 	} else {
1076a74172abSNate Lawson 		printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n",
1077986dffafSJohn Baldwin 		    (u_long)rp->XsdtPhysicalAddress, rp->Length,
1078986dffafSJohn Baldwin 		    rp->ExtendedChecksum);
1079a74172abSNate Lawson 	}
1080c62f1cccSMitsuru IWASAKI 	printf(END_COMMENT);
1081e1e9a4bfSMitsuru IWASAKI }
1082e1e9a4bfSMitsuru IWASAKI 
1083945137d9SNate Lawson static void
1084986dffafSJohn Baldwin acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1085e1e9a4bfSMitsuru IWASAKI {
1086986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdp;
1087986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1088986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1089a74172abSNate Lawson 	vm_offset_t addr;
1090a74172abSNate Lawson 	int entries, i;
1091e1e9a4bfSMitsuru IWASAKI 
1092e1e9a4bfSMitsuru IWASAKI 	acpi_print_rsdt(rsdp);
1093986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1094986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1095986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1096e1e9a4bfSMitsuru IWASAKI 	for (i = 0; i < entries; i++) {
1097a74172abSNate Lawson 		switch (addr_size) {
1098a74172abSNate Lawson 		case 4:
1099986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1100a74172abSNate Lawson 			break;
1101a74172abSNate Lawson 		case 8:
1102986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1103a74172abSNate Lawson 			break;
1104a74172abSNate Lawson 		default:
1105a74172abSNate Lawson 			assert((addr = 0));
1106a74172abSNate Lawson 		}
1107a74172abSNate Lawson 
1108986dffafSJohn Baldwin 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1109986dffafSJohn Baldwin 		if (acpi_checksum(sdp, sdp->Length)) {
11105cf6d493SNate Lawson 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1111986dffafSJohn Baldwin 			    sdp->Signature);
11125cf6d493SNate Lawson 			continue;
11135cf6d493SNate Lawson 		}
1114986dffafSJohn Baldwin 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
11152177d4e6SNate Lawson 			acpi_handle_fadt(sdp);
1116986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1117986dffafSJohn Baldwin 			acpi_handle_madt(sdp);
1118986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
111979d7565cSPeter Wemm 			acpi_handle_hpet(sdp);
1120986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
112155d7ff9eSNate Lawson 			acpi_handle_ecdt(sdp);
1122986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1123a47e681bSScott Long 			acpi_handle_mcfg(sdp);
112433866658SJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
112533866658SJohn Baldwin 			acpi_handle_slit(sdp);
1126986dffafSJohn Baldwin 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1127a0333ad1SJohn Baldwin 			acpi_handle_srat(sdp);
1128c031c93bSTakanori Watanabe 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1129c031c93bSTakanori Watanabe 			acpi_handle_tcpa(sdp);
1130773b6454SNate Lawson 		else {
1131773b6454SNate Lawson 			printf(BEGIN_COMMENT);
1132773b6454SNate Lawson 			acpi_print_sdt(sdp);
1133773b6454SNate Lawson 			printf(END_COMMENT);
1134773b6454SNate Lawson 		}
1135e1e9a4bfSMitsuru IWASAKI 	}
1136e1e9a4bfSMitsuru IWASAKI }
1137c62f1cccSMitsuru IWASAKI 
1138986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1139476daaecSDag-Erling Smørgrav sdt_load_devmem(void)
1140945137d9SNate Lawson {
1141986dffafSJohn Baldwin 	ACPI_TABLE_RSDP *rp;
1142986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *rsdp;
1143945137d9SNate Lawson 
1144945137d9SNate Lawson 	rp = acpi_find_rsd_ptr();
1145945137d9SNate Lawson 	if (!rp)
1146945137d9SNate Lawson 		errx(1, "Can't find ACPI information");
1147945137d9SNate Lawson 
1148945137d9SNate Lawson 	if (tflag)
1149945137d9SNate Lawson 		acpi_print_rsd_ptr(rp);
1150986dffafSJohn Baldwin 	if (rp->Revision < 2) {
1151986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1152986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1153986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1154945137d9SNate Lawson 			errx(1, "RSDT is corrupted");
1155a74172abSNate Lawson 		addr_size = sizeof(uint32_t);
1156a74172abSNate Lawson 	} else {
1157986dffafSJohn Baldwin 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1158986dffafSJohn Baldwin 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1159986dffafSJohn Baldwin 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1160a74172abSNate Lawson 			errx(1, "XSDT is corrupted");
1161a74172abSNate Lawson 		addr_size = sizeof(uint64_t);
1162a74172abSNate Lawson 	}
1163945137d9SNate Lawson 	return (rsdp);
1164945137d9SNate Lawson }
1165c62f1cccSMitsuru IWASAKI 
116662c7bde1SNate Lawson /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1167bfa3f012SMarcel Moolenaar static int
1168986dffafSJohn Baldwin write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1169bfa3f012SMarcel Moolenaar {
1170986dffafSJohn Baldwin 	ACPI_TABLE_HEADER sdt;
1171986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *ssdt;
1172bfa3f012SMarcel Moolenaar 	uint8_t sum;
1173bfa3f012SMarcel Moolenaar 
117462c7bde1SNate Lawson 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1175bfa3f012SMarcel Moolenaar 	sdt = *dsdt;
1176bfa3f012SMarcel Moolenaar 	if (rsdt != NULL) {
1177986dffafSJohn Baldwin 		sdt.Checksum = 0;
1178986dffafSJohn Baldwin 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1179986dffafSJohn Baldwin 		    sizeof(ACPI_TABLE_HEADER));
1180986dffafSJohn Baldwin 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1181f7675a56SNate Lawson 		while (ssdt != NULL) {
1182986dffafSJohn Baldwin 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1183986dffafSJohn Baldwin 			sum += acpi_checksum(ssdt + 1,
1184986dffafSJohn Baldwin 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1185986dffafSJohn Baldwin 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1186bfa3f012SMarcel Moolenaar 		}
1187986dffafSJohn Baldwin 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1188986dffafSJohn Baldwin 		sdt.Checksum -= sum;
1189bfa3f012SMarcel Moolenaar 	}
119062c7bde1SNate Lawson 
119162c7bde1SNate Lawson 	/* Write out the DSDT header and body. */
1192986dffafSJohn Baldwin 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1193986dffafSJohn Baldwin 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
119462c7bde1SNate Lawson 
1195b64e1b67SNate Lawson 	/* Write out any SSDTs (if present.) */
1196f7675a56SNate Lawson 	if (rsdt != NULL) {
1197bfa3f012SMarcel Moolenaar 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1198bfa3f012SMarcel Moolenaar 		while (ssdt != NULL) {
1199986dffafSJohn Baldwin 			write(fd, ssdt + 1, ssdt->Length -
1200986dffafSJohn Baldwin 			    sizeof(ACPI_TABLE_HEADER));
1201bfa3f012SMarcel Moolenaar 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1202bfa3f012SMarcel Moolenaar 		}
1203bfa3f012SMarcel Moolenaar 	}
1204bfa3f012SMarcel Moolenaar 	return (0);
1205bfa3f012SMarcel Moolenaar }
1206bfa3f012SMarcel Moolenaar 
1207c62f1cccSMitsuru IWASAKI void
1208986dffafSJohn Baldwin dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1209c62f1cccSMitsuru IWASAKI {
1210945137d9SNate Lawson 	int	fd;
1211945137d9SNate Lawson 	mode_t	mode;
1212945137d9SNate Lawson 
1213945137d9SNate Lawson 	assert(outfile != NULL);
1214945137d9SNate Lawson 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1215945137d9SNate Lawson 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1216945137d9SNate Lawson 	if (fd == -1) {
1217945137d9SNate Lawson 		perror("dsdt_save_file");
1218945137d9SNate Lawson 		return;
1219945137d9SNate Lawson 	}
1220bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1221945137d9SNate Lawson 	close(fd);
1222c62f1cccSMitsuru IWASAKI }
1223c62f1cccSMitsuru IWASAKI 
1224945137d9SNate Lawson void
1225986dffafSJohn Baldwin aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1226c62f1cccSMitsuru IWASAKI {
122799065116SJung-uk Kim 	char buf[PATH_MAX], tmpstr[PATH_MAX];
122899065116SJung-uk Kim 	const char *tmpdir;
122999065116SJung-uk Kim 	char *tmpext;
1230945137d9SNate Lawson 	FILE *fp;
123199065116SJung-uk Kim 	size_t len;
123299065116SJung-uk Kim 	int fd;
1233945137d9SNate Lawson 
123499065116SJung-uk Kim 	tmpdir = getenv("TMPDIR");
123599065116SJung-uk Kim 	if (tmpdir == NULL)
123699065116SJung-uk Kim 		tmpdir = _PATH_TMP;
123799065116SJung-uk Kim 	strncpy(tmpstr, tmpdir, sizeof(tmpstr));
123899065116SJung-uk Kim 	if (realpath(tmpstr, buf) == NULL) {
1239d6a6e590SJung-uk Kim 		perror("realpath tmp dir");
124099065116SJung-uk Kim 		return;
124199065116SJung-uk Kim 	}
124299065116SJung-uk Kim 	strncpy(tmpstr, buf, sizeof(tmpstr));
1243d6a6e590SJung-uk Kim 	strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(buf));
1244d6a6e590SJung-uk Kim 	len = strlen(tmpstr);
124599065116SJung-uk Kim 	tmpext = tmpstr + len;
124699065116SJung-uk Kim 	strncpy(tmpext, "XXXXXX", sizeof(tmpstr) - len);
1247945137d9SNate Lawson 	fd = mkstemp(tmpstr);
1248945137d9SNate Lawson 	if (fd < 0) {
1249945137d9SNate Lawson 		perror("iasl tmp file");
1250945137d9SNate Lawson 		return;
1251c62f1cccSMitsuru IWASAKI 	}
1252bfa3f012SMarcel Moolenaar 	write_dsdt(fd, rsdt, dsdp);
1253945137d9SNate Lawson 	close(fd);
1254945137d9SNate Lawson 
1255945137d9SNate Lawson 	/* Run iasl -d on the temp file */
1256945137d9SNate Lawson 	if (fork() == 0) {
1257945137d9SNate Lawson 		close(STDOUT_FILENO);
1258945137d9SNate Lawson 		if (vflag == 0)
1259945137d9SNate Lawson 			close(STDERR_FILENO);
126099065116SJung-uk Kim 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1261945137d9SNate Lawson 		err(1, "exec");
1262c62f1cccSMitsuru IWASAKI 	}
1263c62f1cccSMitsuru IWASAKI 
1264945137d9SNate Lawson 	wait(NULL);
1265945137d9SNate Lawson 	unlink(tmpstr);
1266945137d9SNate Lawson 
1267945137d9SNate Lawson 	/* Dump iasl's output to stdout */
126899065116SJung-uk Kim 	strncpy(tmpext, "dsl", sizeof(tmpstr) - len);
126999065116SJung-uk Kim 	fp = fopen(tmpstr, "r");
127099065116SJung-uk Kim 	unlink(tmpstr);
1271945137d9SNate Lawson 	if (fp == NULL) {
1272945137d9SNate Lawson 		perror("iasl tmp file (read)");
1273945137d9SNate Lawson 		return;
1274945137d9SNate Lawson 	}
1275945137d9SNate Lawson 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1276945137d9SNate Lawson 		fwrite(buf, 1, len, stdout);
1277945137d9SNate Lawson 	fclose(fp);
1278c62f1cccSMitsuru IWASAKI }
1279c62f1cccSMitsuru IWASAKI 
1280945137d9SNate Lawson void
1281986dffafSJohn Baldwin sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1282c62f1cccSMitsuru IWASAKI {
1283945137d9SNate Lawson 	acpi_handle_rsdt(rsdp);
1284c62f1cccSMitsuru IWASAKI }
1285c62f1cccSMitsuru IWASAKI 
1286bfa3f012SMarcel Moolenaar /* Fetch a table matching the given signature via the RSDT. */
1287986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1288986dffafSJohn Baldwin sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1289c62f1cccSMitsuru IWASAKI {
1290986dffafSJohn Baldwin 	ACPI_TABLE_HEADER *sdt;
1291986dffafSJohn Baldwin 	ACPI_TABLE_RSDT *rsdt;
1292986dffafSJohn Baldwin 	ACPI_TABLE_XSDT *xsdt;
1293a74172abSNate Lawson 	vm_offset_t addr;
1294a74172abSNate Lawson 	int entries, i;
1295945137d9SNate Lawson 
1296986dffafSJohn Baldwin 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1297986dffafSJohn Baldwin 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1298986dffafSJohn Baldwin 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1299945137d9SNate Lawson 	for (i = 0; i < entries; i++) {
1300a74172abSNate Lawson 		switch (addr_size) {
1301a74172abSNate Lawson 		case 4:
1302986dffafSJohn Baldwin 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1303a74172abSNate Lawson 			break;
1304a74172abSNate Lawson 		case 8:
1305986dffafSJohn Baldwin 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1306a74172abSNate Lawson 			break;
1307a74172abSNate Lawson 		default:
1308a74172abSNate Lawson 			assert((addr = 0));
1309a74172abSNate Lawson 		}
1310986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1311bfa3f012SMarcel Moolenaar 		if (last != NULL) {
1312bfa3f012SMarcel Moolenaar 			if (sdt == last)
1313bfa3f012SMarcel Moolenaar 				last = NULL;
1314bfa3f012SMarcel Moolenaar 			continue;
1315bfa3f012SMarcel Moolenaar 		}
1316986dffafSJohn Baldwin 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1317a74172abSNate Lawson 			continue;
1318986dffafSJohn Baldwin 		if (acpi_checksum(sdt, sdt->Length))
1319945137d9SNate Lawson 			errx(1, "RSDT entry %d is corrupt", i);
1320945137d9SNate Lawson 		return (sdt);
1321c62f1cccSMitsuru IWASAKI 	}
1322c62f1cccSMitsuru IWASAKI 
1323945137d9SNate Lawson 	return (NULL);
1324c62f1cccSMitsuru IWASAKI }
1325c62f1cccSMitsuru IWASAKI 
1326986dffafSJohn Baldwin ACPI_TABLE_HEADER *
1327986dffafSJohn Baldwin dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1328c62f1cccSMitsuru IWASAKI {
1329986dffafSJohn Baldwin 	ACPI_TABLE_HEADER	*sdt;
1330c62f1cccSMitsuru IWASAKI 
1331986dffafSJohn Baldwin 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1332c2962974SNate Lawson 	if (acpi_get_fadt_revision(fadt) == 1)
1333986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
13342e71eb12SNate Lawson 	else
1335986dffafSJohn Baldwin 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1336986dffafSJohn Baldwin 	if (acpi_checksum(sdt, sdt->Length))
1337945137d9SNate Lawson 		errx(1, "DSDT is corrupt\n");
1338945137d9SNate Lawson 	return (sdt);
1339c62f1cccSMitsuru IWASAKI }
1340