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