xref: /freebsd/usr.sbin/acpi/acpidump/acpi.c (revision 5dae51da3da0cc94d17bd67b308fad304ebec7e0)
1 /*-
2  * Copyright (c) 1998 Doug Rabson
3  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *	$FreeBSD$
28  */
29 
30 #include <sys/param.h>
31 #include <sys/endian.h>
32 #include <sys/stat.h>
33 #include <sys/wait.h>
34 #include <assert.h>
35 #include <err.h>
36 #include <fcntl.h>
37 #include <paths.h>
38 #include <stdio.h>
39 #include <stdint.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 
44 #include "acpidump.h"
45 
46 #define BEGIN_COMMENT	"/*\n"
47 #define END_COMMENT	" */\n"
48 
49 static void	acpi_print_string(char *s, size_t length);
50 static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
51 static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
52 static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
53 static void	acpi_print_cpu(u_char cpu_id);
54 static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
55 static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
56 static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
57 		    uint64_t apic_addr);
58 static void	acpi_print_mps_flags(uint16_t flags);
59 static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
60 static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
61 static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
62 static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
63 static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
64 static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
65 static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
66 static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
67 static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
68 		    uint32_t flags);
69 static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
70 static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
71 static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
72 static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
73 static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
74 static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
75 static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
76 static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
77 static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
78 static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
79 static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
80 static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
81 		    void (*action)(ACPI_SUBTABLE_HEADER *));
82 
83 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
84 static int addr_size;
85 
86 /* Strings used in the TCPA table */
87 static const char *tcpa_event_type_strings[] = {
88 	"PREBOOT Certificate",
89 	"POST Code",
90 	"Unused",
91 	"No Action",
92 	"Separator",
93 	"Action",
94 	"Event Tag",
95 	"S-CRTM Contents",
96 	"S-CRTM Version",
97 	"CPU Microcode",
98 	"Platform Config Flags",
99 	"Table of Devices",
100 	"Compact Hash",
101 	"IPL",
102 	"IPL Partition Data",
103 	"Non-Host Code",
104 	"Non-Host Config",
105 	"Non-Host Info"
106 };
107 
108 static const char *TCPA_pcclient_strings[] = {
109 	"<undefined>",
110 	"SMBIOS",
111 	"BIS Certificate",
112 	"POST BIOS ROM Strings",
113 	"ESCD",
114 	"CMOS",
115 	"NVRAM",
116 	"Option ROM Execute",
117 	"Option ROM Configurateion",
118 	"<undefined>",
119 	"Option ROM Microcode Update ",
120 	"S-CRTM Version String",
121 	"S-CRTM Contents",
122 	"POST Contents",
123 	"Table of Devices",
124 };
125 
126 #define	PRINTFLAG_END()		printflag_end()
127 
128 static char pf_sep = '{';
129 
130 static void
131 printflag_end(void)
132 {
133 
134 	if (pf_sep != '{') {
135 		printf("}");
136 		pf_sep = '{';
137 	}
138 	printf("\n");
139 }
140 
141 static void
142 printflag(uint64_t var, uint64_t mask, const char *name)
143 {
144 
145 	if (var & mask) {
146 		printf("%c%s", pf_sep, name);
147 		pf_sep = ',';
148 	}
149 }
150 
151 static void
152 acpi_print_string(char *s, size_t length)
153 {
154 	int	c;
155 
156 	/* Trim trailing spaces and NULLs */
157 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
158 		length--;
159 
160 	while (length--) {
161 		c = *s++;
162 		putchar(c);
163 	}
164 }
165 
166 static void
167 acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
168 {
169 	switch(gas->SpaceId) {
170 	case ACPI_GAS_MEMORY:
171 		if (gas->BitWidth <= 32)
172 			printf("0x%08x:%u[%u] (Memory)",
173 			    (u_int)gas->Address, gas->BitOffset,
174 			    gas->BitWidth);
175 		else
176 			printf("0x%016jx:%u[%u] (Memory)",
177 			    (uintmax_t)gas->Address, gas->BitOffset,
178 			    gas->BitWidth);
179 		break;
180 	case ACPI_GAS_IO:
181 		printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
182 		    gas->BitOffset, gas->BitWidth);
183 		break;
184 	case ACPI_GAS_PCI:
185 		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
186 		       (uint16_t)((gas->Address >> 16) & 0xffff),
187 		       (uint16_t)gas->Address);
188 		break;
189 	/* XXX How to handle these below? */
190 	case ACPI_GAS_EMBEDDED:
191 		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
192 		       gas->BitOffset, gas->BitWidth);
193 		break;
194 	case ACPI_GAS_SMBUS:
195 		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
196 		       gas->BitOffset, gas->BitWidth);
197 		break;
198 	case ACPI_GAS_CMOS:
199 	case ACPI_GAS_PCIBAR:
200 	case ACPI_GAS_DATATABLE:
201 	case ACPI_GAS_FIXED:
202 	default:
203 		printf("0x%016jx (?)", (uintmax_t)gas->Address);
204 		break;
205 	}
206 }
207 
208 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
209 static int
210 acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
211 {
212 	int fadt_revision;
213 
214 	/* Set the FADT revision separately from the RSDP version. */
215 	if (addr_size == 8) {
216 		fadt_revision = 2;
217 
218 		/*
219 		 * A few systems (e.g., IBM T23) have an RSDP that claims
220 		 * revision 2 but the 64 bit addresses are invalid.  If
221 		 * revision 2 and the 32 bit address is non-zero but the
222 		 * 32 and 64 bit versions don't match, prefer the 32 bit
223 		 * version for all subsequent tables.
224 		 */
225 		if (fadt->Facs != 0 &&
226 		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
227 			fadt_revision = 1;
228 	} else
229 		fadt_revision = 1;
230 	return (fadt_revision);
231 }
232 
233 static void
234 acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
235 {
236 	ACPI_TABLE_HEADER *dsdp;
237 	ACPI_TABLE_FACS	*facs;
238 	ACPI_TABLE_FADT *fadt;
239 	int		fadt_revision;
240 
241 	fadt = (ACPI_TABLE_FADT *)sdp;
242 	acpi_print_fadt(sdp);
243 
244 	fadt_revision = acpi_get_fadt_revision(fadt);
245 	if (fadt_revision == 1)
246 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
247 	else
248 		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
249 	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
250 		errx(1, "FACS is corrupt");
251 	acpi_print_facs(facs);
252 
253 	if (fadt_revision == 1)
254 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
255 	else
256 		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
257 	if (acpi_checksum(dsdp, dsdp->Length))
258 		errx(1, "DSDT is corrupt");
259 	acpi_print_dsdt(dsdp);
260 }
261 
262 static void
263 acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
264     void (*action)(ACPI_SUBTABLE_HEADER *))
265 {
266 	ACPI_SUBTABLE_HEADER *subtable;
267 	char *end;
268 
269 	subtable = first;
270 	end = (char *)table + table->Length;
271 	while ((char *)subtable < end) {
272 		printf("\n");
273 		action(subtable);
274 		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
275 		    subtable->Length);
276 	}
277 }
278 
279 static void
280 acpi_print_cpu(u_char cpu_id)
281 {
282 
283 	printf("\tACPI CPU=");
284 	if (cpu_id == 0xff)
285 		printf("ALL\n");
286 	else
287 		printf("%d\n", (u_int)cpu_id);
288 }
289 
290 static void
291 acpi_print_cpu_uid(uint32_t uid, char *uid_string)
292 {
293 
294 	printf("\tUID=%d", uid);
295 	if (uid_string != NULL)
296 		printf(" (%s)", uid_string);
297 	printf("\n");
298 }
299 
300 static void
301 acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
302 {
303 
304 	printf("\tFlags={");
305 	if (flags & ACPI_MADT_ENABLED)
306 		printf("ENABLED");
307 	else
308 		printf("DISABLED");
309 	printf("}\n");
310 	printf("\tAPIC ID=%d\n", apic_id);
311 }
312 
313 static void
314 acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
315 {
316 
317 	printf("\tAPIC ID=%d\n", apic_id);
318 	printf("\tINT BASE=%d\n", int_base);
319 	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
320 }
321 
322 static void
323 acpi_print_mps_flags(uint16_t flags)
324 {
325 
326 	printf("\tFlags={Polarity=");
327 	switch (flags & ACPI_MADT_POLARITY_MASK) {
328 	case ACPI_MADT_POLARITY_CONFORMS:
329 		printf("conforming");
330 		break;
331 	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
332 		printf("active-hi");
333 		break;
334 	case ACPI_MADT_POLARITY_ACTIVE_LOW:
335 		printf("active-lo");
336 		break;
337 	default:
338 		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
339 		break;
340 	}
341 	printf(", Trigger=");
342 	switch (flags & ACPI_MADT_TRIGGER_MASK) {
343 	case ACPI_MADT_TRIGGER_CONFORMS:
344 		printf("conforming");
345 		break;
346 	case ACPI_MADT_TRIGGER_EDGE:
347 		printf("edge");
348 		break;
349 	case ACPI_MADT_TRIGGER_LEVEL:
350 		printf("level");
351 		break;
352 	default:
353 		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
354 	}
355 	printf("}\n");
356 }
357 
358 static void
359 acpi_print_gicc_flags(uint32_t flags)
360 {
361 
362 	printf("\tFlags={Performance intr=");
363 	if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
364 		printf("edge");
365 	else
366 		printf("level");
367 	printf(", VGIC intr=");
368 	if (flags & ACPI_MADT_VGIC_IRQ_MODE)
369 		printf("edge");
370 	else
371 		printf("level");
372 	printf("}\n");
373 }
374 
375 static void
376 acpi_print_intr(uint32_t intr, uint16_t mps_flags)
377 {
378 
379 	printf("\tINTR=%d\n", intr);
380 	acpi_print_mps_flags(mps_flags);
381 }
382 
383 static void
384 acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
385 {
386 
387 	printf("\tLINT Pin=%d\n", lint);
388 	acpi_print_mps_flags(mps_flags);
389 }
390 
391 static const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override",
392 				    "NMI", "Local APIC NMI",
393 				    "Local APIC Override", "IO SAPIC",
394 				    "Local SAPIC", "Platform Interrupt",
395 				    "Local X2APIC", "Local X2APIC NMI",
396 				    "GIC CPU Interface Structure",
397 				    "GIC Distributor Structure",
398 				    "GICv2m MSI Frame",
399 				    "GIC Redistributor Structure",
400 				    "GIC ITS Structure" };
401 static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
402 					    "Corrected Platform Error" };
403 
404 static void
405 acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
406 {
407 	ACPI_MADT_LOCAL_APIC *lapic;
408 	ACPI_MADT_IO_APIC *ioapic;
409 	ACPI_MADT_INTERRUPT_OVERRIDE *over;
410 	ACPI_MADT_NMI_SOURCE *nmi;
411 	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
412 	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
413 	ACPI_MADT_IO_SAPIC *iosapic;
414 	ACPI_MADT_LOCAL_SAPIC *lsapic;
415 	ACPI_MADT_INTERRUPT_SOURCE *isrc;
416 	ACPI_MADT_LOCAL_X2APIC *x2apic;
417 	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
418 	ACPI_MADT_GENERIC_INTERRUPT *gicc;
419 	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
420 	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
421 	ACPI_MADT_GENERIC_TRANSLATOR *gict;
422 
423 	if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0]))
424 		printf("\tType=%s\n", apic_types[mp->Type]);
425 	else
426 		printf("\tType=%d (unknown)\n", mp->Type);
427 	switch (mp->Type) {
428 	case ACPI_MADT_TYPE_LOCAL_APIC:
429 		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
430 		acpi_print_cpu(lapic->ProcessorId);
431 		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
432 		break;
433 	case ACPI_MADT_TYPE_IO_APIC:
434 		ioapic = (ACPI_MADT_IO_APIC *)mp;
435 		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
436 		    ioapic->Address);
437 		break;
438 	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
439 		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
440 		printf("\tBUS=%d\n", (u_int)over->Bus);
441 		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
442 		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
443 		break;
444 	case ACPI_MADT_TYPE_NMI_SOURCE:
445 		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
446 		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
447 		break;
448 	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
449 		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
450 		acpi_print_cpu(lapic_nmi->ProcessorId);
451 		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
452 		break;
453 	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
454 		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
455 		printf("\tLocal APIC ADDR=0x%016jx\n",
456 		    (uintmax_t)lapic_over->Address);
457 		break;
458 	case ACPI_MADT_TYPE_IO_SAPIC:
459 		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
460 		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
461 		    iosapic->Address);
462 		break;
463 	case ACPI_MADT_TYPE_LOCAL_SAPIC:
464 		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
465 		acpi_print_cpu(lsapic->ProcessorId);
466 		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
467 		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
468 		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
469 			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
470 		break;
471 	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
472 		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
473 		if (isrc->Type < sizeof(platform_int_types) /
474 		    sizeof(platform_int_types[0]))
475 			printf("\tType=%s\n", platform_int_types[isrc->Type]);
476 		else
477 			printf("\tType=%d (unknown)\n", isrc->Type);
478 		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
479 		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
480 		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
481 		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
482 		break;
483 	case ACPI_MADT_TYPE_LOCAL_X2APIC:
484 		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
485 		acpi_print_cpu_uid(x2apic->Uid, NULL);
486 		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
487 		break;
488 	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
489 		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
490 		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
491 		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
492 		break;
493 	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
494 		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
495 		acpi_print_cpu_uid(gicc->Uid, NULL);
496 		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
497 		acpi_print_gicc_flags(gicc->Flags);
498 		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
499 		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
500 		printf("\tParked ADDR=%016jx\n",
501 		    (uintmax_t)gicc->ParkedAddress);
502 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
503 		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
504 		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
505 		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
506 		printf("\tGICR ADDR=%016jx\n",
507 		    (uintmax_t)gicc->GicrBaseAddress);
508 		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
509 		printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass);
510 		break;
511 	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
512 		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
513 		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
514 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
515 		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
516 		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
517 		break;
518 	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
519 		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
520 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
521 		printf("\tLength=%08x\n", gicr->Length);
522 		break;
523 	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
524 		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
525 		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
526 		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
527 		break;
528 	}
529 }
530 
531 static void
532 acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
533 {
534 	ACPI_TABLE_MADT *madt;
535 
536 	printf(BEGIN_COMMENT);
537 	acpi_print_sdt(sdp);
538 	madt = (ACPI_TABLE_MADT *)sdp;
539 	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
540 	printf("\tFlags={");
541 	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
542 		printf("PC-AT");
543 	printf("}\n");
544 	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
545 	printf(END_COMMENT);
546 }
547 
548 static void
549 acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
550 {
551 	ACPI_TABLE_HPET *hpet;
552 
553 	printf(BEGIN_COMMENT);
554 	acpi_print_sdt(sdp);
555 	hpet = (ACPI_TABLE_HPET *)sdp;
556 	printf("\tHPET Number=%d\n", hpet->Sequence);
557 	printf("\tADDR=");
558 	acpi_print_gas(&hpet->Address);
559 	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
560 	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
561 	    8);
562 	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
563 	    1 : 0);
564 	printf("\tLegacy IRQ routing capable={");
565 	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
566 		printf("TRUE}\n");
567 	else
568 		printf("FALSE}\n");
569 	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
570 	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
571 	printf("\tFlags=0x%02x\n", hpet->Flags);
572 	printf(END_COMMENT);
573 }
574 
575 static void
576 acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
577 {
578 	ACPI_TABLE_ECDT *ecdt;
579 
580 	printf(BEGIN_COMMENT);
581 	acpi_print_sdt(sdp);
582 	ecdt = (ACPI_TABLE_ECDT *)sdp;
583 	printf("\tEC_CONTROL=");
584 	acpi_print_gas(&ecdt->Control);
585 	printf("\n\tEC_DATA=");
586 	acpi_print_gas(&ecdt->Data);
587 	printf("\n\tUID=%#x, ", ecdt->Uid);
588 	printf("GPE_BIT=%#x\n", ecdt->Gpe);
589 	printf("\tEC_ID=%s\n", ecdt->Id);
590 	printf(END_COMMENT);
591 }
592 
593 static void
594 acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
595 {
596 	ACPI_TABLE_MCFG *mcfg;
597 	ACPI_MCFG_ALLOCATION *alloc;
598 	u_int i, entries;
599 
600 	printf(BEGIN_COMMENT);
601 	acpi_print_sdt(sdp);
602 	mcfg = (ACPI_TABLE_MCFG *)sdp;
603 	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
604 	    sizeof(ACPI_MCFG_ALLOCATION);
605 	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
606 	for (i = 0; i < entries; i++, alloc++) {
607 		printf("\n");
608 		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
609 		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
610 		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
611 		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
612 	}
613 	printf(END_COMMENT);
614 }
615 
616 static void
617 acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
618 {
619 	ACPI_TABLE_SLIT *slit;
620 	UINT64 i, j;
621 
622 	printf(BEGIN_COMMENT);
623 	acpi_print_sdt(sdp);
624 	slit = (ACPI_TABLE_SLIT *)sdp;
625 	printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
626 	printf("\n\t      ");
627 	for (i = 0; i < slit->LocalityCount; i++)
628 		printf(" %3ju", (uintmax_t)i);
629 	printf("\n\t     +");
630 	for (i = 0; i < slit->LocalityCount; i++)
631 		printf("----");
632 	printf("\n");
633 	for (i = 0; i < slit->LocalityCount; i++) {
634 		printf("\t %3ju |", (uintmax_t)i);
635 		for (j = 0; j < slit->LocalityCount; j++)
636 			printf(" %3d",
637 			    slit->Entry[i * slit->LocalityCount + j]);
638 		printf("\n");
639 	}
640 	printf(END_COMMENT);
641 }
642 
643 static void
644 acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
645     uint32_t flags)
646 {
647 
648 	printf("\tFlags={");
649 	if (flags & ACPI_SRAT_CPU_ENABLED)
650 		printf("ENABLED");
651 	else
652 		printf("DISABLED");
653 	printf("}\n");
654 	printf("\tAPIC ID=%d\n", apic_id);
655 	printf("\tProximity Domain=%d\n", proximity_domain);
656 }
657 
658 static char *
659 acpi_tcpa_evname(struct TCPAevent *event)
660 {
661 	struct TCPApc_event *pc_event;
662 	char *eventname = NULL;
663 
664 	pc_event = (struct TCPApc_event *)(event + 1);
665 
666 	switch(event->event_type) {
667 	case PREBOOT:
668 	case POST_CODE:
669 	case UNUSED:
670 	case NO_ACTION:
671 	case SEPARATOR:
672 	case SCRTM_CONTENTS:
673 	case SCRTM_VERSION:
674 	case CPU_MICROCODE:
675 	case PLATFORM_CONFIG_FLAGS:
676 	case TABLE_OF_DEVICES:
677 	case COMPACT_HASH:
678 	case IPL:
679 	case IPL_PARTITION_DATA:
680 	case NONHOST_CODE:
681 	case NONHOST_CONFIG:
682 	case NONHOST_INFO:
683 		asprintf(&eventname, "%s",
684 		    tcpa_event_type_strings[event->event_type]);
685 		break;
686 
687 	case ACTION:
688 		eventname = calloc(event->event_size + 1, sizeof(char));
689 		memcpy(eventname, pc_event, event->event_size);
690 		break;
691 
692 	case EVENT_TAG:
693 		switch (pc_event->event_id) {
694 		case SMBIOS:
695 		case BIS_CERT:
696 		case CMOS:
697 		case NVRAM:
698 		case OPTION_ROM_EXEC:
699 		case OPTION_ROM_CONFIG:
700 		case S_CRTM_VERSION:
701 		case POST_BIOS_ROM:
702 		case ESCD:
703 		case OPTION_ROM_MICROCODE:
704 		case S_CRTM_CONTENTS:
705 		case POST_CONTENTS:
706 			asprintf(&eventname, "%s",
707 			    TCPA_pcclient_strings[pc_event->event_id]);
708 			break;
709 
710 		default:
711 			asprintf(&eventname, "<unknown tag 0x%02x>",
712 			    pc_event->event_id);
713 			break;
714 		}
715 		break;
716 
717 	default:
718 		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
719 		break;
720 	}
721 
722 	return eventname;
723 }
724 
725 static void
726 acpi_print_tcpa(struct TCPAevent *event)
727 {
728 	int i;
729 	char *eventname;
730 
731 	eventname = acpi_tcpa_evname(event);
732 
733 	printf("\t%d", event->pcr_index);
734 	printf(" 0x");
735 	for (i = 0; i < 20; i++)
736 		printf("%02x", event->pcr_value[i]);
737 	printf(" [%s]\n", eventname ? eventname : "<unknown>");
738 
739 	free(eventname);
740 }
741 
742 static void
743 acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
744 {
745 	struct TCPAbody *tcpa;
746 	struct TCPAevent *event;
747 	uintmax_t len, paddr;
748 	unsigned char *vaddr = NULL;
749 	unsigned char *vend = NULL;
750 
751 	printf(BEGIN_COMMENT);
752 	acpi_print_sdt(sdp);
753 	tcpa = (struct TCPAbody *) sdp;
754 
755 	switch (tcpa->platform_class) {
756 	case ACPI_TCPA_BIOS_CLIENT:
757 		len = tcpa->client.log_max_len;
758 		paddr = tcpa->client.log_start_addr;
759 		break;
760 
761 	case ACPI_TCPA_BIOS_SERVER:
762 		len = tcpa->server.log_max_len;
763 		paddr = tcpa->server.log_start_addr;
764 		break;
765 
766 	default:
767 		printf("XXX");
768 		printf(END_COMMENT);
769 		return;
770 	}
771 	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
772 	    tcpa->platform_class, paddr, len);
773 
774 	if (len == 0) {
775 		printf("\tEmpty TCPA table\n");
776 		printf(END_COMMENT);
777 		return;
778 	}
779 	if(sdp->Revision == 1){
780 		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
781 		printf(END_COMMENT);
782 		return;
783 	}
784 
785 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
786 	vend = vaddr + len;
787 
788 	while (vaddr != NULL) {
789 		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
790 		    (vaddr + sizeof(struct TCPAevent) < vaddr))
791 			break;
792 		event = (struct TCPAevent *)(void *)vaddr;
793 		if (vaddr + event->event_size >= vend)
794 			break;
795 		if (vaddr + event->event_size < vaddr)
796 			break;
797 		if (event->event_type == 0 && event->event_size == 0)
798 			break;
799 #if 0
800 		{
801 		unsigned int i, j, k;
802 
803 		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
804 		for (j = 0, i = 0; i <
805 		    sizeof(struct TCPAevent) + event->event_size; i++) {
806 			printf("%02x ", vaddr[i]);
807 			if ((i+1) % 8 == 0) {
808 				for (k = 0; k < 8; k++)
809 					printf("%c", isprint(vaddr[j+k]) ?
810 					    vaddr[j+k] : '.');
811 				printf("\n\t\t%p ", &vaddr[i + 1]);
812 				j = i + 1;
813 			}
814 		}
815 		printf("\n"); }
816 #endif
817 		acpi_print_tcpa(event);
818 
819 		vaddr += sizeof(struct TCPAevent) + event->event_size;
820 	}
821 
822 	printf(END_COMMENT);
823 }
824 
825 static const char *
826 devscope_type2str(int type)
827 {
828 	static char typebuf[16];
829 
830 	switch (type) {
831 	case 1:
832 		return ("PCI Endpoint Device");
833 	case 2:
834 		return ("PCI Sub-Hierarchy");
835 	case 3:
836 		return ("IOAPIC");
837 	case 4:
838 		return ("HPET");
839 	default:
840 		snprintf(typebuf, sizeof(typebuf), "%d", type);
841 		return (typebuf);
842 	}
843 }
844 
845 static int
846 acpi_handle_dmar_devscope(void *addr, int remaining)
847 {
848 	char sep;
849 	int pathlen;
850 	ACPI_DMAR_PCI_PATH *path, *pathend;
851 	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
852 
853 	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
854 		return (-1);
855 
856 	if (remaining < devscope->Length)
857 		return (-1);
858 
859 	printf("\n");
860 	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
861 	printf("\t\tLength=%d\n", devscope->Length);
862 	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
863 	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
864 
865 	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
866 	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
867 	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
868 	if (path < pathend) {
869 		sep = '{';
870 		printf("\t\tPath=");
871 		do {
872 			printf("%c%d:%d", sep, path->Device, path->Function);
873 			sep=',';
874 			path++;
875 		} while (path < pathend);
876 		printf("}\n");
877 	}
878 
879 	return (devscope->Length);
880 }
881 
882 static void
883 acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
884 {
885 	char *cp;
886 	int remaining, consumed;
887 
888 	printf("\n");
889 	printf("\tType=DRHD\n");
890 	printf("\tLength=%d\n", drhd->Header.Length);
891 
892 #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
893 
894 	printf("\tFlags=");
895 	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
896 	PRINTFLAG_END();
897 
898 #undef PRINTFLAG
899 
900 	printf("\tSegment=%d\n", drhd->Segment);
901 	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
902 
903 	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
904 	if (remaining > 0)
905 		printf("\tDevice Scope:");
906 	while (remaining > 0) {
907 		cp = (char *)drhd + drhd->Header.Length - remaining;
908 		consumed = acpi_handle_dmar_devscope(cp, remaining);
909 		if (consumed <= 0)
910 			break;
911 		else
912 			remaining -= consumed;
913 	}
914 }
915 
916 static void
917 acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
918 {
919 	char *cp;
920 	int remaining, consumed;
921 
922 	printf("\n");
923 	printf("\tType=RMRR\n");
924 	printf("\tLength=%d\n", rmrr->Header.Length);
925 	printf("\tSegment=%d\n", rmrr->Segment);
926 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
927 	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
928 
929 	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
930 	if (remaining > 0)
931 		printf("\tDevice Scope:");
932 	while (remaining > 0) {
933 		cp = (char *)rmrr + rmrr->Header.Length - remaining;
934 		consumed = acpi_handle_dmar_devscope(cp, remaining);
935 		if (consumed <= 0)
936 			break;
937 		else
938 			remaining -= consumed;
939 	}
940 }
941 
942 static void
943 acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
944 {
945 	char *cp;
946 	int remaining, consumed;
947 
948 	printf("\n");
949 	printf("\tType=ATSR\n");
950 	printf("\tLength=%d\n", atsr->Header.Length);
951 
952 #define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
953 
954 	printf("\tFlags=");
955 	PRINTFLAG(atsr->Flags, ALL_PORTS);
956 	PRINTFLAG_END();
957 
958 #undef PRINTFLAG
959 
960 	printf("\tSegment=%d\n", atsr->Segment);
961 
962 	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
963 	if (remaining > 0)
964 		printf("\tDevice Scope:");
965 	while (remaining > 0) {
966 		cp = (char *)atsr + atsr->Header.Length - remaining;
967 		consumed = acpi_handle_dmar_devscope(cp, remaining);
968 		if (consumed <= 0)
969 			break;
970 		else
971 			remaining -= consumed;
972 	}
973 }
974 
975 static void
976 acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
977 {
978 
979 	printf("\n");
980 	printf("\tType=RHSA\n");
981 	printf("\tLength=%d\n", rhsa->Header.Length);
982 	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
983 	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
984 }
985 
986 static int
987 acpi_handle_dmar_remapping_structure(void *addr, int remaining)
988 {
989 	ACPI_DMAR_HEADER *hdr = addr;
990 
991 	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
992 		return (-1);
993 
994 	if (remaining < hdr->Length)
995 		return (-1);
996 
997 	switch (hdr->Type) {
998 	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
999 		acpi_handle_dmar_drhd(addr);
1000 		break;
1001 	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1002 		acpi_handle_dmar_rmrr(addr);
1003 		break;
1004 	case ACPI_DMAR_TYPE_ROOT_ATS:
1005 		acpi_handle_dmar_atsr(addr);
1006 		break;
1007 	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1008 		acpi_handle_dmar_rhsa(addr);
1009 		break;
1010 	default:
1011 		printf("\n");
1012 		printf("\tType=%d\n", hdr->Type);
1013 		printf("\tLength=%d\n", hdr->Length);
1014 		break;
1015 	}
1016 	return (hdr->Length);
1017 }
1018 
1019 #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1020 #define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
1021 #endif
1022 
1023 static void
1024 acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1025 {
1026 	char *cp;
1027 	int remaining, consumed;
1028 	ACPI_TABLE_DMAR *dmar;
1029 
1030 	printf(BEGIN_COMMENT);
1031 	acpi_print_sdt(sdp);
1032 	dmar = (ACPI_TABLE_DMAR *)sdp;
1033 	printf("\tHost Address Width=%d\n", dmar->Width + 1);
1034 
1035 #define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
1036 
1037 	printf("\tFlags=");
1038 	PRINTFLAG(dmar->Flags, INTR_REMAP);
1039 	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1040 	PRINTFLAG_END();
1041 
1042 #undef PRINTFLAG
1043 
1044 	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1045 	while (remaining > 0) {
1046 		cp = (char *)sdp + sdp->Length - remaining;
1047 		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1048 		if (consumed <= 0)
1049 			break;
1050 		else
1051 			remaining -= consumed;
1052 	}
1053 
1054 	printf(END_COMMENT);
1055 }
1056 
1057 static void
1058 acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1059 {
1060 
1061 	printf("\tFlags={");
1062 	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1063 		printf("ENABLED");
1064 	else
1065 		printf("DISABLED");
1066 	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1067 		printf(",HOT_PLUGGABLE");
1068 	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1069 		printf(",NON_VOLATILE");
1070 	printf("}\n");
1071 	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1072 	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1073 	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1074 }
1075 
1076 static const char *srat_types[] = { "CPU", "Memory", "X2APIC", "GICC" };
1077 
1078 static void
1079 acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1080 {
1081 	ACPI_SRAT_CPU_AFFINITY *cpu;
1082 	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
1083 	ACPI_SRAT_GICC_AFFINITY *gic;
1084 
1085 	if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0]))
1086 		printf("\tType=%s\n", srat_types[srat->Type]);
1087 	else
1088 		printf("\tType=%d (unknown)\n", srat->Type);
1089 	switch (srat->Type) {
1090 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
1091 		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1092 		acpi_print_srat_cpu(cpu->ApicId,
1093 		    cpu->ProximityDomainHi[2] << 24 |
1094 		    cpu->ProximityDomainHi[1] << 16 |
1095 		    cpu->ProximityDomainHi[0] << 0 |
1096 		    cpu->ProximityDomainLo, cpu->Flags);
1097 		break;
1098 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1099 		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1100 		break;
1101 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1102 		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1103 		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1104 		    x2apic->Flags);
1105 		break;
1106 	case ACPI_SRAT_TYPE_GICC_AFFINITY:
1107 		gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
1108 		acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
1109 		    gic->Flags);
1110 		break;
1111 	}
1112 }
1113 
1114 static void
1115 acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1116 {
1117 	ACPI_TABLE_SRAT *srat;
1118 
1119 	printf(BEGIN_COMMENT);
1120 	acpi_print_sdt(sdp);
1121 	srat = (ACPI_TABLE_SRAT *)sdp;
1122 	printf("\tTable Revision=%d\n", srat->TableRevision);
1123 	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1124 	printf(END_COMMENT);
1125 }
1126 
1127 static void
1128 acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1129 {
1130 	printf("  ");
1131 	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
1132 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1133 	       sdp->Length, sdp->Revision, sdp->Checksum);
1134 	printf("\tOEMID=");
1135 	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1136 	printf(", OEM Table ID=");
1137 	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1138 	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1139 	printf("\tCreator ID=");
1140 	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
1141 	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1142 }
1143 
1144 static void
1145 acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1146 {
1147 	ACPI_TABLE_RSDT *rsdt;
1148 	ACPI_TABLE_XSDT *xsdt;
1149 	int	i, entries;
1150 
1151 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1152 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1153 	printf(BEGIN_COMMENT);
1154 	acpi_print_sdt(rsdp);
1155 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1156 	printf("\tEntries={ ");
1157 	for (i = 0; i < entries; i++) {
1158 		if (i > 0)
1159 			printf(", ");
1160 		if (addr_size == 4)
1161 			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1162 		else
1163 			printf("0x%016jx",
1164 			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1165 	}
1166 	printf(" }\n");
1167 	printf(END_COMMENT);
1168 }
1169 
1170 static const char *acpi_pm_profiles[] = {
1171 	"Unspecified", "Desktop", "Mobile", "Workstation",
1172 	"Enterprise Server", "SOHO Server", "Appliance PC"
1173 };
1174 
1175 static void
1176 acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1177 {
1178 	ACPI_TABLE_FADT *fadt;
1179 	const char *pm;
1180 
1181 	fadt = (ACPI_TABLE_FADT *)sdp;
1182 	printf(BEGIN_COMMENT);
1183 	acpi_print_sdt(sdp);
1184 	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1185 	       fadt->Dsdt);
1186 	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1187 	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
1188 		pm = "Reserved";
1189 	else
1190 		pm = acpi_pm_profiles[fadt->PreferredProfile];
1191 	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1192 	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1193 	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1194 	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1195 	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1196 	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1197 	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1198 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1199 	       fadt->Pm1aEventBlock,
1200 	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1201 	if (fadt->Pm1bEventBlock != 0)
1202 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1203 		       fadt->Pm1bEventBlock,
1204 		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1205 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1206 	       fadt->Pm1aControlBlock,
1207 	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1208 	if (fadt->Pm1bControlBlock != 0)
1209 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1210 		       fadt->Pm1bControlBlock,
1211 		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1212 	if (fadt->Pm2ControlBlock != 0)
1213 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1214 		       fadt->Pm2ControlBlock,
1215 		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1216 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1217 	       fadt->PmTimerBlock,
1218 	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1219 	if (fadt->Gpe0Block != 0)
1220 		printf("\tGPE0_BLK=0x%x-0x%x\n",
1221 		       fadt->Gpe0Block,
1222 		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1223 	if (fadt->Gpe1Block != 0)
1224 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1225 		       fadt->Gpe1Block,
1226 		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1227 		       fadt->Gpe1Base);
1228 	if (fadt->CstControl != 0)
1229 		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
1230 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1231 	       fadt->C2Latency, fadt->C3Latency);
1232 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1233 	       fadt->FlushSize, fadt->FlushStride);
1234 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1235 	       fadt->DutyOffset, fadt->DutyWidth);
1236 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1237 	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1238 
1239 #define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
1240 
1241 	printf("\tIAPC_BOOT_ARCH=");
1242 	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1243 	PRINTFLAG(fadt->BootFlags, 8042);
1244 	PRINTFLAG(fadt->BootFlags, NO_VGA);
1245 	PRINTFLAG(fadt->BootFlags, NO_MSI);
1246 	PRINTFLAG(fadt->BootFlags, NO_ASPM);
1247 	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1248 	PRINTFLAG_END();
1249 
1250 	printf("\tFlags=");
1251 	PRINTFLAG(fadt->Flags, WBINVD);
1252 	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1253 	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1254 	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1255 	PRINTFLAG(fadt->Flags, POWER_BUTTON);
1256 	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1257 	PRINTFLAG(fadt->Flags, FIXED_RTC);
1258 	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1259 	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1260 	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1261 	PRINTFLAG(fadt->Flags, RESET_REGISTER);
1262 	PRINTFLAG(fadt->Flags, SEALED_CASE);
1263 	PRINTFLAG(fadt->Flags, HEADLESS);
1264 	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1265 	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1266 	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1267 	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1268 	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1269 	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1270 	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1271 	PRINTFLAG(fadt->Flags, HW_REDUCED);
1272 	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1273 	PRINTFLAG_END();
1274 
1275 #undef PRINTFLAG
1276 
1277 	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
1278 		printf("\tRESET_REG=");
1279 		acpi_print_gas(&fadt->ResetRegister);
1280 		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
1281 	}
1282 	if (acpi_get_fadt_revision(fadt) > 1) {
1283 		printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
1284 		printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1285 		printf("\tX_PM1a_EVT_BLK=");
1286 		acpi_print_gas(&fadt->XPm1aEventBlock);
1287 		if (fadt->XPm1bEventBlock.Address != 0) {
1288 			printf("\n\tX_PM1b_EVT_BLK=");
1289 			acpi_print_gas(&fadt->XPm1bEventBlock);
1290 		}
1291 		printf("\n\tX_PM1a_CNT_BLK=");
1292 		acpi_print_gas(&fadt->XPm1aControlBlock);
1293 		if (fadt->XPm1bControlBlock.Address != 0) {
1294 			printf("\n\tX_PM1b_CNT_BLK=");
1295 			acpi_print_gas(&fadt->XPm1bControlBlock);
1296 		}
1297 		if (fadt->XPm2ControlBlock.Address != 0) {
1298 			printf("\n\tX_PM2_CNT_BLK=");
1299 			acpi_print_gas(&fadt->XPm2ControlBlock);
1300 		}
1301 		printf("\n\tX_PM_TMR_BLK=");
1302 		acpi_print_gas(&fadt->XPmTimerBlock);
1303 		if (fadt->XGpe0Block.Address != 0) {
1304 			printf("\n\tX_GPE0_BLK=");
1305 			acpi_print_gas(&fadt->XGpe0Block);
1306 		}
1307 		if (fadt->XGpe1Block.Address != 0) {
1308 			printf("\n\tX_GPE1_BLK=");
1309 			acpi_print_gas(&fadt->XGpe1Block);
1310 		}
1311 		printf("\n");
1312 	}
1313 
1314 	printf(END_COMMENT);
1315 }
1316 
1317 static void
1318 acpi_print_facs(ACPI_TABLE_FACS *facs)
1319 {
1320 	printf(BEGIN_COMMENT);
1321 	printf("  FACS:\tLength=%u, ", facs->Length);
1322 	printf("HwSig=0x%08x, ", facs->HardwareSignature);
1323 	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
1324 
1325 	printf("\tGlobal_Lock=");
1326 	if (facs->GlobalLock != 0) {
1327 		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
1328 			printf("PENDING,");
1329 		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
1330 			printf("OWNED");
1331 	}
1332 	printf("\n");
1333 
1334 	printf("\tFlags=");
1335 	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
1336 		printf("S4BIOS");
1337 	printf("\n");
1338 
1339 	if (facs->XFirmwareWakingVector != 0)
1340 		printf("\tX_Firm_Wake_Vec=%016jx\n",
1341 		    (uintmax_t)facs->XFirmwareWakingVector);
1342 	printf("\tVersion=%u\n", facs->Version);
1343 
1344 	printf(END_COMMENT);
1345 }
1346 
1347 static void
1348 acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1349 {
1350 	printf(BEGIN_COMMENT);
1351 	acpi_print_sdt(dsdp);
1352 	printf(END_COMMENT);
1353 }
1354 
1355 int
1356 acpi_checksum(void *p, size_t length)
1357 {
1358 	uint8_t *bp;
1359 	uint8_t sum;
1360 
1361 	bp = p;
1362 	sum = 0;
1363 	while (length--)
1364 		sum += *bp++;
1365 
1366 	return (sum);
1367 }
1368 
1369 static ACPI_TABLE_HEADER *
1370 acpi_map_sdt(vm_offset_t pa)
1371 {
1372 	ACPI_TABLE_HEADER *sp;
1373 
1374 	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1375 	sp = acpi_map_physical(pa, sp->Length);
1376 	return (sp);
1377 }
1378 
1379 static void
1380 acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
1381 {
1382 	printf(BEGIN_COMMENT);
1383 	printf("  RSD PTR: OEM=");
1384 	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
1385 	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
1386 	       rp->Revision);
1387 	if (rp->Revision < 2) {
1388 		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
1389 		    rp->Checksum);
1390 	} else {
1391 		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
1392 		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
1393 		    rp->ExtendedChecksum);
1394 	}
1395 	printf(END_COMMENT);
1396 }
1397 
1398 static void
1399 acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
1400 {
1401 	ACPI_TABLE_HEADER *sdp;
1402 	ACPI_TABLE_RSDT *rsdt;
1403 	ACPI_TABLE_XSDT *xsdt;
1404 	vm_offset_t addr;
1405 	int entries, i;
1406 
1407 	acpi_print_rsdt(rsdp);
1408 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1409 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1410 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1411 	for (i = 0; i < entries; i++) {
1412 		if (addr_size == 4)
1413 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1414 		else
1415 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1416 		if (addr == 0)
1417 			continue;
1418 		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1419 		if (acpi_checksum(sdp, sdp->Length)) {
1420 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
1421 			    sdp->Signature);
1422 			continue;
1423 		}
1424 		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
1425 			acpi_handle_fadt(sdp);
1426 		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
1427 			acpi_handle_madt(sdp);
1428 		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
1429 			acpi_handle_hpet(sdp);
1430 		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
1431 			acpi_handle_ecdt(sdp);
1432 		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
1433 			acpi_handle_mcfg(sdp);
1434 		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
1435 			acpi_handle_slit(sdp);
1436 		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
1437 			acpi_handle_srat(sdp);
1438 		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
1439 			acpi_handle_tcpa(sdp);
1440 		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
1441 			acpi_handle_dmar(sdp);
1442 		else {
1443 			printf(BEGIN_COMMENT);
1444 			acpi_print_sdt(sdp);
1445 			printf(END_COMMENT);
1446 		}
1447 	}
1448 }
1449 
1450 ACPI_TABLE_HEADER *
1451 sdt_load_devmem(void)
1452 {
1453 	ACPI_TABLE_RSDP *rp;
1454 	ACPI_TABLE_HEADER *rsdp;
1455 
1456 	rp = acpi_find_rsd_ptr();
1457 	if (!rp)
1458 		errx(1, "Can't find ACPI information");
1459 
1460 	if (tflag)
1461 		acpi_print_rsd_ptr(rp);
1462 	if (rp->Revision < 2) {
1463 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
1464 		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
1465 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1466 			errx(1, "RSDT is corrupted");
1467 		addr_size = sizeof(uint32_t);
1468 	} else {
1469 		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
1470 		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
1471 		    acpi_checksum(rsdp, rsdp->Length) != 0)
1472 			errx(1, "XSDT is corrupted");
1473 		addr_size = sizeof(uint64_t);
1474 	}
1475 	return (rsdp);
1476 }
1477 
1478 /* Write the DSDT to a file, concatenating any SSDTs (if present). */
1479 static int
1480 write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
1481 {
1482 	ACPI_TABLE_HEADER sdt;
1483 	ACPI_TABLE_HEADER *ssdt;
1484 	uint8_t sum;
1485 
1486 	/* Create a new checksum to account for the DSDT and any SSDTs. */
1487 	sdt = *dsdt;
1488 	if (rsdt != NULL) {
1489 		sdt.Checksum = 0;
1490 		sum = acpi_checksum(dsdt + 1, dsdt->Length -
1491 		    sizeof(ACPI_TABLE_HEADER));
1492 		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
1493 		while (ssdt != NULL) {
1494 			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
1495 			sum += acpi_checksum(ssdt + 1,
1496 			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
1497 			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
1498 		}
1499 		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
1500 		sdt.Checksum -= sum;
1501 	}
1502 
1503 	/* Write out the DSDT header and body. */
1504 	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
1505 	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
1506 
1507 	/* Write out any SSDTs (if present.) */
1508 	if (rsdt != NULL) {
1509 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
1510 		while (ssdt != NULL) {
1511 			write(fd, ssdt + 1, ssdt->Length -
1512 			    sizeof(ACPI_TABLE_HEADER));
1513 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
1514 		}
1515 	}
1516 	return (0);
1517 }
1518 
1519 void
1520 dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1521 {
1522 	int	fd;
1523 	mode_t	mode;
1524 
1525 	assert(outfile != NULL);
1526 	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1527 	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
1528 	if (fd == -1) {
1529 		perror("dsdt_save_file");
1530 		return;
1531 	}
1532 	write_dsdt(fd, rsdt, dsdp);
1533 	close(fd);
1534 }
1535 
1536 void
1537 aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
1538 {
1539 	char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
1540 	const char *iname = "/acpdump.din";
1541 	const char *oname = "/acpdump.dsl";
1542 	const char *tmpdir;
1543 	FILE *fp;
1544 	size_t len;
1545 	int fd, status;
1546 	pid_t pid;
1547 
1548 	tmpdir = getenv("TMPDIR");
1549 	if (tmpdir == NULL)
1550 		tmpdir = _PATH_TMP;
1551 	if (realpath(tmpdir, buf) == NULL) {
1552 		perror("realpath tmp dir");
1553 		return;
1554 	}
1555 	len = sizeof(wrkdir) - strlen(iname);
1556 	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
1557 		fprintf(stderr, "$TMPDIR too long\n");
1558 		return;
1559 	}
1560 	if  (mkdtemp(wrkdir) == NULL) {
1561 		perror("mkdtemp tmp working dir");
1562 		return;
1563 	}
1564 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
1565 	assert(len <= sizeof(tmpstr) - 1);
1566 	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1567 	if (fd < 0) {
1568 		perror("iasl tmp file");
1569 		return;
1570 	}
1571 	write_dsdt(fd, rsdt, dsdp);
1572 	close(fd);
1573 
1574 	/* Run iasl -d on the temp file */
1575 	if ((pid = fork()) == 0) {
1576 		close(STDOUT_FILENO);
1577 		if (vflag == 0)
1578 			close(STDERR_FILENO);
1579 		execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
1580 		err(1, "exec");
1581 	}
1582 	if (pid > 0)
1583 		wait(&status);
1584 	if (unlink(tmpstr) < 0) {
1585 		perror("unlink");
1586 		goto out;
1587 	}
1588 	if (pid < 0) {
1589 		perror("fork");
1590 		goto out;
1591 	}
1592 	if (status != 0) {
1593 		fprintf(stderr, "iast exit status = %d\n", status);
1594 	}
1595 
1596 	/* Dump iasl's output to stdout */
1597 	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
1598 	assert(len <= sizeof(tmpstr) - 1);
1599 	fp = fopen(tmpstr, "r");
1600 	if (unlink(tmpstr) < 0) {
1601 		perror("unlink");
1602 		goto out;
1603 	}
1604 	if (fp == NULL) {
1605 		perror("iasl tmp file (read)");
1606 		goto out;
1607 	}
1608 	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
1609 		fwrite(buf, 1, len, stdout);
1610 	fclose(fp);
1611 
1612     out:
1613 	if (rmdir(wrkdir) < 0)
1614 		perror("rmdir");
1615 }
1616 
1617 void
1618 sdt_print_all(ACPI_TABLE_HEADER *rsdp)
1619 {
1620 	acpi_handle_rsdt(rsdp);
1621 }
1622 
1623 /* Fetch a table matching the given signature via the RSDT. */
1624 ACPI_TABLE_HEADER *
1625 sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
1626 {
1627 	ACPI_TABLE_HEADER *sdt;
1628 	ACPI_TABLE_RSDT *rsdt;
1629 	ACPI_TABLE_XSDT *xsdt;
1630 	vm_offset_t addr;
1631 	int entries, i;
1632 
1633 	rsdt = (ACPI_TABLE_RSDT *)rsdp;
1634 	xsdt = (ACPI_TABLE_XSDT *)rsdp;
1635 	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1636 	for (i = 0; i < entries; i++) {
1637 		if (addr_size == 4)
1638 			addr = le32toh(rsdt->TableOffsetEntry[i]);
1639 		else
1640 			addr = le64toh(xsdt->TableOffsetEntry[i]);
1641 		if (addr == 0)
1642 			continue;
1643 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
1644 		if (last != NULL) {
1645 			if (sdt == last)
1646 				last = NULL;
1647 			continue;
1648 		}
1649 		if (memcmp(sdt->Signature, sig, strlen(sig)))
1650 			continue;
1651 		if (acpi_checksum(sdt, sdt->Length))
1652 			errx(1, "RSDT entry %d is corrupt", i);
1653 		return (sdt);
1654 	}
1655 
1656 	return (NULL);
1657 }
1658 
1659 ACPI_TABLE_HEADER *
1660 dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
1661 {
1662 	ACPI_TABLE_HEADER	*sdt;
1663 
1664 	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
1665 	if (acpi_get_fadt_revision(fadt) == 1)
1666 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
1667 	else
1668 		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
1669 	if (acpi_checksum(sdt, sdt->Length))
1670 		errx(1, "DSDT is corrupt\n");
1671 	return (sdt);
1672 }
1673