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