1/* $NetBSD: acpi.c,v 1.56 2024/05/12 23:00:21 msaitoh Exp $ */
2
3/*-
4 * Copyright (c) 1998 Doug Rabson
5 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	$FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 321299 2017-07-20 17:36:17Z emaste $
30 */
31
32#include <sys/cdefs.h>
33__RCSID("$NetBSD: acpi.c,v 1.56 2024/05/12 23:00:21 msaitoh Exp $");
34
35#include <sys/param.h>
36#include <sys/endian.h>
37#include <sys/stat.h>
38#include <sys/wait.h>
39#include <assert.h>
40#include <err.h>
41#include <fcntl.h>
42#include <paths.h>
43#include <stdbool.h>
44#include <stdio.h>
45#include <stdint.h>
46#include <stdlib.h>
47#include <string.h>
48#include <unistd.h>
49#include <stddef.h>
50#include <uuid.h>
51
52#include "acpidump.h"
53
54#define BEGIN_COMMENT	"/*\n"
55#define END_COMMENT	" */\n"
56
57/* Commonly used helper functions */
58static void	acpi_print_string(char *s, size_t length);
59static void	acpi_print_tabs(unsigned int n);
60static void	acpi_dump_bytes(uint8_t *p, uint32_t len, unsigned int ntabs);
61static void	acpi_dump_table(ACPI_TABLE_HEADER *sdp);
62static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
63static void	acpi_print_pci(uint16_t vendorid, uint16_t deviceid,
64		    uint8_t seg, uint8_t bus, uint8_t device, uint8_t func);
65static void	acpi_print_pci_sbdf(uint8_t seg, uint8_t bus, uint8_t device,
66		    uint8_t func);
67#ifdef notyet
68static void	acpi_print_hest_generic_status(ACPI_HEST_GENERIC_STATUS *);
69static void	acpi_print_hest_generic_data(ACPI_HEST_GENERIC_DATA *);
70#endif
71static void	acpi_print_whea(ACPI_WHEA_HEADER *whea,
72		    void (*print_action)(ACPI_WHEA_HEADER *),
73		    void (*print_ins)(ACPI_WHEA_HEADER *),
74		    void (*print_flags)(ACPI_WHEA_HEADER *));
75static uint64_t	acpi_select_address(uint32_t, uint64_t);
76
77/* Handlers for each table */
78static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
79static void	acpi_print_cpu(u_char cpu_id);
80static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
81static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
82static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
83		    uint64_t apic_addr);
84static void	acpi_print_mps_flags(uint16_t flags);
85static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
86static void	acpi_print_local_nmi(u_int local_int, uint16_t mps_flags);
87static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
88static void	acpi_handle_bert(ACPI_TABLE_HEADER *sdp);
89static void	acpi_handle_bgrt(ACPI_TABLE_HEADER *sdp);
90static void	acpi_handle_boot(ACPI_TABLE_HEADER *sdp);
91static void	acpi_handle_cpep(ACPI_TABLE_HEADER *sdp);
92static void	acpi_handle_csrt(ACPI_TABLE_HEADER *sdp);
93static void	acpi_handle_dbgp(ACPI_TABLE_HEADER *sdp);
94static void	acpi_handle_dbg2(ACPI_TABLE_HEADER *sdp);
95static void	acpi_handle_einj(ACPI_TABLE_HEADER *sdp);
96static void	acpi_handle_erst(ACPI_TABLE_HEADER *sdp);
97static void	acpi_handle_gtdt(ACPI_TABLE_HEADER *sdp);
98static void	acpi_handle_hest(ACPI_TABLE_HEADER *sdp);
99static void	acpi_handle_iort(ACPI_TABLE_HEADER *sdp);
100static void	acpi_handle_lpit(ACPI_TABLE_HEADER *sdp);
101static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
102static void	acpi_handle_msct(ACPI_TABLE_HEADER *sdp);
103static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
104static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
105static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
106static void	acpi_handle_pcct(ACPI_TABLE_HEADER *sdp);
107static void	acpi_handle_pptt(ACPI_TABLE_HEADER *sdp);
108static void	acpi_handle_sbst(ACPI_TABLE_HEADER *sdp);
109static void	acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
110static void	acpi_handle_spcr(ACPI_TABLE_HEADER *sdp);
111static void	acpi_handle_spmi(ACPI_TABLE_HEADER *sdp);
112static void	acpi_print_srat_cpu(uint8_t type, uint32_t apic_id,
113		    uint32_t proximity_domain,
114		    uint32_t flags, uint32_t clockdomain, uint8_t sapic_eid);
115static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
116static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
117static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
118static void	acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
119static void	acpi_handle_tpm2(ACPI_TABLE_HEADER *sdp);
120static void	acpi_print_nfit(ACPI_NFIT_HEADER *nfit);
121static void	acpi_handle_nfit(ACPI_TABLE_HEADER *sdp);
122static void	acpi_handle_uefi(ACPI_TABLE_HEADER *sdp);
123static void	acpi_handle_waet(ACPI_TABLE_HEADER *sdp);
124static void	acpi_handle_wdat(ACPI_TABLE_HEADER *sdp);
125static void	acpi_handle_wddt(ACPI_TABLE_HEADER *sdp);
126static void	acpi_handle_wdrt(ACPI_TABLE_HEADER *sdp);
127static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
128static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
129static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
130static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
131static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
132static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
133static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
134static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
135		    void (*action)(ACPI_SUBTABLE_HEADER *));
136static void	acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
137		    void (*action)(ACPI_NFIT_HEADER *));
138
139/* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
140static int addr_size;
141
142/* Strings used in the TCPA table */
143static const char *tcpa_event_type_strings[] = {
144	"PREBOOT Certificate",
145	"POST Code",
146	"Unused",
147	"No Action",
148	"Separator",
149	"Action",
150	"Event Tag",
151	"S-CRTM Contents",
152	"S-CRTM Version",
153	"CPU Microcode",
154	"Platform Config Flags",
155	"Table of Devices",
156	"Compact Hash",
157	"IPL",
158	"IPL Partition Data",
159	"Non-Host Code",
160	"Non-Host Config",
161	"Non-Host Info"
162};
163
164static const char *TCPA_pcclient_strings[] = {
165	"<undefined>",
166	"SMBIOS",
167	"BIS Certificate",
168	"POST BIOS ROM Strings",
169	"ESCD",
170	"CMOS",
171	"NVRAM",
172	"Option ROM Execute",
173	"Option ROM Configurateion",
174	"<undefined>",
175	"Option ROM Microcode Update ",
176	"S-CRTM Version String",
177	"S-CRTM Contents",
178	"POST Contents",
179	"Table of Devices",
180};
181
182#define	PRINTFLAG_END()		printflag_end()
183
184static char pf_sep = '{';
185
186static void
187printflag_end(void)
188{
189
190	if (pf_sep == ',') {
191		printf("}");
192	} else if (pf_sep == '{') {
193		printf("{}");
194	}
195	pf_sep = '{';
196	printf("\n");
197}
198
199static void
200printflag(uint64_t var, uint64_t mask, const char *name)
201{
202
203	if (var & mask) {
204		printf("%c%s", pf_sep, name);
205		pf_sep = ',';
206	}
207}
208
209static void
210acpi_print_string(char *s, size_t length)
211{
212	int	c;
213
214	/* Trim trailing spaces and NULLs */
215	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
216		length--;
217
218	while (length--) {
219		c = *s++;
220		if (c == '\0')
221			return;
222		putchar(c);
223	}
224}
225
226static void
227acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
228{
229	switch (gas->SpaceId) {
230	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
231		if (gas->BitWidth <= 32)
232			printf("0x%08x:%u[%u] (Memory)",
233			    (u_int)gas->Address, gas->BitOffset,
234			    gas->BitWidth);
235		else
236			printf("0x%016jx:%u[%u] (Memory)",
237			    (uintmax_t)gas->Address, gas->BitOffset,
238			    gas->BitWidth);
239		break;
240	case ACPI_ADR_SPACE_SYSTEM_IO:
241		printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
242		    gas->BitOffset, gas->BitWidth);
243		break;
244	case ACPI_ADR_SPACE_PCI_CONFIG:
245		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
246		       (uint16_t)((gas->Address >> 16) & 0xffff),
247		       (uint16_t)gas->Address);
248		break;
249	/* XXX How to handle these below? */
250	case ACPI_ADR_SPACE_EC:
251		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
252		       gas->BitOffset, gas->BitWidth);
253		break;
254	case ACPI_ADR_SPACE_SMBUS:
255		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
256		       gas->BitOffset, gas->BitWidth);
257		break;
258	case ACPI_ADR_SPACE_CMOS:
259	case ACPI_ADR_SPACE_PCI_BAR_TARGET:
260	case ACPI_ADR_SPACE_IPMI:
261	case ACPI_ADR_SPACE_GPIO:
262	case ACPI_ADR_SPACE_GSBUS:
263	case ACPI_ADR_SPACE_PLATFORM_COMM:
264	case ACPI_ADR_SPACE_FIXED_HARDWARE:
265	default:
266		printf("0x%016jx (SpaceID=%hhu)", (uintmax_t)gas->Address,
267		    gas->SpaceId);
268		break;
269	}
270}
271
272static void
273acpi_print_pci(uint16_t vendorid, uint16_t deviceid,
274    uint8_t seg, uint8_t bus, uint8_t device, uint8_t func)
275{
276	if (vendorid == 0xffff && deviceid == 0xffff) {
277		printf("\tPCI Device=NONE\n");
278		return;
279	}
280
281	printf("\tPCI device={\n");
282	printf("\t\tVendor=0x%x\n", vendorid);
283	printf("\t\tDevice=0x%x\n", deviceid);
284	printf("\n");
285	printf("\t\tSegment Group=%d\n", seg);
286	printf("\t\tBus=%d\n", bus);
287	printf("\t\tDevice=%d\n", device);
288	printf("\t\tFunction=%d\n", func);
289	printf("\t}\n");
290}
291
292static void
293acpi_print_pci_sbdf(uint8_t seg, uint8_t bus, uint8_t device, uint8_t func)
294{
295	if (bus == 0xff && device == 0xff && func == 0xff) {
296		printf("\tPCI Device=NONE\n");
297		return;
298	}
299
300	printf("\tPCI device={\n");
301	printf("\t\tSegment Group=%d\n", seg);
302	printf("\t\tBus=%d\n", bus);
303	printf("\t\tDevice=%d\n", device);
304	printf("\t\tFunction=%d\n", func);
305	printf("\t}\n");
306}
307
308#ifdef notyet
309static void
310acpi_print_hest_errorseverity(uint32_t error)
311{
312	printf("\tError Severity={ ");
313	switch (error) {
314	case 0:
315		printf("Recoverable");
316		break;
317	case 1:
318		printf("Fatal");
319		break;
320	case 2:
321		printf("Corrected");
322		break;
323	case 3:
324		printf("None");
325		break;
326	default:
327		printf("%d (reserved)", error);
328		break;
329	}
330	printf("}\n");
331}
332#endif
333
334static void
335acpi_print_hest_errorbank(ACPI_HEST_IA_ERROR_BANK *bank)
336{
337	printf("\n");
338	printf("\tBank Number=%d\n", bank->BankNumber);
339	printf("\tClear Status On Init={%s}\n",
340		bank->ClearStatusOnInit ? "NO" : "YES");
341	printf("\tStatus Data Format={ ");
342	switch (bank->StatusFormat) {
343	case 0:
344		printf("IA32 MCA");
345		break;
346	case 1:
347		printf("EMT64 MCA");
348		break;
349	case 2:
350		printf("AMD64 MCA");
351		break;
352	}
353	printf(" }\n");
354
355	if (bank->ControlRegister)
356		printf("\tControl Register=0x%x\n", bank->ControlRegister);
357	printf("\tControl Init Data=0x%"PRIx64"\n", bank->ControlData);
358	printf("\tStatus MSR=0x%x\n", bank->StatusRegister);
359	printf("\tAddress MSR=0x%x\n", bank->AddressRegister);
360	printf("\tMisc MSR=0x%x\n", bank->MiscRegister);
361}
362
363static void
364acpi_print_hest_header(ACPI_HEST_HEADER *hest)
365{
366	printf("\tType={");
367	switch (hest->Type) {
368	case ACPI_HEST_TYPE_IA32_CHECK:
369		printf("IA32 Machine Check Exception");
370		break;
371	case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
372		printf("IA32 Corrected Machine Check");
373		break;
374	case ACPI_HEST_TYPE_IA32_NMI:
375		printf("IA32 Non-Maskable Interrupt");
376		break;
377	case ACPI_HEST_TYPE_NOT_USED3:
378	case ACPI_HEST_TYPE_NOT_USED4:
379	case ACPI_HEST_TYPE_NOT_USED5:
380		printf("unused type: %d", hest->Type);
381		break;
382	case ACPI_HEST_TYPE_AER_ROOT_PORT:
383		printf("PCI Express Root Port AER");
384		break;
385	case ACPI_HEST_TYPE_AER_ENDPOINT:
386		printf("PCI Express Endpoint AER");
387		break;
388	case ACPI_HEST_TYPE_AER_BRIDGE:
389		printf("PCI Express/PCI-X Bridge AER");
390		break;
391	case ACPI_HEST_TYPE_GENERIC_ERROR:
392		printf("Generic Hardware Error Source");
393		break;
394	case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
395		printf("Generic Hardware Error Source version 2");
396		break;
397	case ACPI_HEST_TYPE_RESERVED:
398	default:
399		printf("Reserved (%d)", hest->Type);
400		break;
401	}
402	printf("}\n");
403	printf("\tSourceId=%d\n", hest->SourceId);
404}
405
406static void
407acpi_print_hest_aer_common(ACPI_HEST_AER_COMMON *data)
408{
409
410#define PRINTFLAG(var, flag)	printflag((var), ACPI_HEST_## flag, #flag)
411
412	printf("\tFlags=");
413	PRINTFLAG(data->Flags, FIRMWARE_FIRST);
414	PRINTFLAG(data->Flags, GLOBAL);
415	PRINTFLAG(data->Flags, GHES_ASSIST);
416	PRINTFLAG_END();
417
418#undef PRINTFLAG
419
420	printf("\tEnabled={ %s ", data->Flags ? "YES" : "NO");
421	if (data->Flags & ACPI_HEST_FIRMWARE_FIRST)
422		printf("(ignored) ");
423	printf("}\n");
424	printf("\tNumber of Record to pre-allocate=%d\n",
425		data->RecordsToPreallocate);
426	printf("\tMax. Sections per Record=%d\n", data->MaxSectionsPerRecord);
427	if (!(data->Flags & ACPI_HEST_GLOBAL))
428		acpi_print_pci_sbdf(0, data->Bus, data->Device, data->Function);
429	printf("\tDevice Control=0x%x\n", data->DeviceControl);
430	printf("\tUncorrectable Error Mask Register=0x%x\n",
431		data->UncorrectableMask);
432	printf("\tUncorrectable Error Severity Register=0x%x\n",
433		data->UncorrectableSeverity);
434	printf("\tCorrectable Error Mask Register=0x%x\n",
435		data->CorrectableMask);
436	printf("\tAdvanced Capabilities Register=0x%x\n",
437		data->AdvancedCapabilities);
438}
439
440static void
441acpi_print_hest_notify(ACPI_HEST_NOTIFY *notify)
442{
443	printf("\tHW Error Notification={\n");
444	printf("\t\tType={");
445	switch (notify->Type) {
446	case ACPI_HEST_NOTIFY_POLLED:
447		printf("POLLED");
448		break;
449	case ACPI_HEST_NOTIFY_EXTERNAL:
450		printf("EXTERN");
451		break;
452	case ACPI_HEST_NOTIFY_LOCAL:
453		printf("LOCAL");
454		break;
455	case ACPI_HEST_NOTIFY_SCI:
456		printf("SCI");
457		break;
458	case ACPI_HEST_NOTIFY_NMI:
459		printf("NMI");
460		break;
461	case ACPI_HEST_NOTIFY_CMCI:
462		printf("CMCI");
463		break;
464	case ACPI_HEST_NOTIFY_MCE:
465		printf("MCE");
466		break;
467	case ACPI_HEST_NOTIFY_GPIO:
468		printf("GPIO-Signal");
469		break;
470	case ACPI_HEST_NOTIFY_SEA:
471		printf("ARMv8 SEA");
472		break;
473	case ACPI_HEST_NOTIFY_SEI:
474		printf("ARMv8 SEI");
475		break;
476	case ACPI_HEST_NOTIFY_GSIV:
477		printf("External Interrupt - GSIV");
478		break;
479	case ACPI_HEST_NOTIFY_RESERVED:
480		printf("RESERVED");
481		break;
482	default:
483		printf("%d (reserved)", notify->Type);
484		break;
485	}
486	printf("}\n");
487
488	printf("\t\tLength=%d\n", notify->Length);
489
490#define PRINTFLAG(var, flag)	printflag((var), ACPI_HEST_## flag, #flag)
491
492	printf("\t\tConfig Write Enable=");
493	PRINTFLAG(notify->ConfigWriteEnable, TYPE);
494	PRINTFLAG(notify->ConfigWriteEnable, POLL_INTERVAL);
495	PRINTFLAG(notify->ConfigWriteEnable, POLL_THRESHOLD_VALUE);
496	PRINTFLAG(notify->ConfigWriteEnable, POLL_THRESHOLD_WINDOW);
497	PRINTFLAG(notify->ConfigWriteEnable, ERR_THRESHOLD_VALUE);
498	PRINTFLAG(notify->ConfigWriteEnable, ERR_THRESHOLD_WINDOW);
499	PRINTFLAG_END();
500
501#undef PRINTFLAG
502
503	printf("\t\tPoll Interval=%d msec\n", notify->PollInterval);
504	printf("\t\tInterrupt Vector=%d\n", notify->Vector);
505	printf("\t\tSwitch To Polling Threshold Value=%d\n",
506		notify->PollingThresholdValue);
507	printf("\t\tSwitch To Polling Threshold Window=%d msec\n",
508		notify->PollingThresholdWindow);
509	printf("\t\tError Threshold Value=%d\n",
510		notify->ErrorThresholdValue);
511	printf("\t\tError Threshold Window=%d msec\n",
512		notify->ErrorThresholdWindow);
513	printf("\t}\n");
514}
515
516#ifdef notyet
517static void
518acpi_print_hest_generic_status(ACPI_HEST_GENERIC_STATUS *data)
519{
520	uint32_t i, pos, entries;
521	ACPI_HEST_GENERIC_DATA *gen;
522
523	entries = data->BlockStatus & ACPI_HEST_ERROR_ENTRY_COUNT;
524
525	printf("\tGeneric Error Status={\n");
526	printf("\t\tBlock Status={ ");
527	if (data->BlockStatus & ACPI_HEST_UNCORRECTABLE)
528		printf("UNCORRECTABLE");
529	if (data->BlockStatus & ACPI_HEST_CORRECTABLE)
530		printf("CORRECTABLE");
531	if (data->BlockStatus & ACPI_HEST_MULTIPLE_UNCORRECTABLE)
532		printf("MULTIPLE UNCORRECTABLE");
533	if (data->BlockStatus & ACPI_HEST_MULTIPLE_CORRECTABLE)
534		printf("MULTIPLE CORRECTABLE");
535	printf(" }\n");
536	printf("\t\tEntry Count=%d\n", entries);
537	printf("\t\tRaw Data Offset=%d\n", data->RawDataOffset);
538	printf("\t\tRaw Data Length=%d\n", data->RawDataLength);
539	printf("\t\tData Length=%d\n", data->DataLength);
540	printf("\t");
541	acpi_print_hest_errorseverity(data->ErrorSeverity);
542	printf("\t}\n");
543
544	pos = sizeof(ACPI_HEST_GENERIC_STATUS);
545	for (i = 0; i < entries; i++) {
546		gen = (ACPI_HEST_GENERIC_DATA *)((char *)data + pos);
547		acpi_print_hest_generic_data(gen);
548		pos += sizeof(ACPI_HEST_GENERIC_DATA);
549	}
550}
551#endif
552
553#ifdef notyet
554static void
555acpi_print_hest_generic_data(ACPI_HEST_GENERIC_DATA *data)
556{
557	printf("\tGeneric Error Data={\n");
558	printf("\t\tSectionType=");
559	acpi_print_string((char *)data->SectionType, sizeof(data->SectionType));
560	printf("\n\t");
561	acpi_print_hest_errorseverity(data->ErrorSeverity);
562	printf("\t\tRevision=0x%x\n", data->Revision);
563	printf("\t\tValidation Bits=0x%x\n", data->ValidationBits);
564	printf("\t\tFlags=0x%x\n", data->Flags);
565	printf("\t\tData Length=%d\n", data->ErrorDataLength);
566	printf("\t\tField Replication Unit Id=");
567	acpi_print_string((char *)data->FruId, sizeof(data->FruId));
568	printf("\n");
569	printf("\t\tField Replication Unit=");
570	acpi_print_string((char *)data->FruText, sizeof(data->FruText));
571	printf("\n");
572	printf("\t}\n");
573}
574#endif
575
576static void
577acpi_print_whea(ACPI_WHEA_HEADER *whea,
578    void (*print_action)(ACPI_WHEA_HEADER *),
579    void (*print_ins)(ACPI_WHEA_HEADER *),
580    void (*print_flags)(ACPI_WHEA_HEADER *))
581{
582	printf("\n");
583
584	print_action(whea);
585	print_ins(whea);
586	if (print_flags)
587		print_flags(whea);
588	printf("\tRegisterRegion=");
589	acpi_print_gas(&whea->RegisterRegion);
590	printf("\n");
591	printf("\tMASK=0x%08"PRIx64"\n", whea->Mask);
592}
593
594static void
595acpi_print_hest_ia32_check(ACPI_HEST_IA_MACHINE_CHECK *data)
596{
597	uint32_t i, pos;
598	ACPI_HEST_IA_ERROR_BANK *bank;
599
600	acpi_print_hest_header(&data->Header);
601	printf("\tFlags={ ");
602	if (data->Flags & ACPI_HEST_FIRMWARE_FIRST)
603		printf("FIRMWARE_FIRST");
604	printf(" }\n");
605	printf("\tEnabled={ %s }\n", data->Enabled ? "YES" : "NO");
606	printf("\tNumber of Record to pre-allocate=%d\n",
607		data->RecordsToPreallocate);
608	printf("\tMax Sections per Record=%d\n",
609		data->MaxSectionsPerRecord);
610	printf("\tGlobal Capability Init Data=0x%"PRIx64"\n",
611		data->GlobalCapabilityData);
612	printf("\tGlobal Control Init Data=0x%"PRIx64"\n",
613		data->GlobalControlData);
614	printf("\tNumber of Hardware Error Reporting Banks=%d\n",
615		data->NumHardwareBanks);
616
617	pos = sizeof(ACPI_HEST_IA_MACHINE_CHECK);
618	for (i = 0; i < data->NumHardwareBanks; i++) {
619		bank = (ACPI_HEST_IA_ERROR_BANK *)((char *)data + pos);
620		acpi_print_hest_errorbank(bank);
621		pos += sizeof(ACPI_HEST_IA_ERROR_BANK);
622	}
623}
624
625static void
626acpi_print_hest_ia32_correctedcheck(ACPI_HEST_IA_CORRECTED *data)
627{
628	uint32_t i, pos;
629	ACPI_HEST_IA_ERROR_BANK *bank;
630
631	acpi_print_hest_header(&data->Header);
632	printf("\tFlags={ ");
633	if (data->Flags & ACPI_HEST_FIRMWARE_FIRST)
634		printf("FIRMWARE_FIRST");
635	printf(" }\n");
636	printf("\tEnabled={ %s }\n", data->Enabled ? "YES" : "NO");
637	printf("\tNumber of Record to pre-allocate=%d\n",
638		data->RecordsToPreallocate);
639	printf("\tMax Sections per Record=%d\n",
640		data->MaxSectionsPerRecord);
641	acpi_print_hest_notify(&data->Notify);
642
643	printf("\tNumber of Hardware Error Reporting Banks=%d\n",
644		data->NumHardwareBanks);
645
646	pos = sizeof(ACPI_HEST_IA_MACHINE_CHECK);
647	for (i = 0; i < data->NumHardwareBanks; i++) {
648		bank = (ACPI_HEST_IA_ERROR_BANK *)((char *)data + pos);
649		acpi_print_hest_errorbank(bank);
650		pos += sizeof(ACPI_HEST_IA_ERROR_BANK);
651	}
652}
653
654static void
655acpi_print_hest_ia32_nmi(ACPI_HEST_IA_NMI *data)
656{
657	acpi_print_hest_header(&data->Header);
658	printf("\tNumber of Record to pre-allocate=%d\n",
659		data->RecordsToPreallocate);
660	printf("\tMax Sections per Record=%d\n",
661		data->MaxSectionsPerRecord);
662	printf("\tMax Raw Data Length=%d\n",
663		data->MaxRawDataLength);
664}
665
666static void
667acpi_print_hest_aer_root(ACPI_HEST_AER_ROOT *data)
668{
669	acpi_print_hest_header(&data->Header);
670	acpi_print_hest_aer_common(&data->Aer);
671	printf("Root Error Command Register=0x%x\n", data->RootErrorCommand);
672}
673
674static void
675acpi_print_hest_aer_endpoint(ACPI_HEST_AER *data)
676{
677	acpi_print_hest_header(&data->Header);
678	acpi_print_hest_aer_common(&data->Aer);
679}
680
681static void
682acpi_print_hest_aer_bridge(ACPI_HEST_AER_BRIDGE *data)
683{
684	acpi_print_hest_header(&data->Header);
685	acpi_print_hest_aer_common(&data->Aer);
686
687	printf("\tSecondary Uncorrectable Error Mask Register=0x%x\n",
688		data->UncorrectableMask2);
689	printf("\tSecondary Uncorrectable Error Severity Register=0x%x\n",
690		data->UncorrectableSeverity2);
691	printf("\tSecondory Advanced Capabilities Register=0x%x\n",
692		data->AdvancedCapabilities2);
693}
694
695static void
696acpi_print_hest_generic(ACPI_HEST_GENERIC *data)
697{
698	acpi_print_hest_header(&data->Header);
699	if (data->RelatedSourceId != 0xffff)
700		printf("\tReleated SourceId=%d\n", data->RelatedSourceId);
701	printf("\tEnabled={%s}\n", data->Enabled ? "YES" : "NO");
702	printf("\tNumber of Records to pre-allocate=%u\n",
703		data->RecordsToPreallocate);
704	printf("\tMax Sections per Record=%u\n", data->MaxSectionsPerRecord);
705	printf("\tMax Raw Data Length=%u\n", data->MaxRawDataLength);
706	printf("\tError Status Address=");
707	acpi_print_gas(&data->ErrorStatusAddress);
708	printf("\n");
709	acpi_print_hest_notify(&data->Notify);
710	printf("\tError Block Length=%u\n", data->ErrorBlockLength);
711}
712
713static void
714acpi_print_hest_generic_v2(ACPI_HEST_GENERIC_V2 *data)
715{
716
717	/* The first 64 bytes are the same as ACPI_HEST_GENERIC */
718	acpi_print_hest_generic((ACPI_HEST_GENERIC *)data);
719
720	printf("\tError Status Address");
721	acpi_print_gas(&data->ReadAckRegister);
722	printf("\n\tRead Ack Preserve=0x%016jx\n",
723	    (uintmax_t)data->ReadAckPreserve);
724	printf("\tRead Ack Write=0x%016jx\n",
725	    (uintmax_t)data->ReadAckWrite);
726}
727
728static void
729acpi_handle_hest(ACPI_TABLE_HEADER *sdp)
730{
731	ACPI_TABLE_HEST *hest;
732	ACPI_HEST_HEADER *subhest;
733	uint32_t i, pos;
734
735	printf(BEGIN_COMMENT);
736	acpi_print_sdt(sdp);
737	hest = (ACPI_TABLE_HEST *)sdp;
738
739	printf("\tError Source Count=%d\n", hest->ErrorSourceCount);
740	pos = sizeof(ACPI_TABLE_HEST);
741	for (i = 0; i < hest->ErrorSourceCount; i++) {
742		subhest = (ACPI_HEST_HEADER *)((char *)hest + pos);
743		printf("\n");
744
745		switch (subhest->Type) {
746		case ACPI_HEST_TYPE_IA32_CHECK:
747			acpi_print_hest_ia32_check(
748				(ACPI_HEST_IA_MACHINE_CHECK *)subhest);
749			pos += sizeof(ACPI_HEST_IA_MACHINE_CHECK);
750			break;
751
752		case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
753			acpi_print_hest_ia32_correctedcheck(
754				(ACPI_HEST_IA_CORRECTED *)subhest);
755			pos += sizeof(ACPI_HEST_IA_CORRECTED);
756			break;
757
758		case ACPI_HEST_TYPE_IA32_NMI:
759			acpi_print_hest_ia32_nmi(
760				(ACPI_HEST_IA_NMI *)subhest);
761			pos += sizeof(ACPI_HEST_IA_NMI);
762			break;
763
764		case ACPI_HEST_TYPE_NOT_USED3:
765		case ACPI_HEST_TYPE_NOT_USED4:
766		case ACPI_HEST_TYPE_NOT_USED5:
767			pos += sizeof(ACPI_HEST_HEADER);
768			break;
769
770		case ACPI_HEST_TYPE_AER_ROOT_PORT:
771			acpi_print_hest_aer_root((ACPI_HEST_AER_ROOT *)subhest);
772			pos += sizeof(ACPI_HEST_AER_ROOT);
773			break;
774
775		case ACPI_HEST_TYPE_AER_ENDPOINT:
776			acpi_print_hest_aer_endpoint((ACPI_HEST_AER *)subhest);
777			pos += sizeof(ACPI_HEST_AER);
778			break;
779
780		case ACPI_HEST_TYPE_AER_BRIDGE:
781			acpi_print_hest_aer_bridge((ACPI_HEST_AER_BRIDGE *)subhest);
782			pos += sizeof(ACPI_HEST_AER_BRIDGE);
783			break;
784
785		case ACPI_HEST_TYPE_GENERIC_ERROR:
786			acpi_print_hest_generic((ACPI_HEST_GENERIC *)subhest);
787			pos += sizeof(ACPI_HEST_GENERIC);
788			break;
789
790		case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
791			acpi_print_hest_generic_v2(
792				(ACPI_HEST_GENERIC_V2 *)subhest);
793			pos += sizeof(ACPI_HEST_GENERIC_V2);
794			break;
795
796		case ACPI_HEST_TYPE_RESERVED:
797		default:
798			pos += sizeof(ACPI_HEST_HEADER);
799			break;
800		}
801	}
802
803	printf(END_COMMENT);
804}
805
806static uint64_t
807acpi_select_address(uint32_t addr32, uint64_t addr64)
808{
809
810	if (addr64 == 0)
811		return addr32;
812
813	if ((addr32 != 0) && ((addr64 & 0xfffffff) != addr32)) {
814		/*
815		 * A few systems (e.g., IBM T23) have an RSDP that claims
816		 * revision 2 but the 64 bit addresses are invalid.  If
817		 * revision 2 and the 32 bit address is non-zero but the
818		 * 32 and 64 bit versions don't match, prefer the 32 bit
819		 * version for all subsequent tables.
820		 */
821		return addr32;
822	}
823
824	return addr64;
825}
826
827static void
828acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
829{
830	ACPI_TABLE_HEADER *dsdp;
831	ACPI_TABLE_FACS	*facs;
832	ACPI_TABLE_FADT *fadt;
833
834	fadt = (ACPI_TABLE_FADT *)sdp;
835	acpi_print_fadt(sdp);
836
837	if (acpi_select_address(fadt->Facs, fadt->XFacs) == 0) {
838		if ((fadt->Flags & ACPI_FADT_HW_REDUCED) == 0)
839			errx(EXIT_FAILURE, "Missing FACS and HW_REDUCED_ACPI flag not set in FADT");
840	} else if ((fadt->Flags & ACPI_FADT_HW_REDUCED) == 0) {
841		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(
842			acpi_select_address(fadt->Facs, fadt->XFacs));
843		if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
844			errx(EXIT_FAILURE, "FACS is corrupt");
845		acpi_print_facs(facs);
846	}
847
848	dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(
849		acpi_select_address(fadt->Dsdt, fadt->XDsdt));
850	if (memcmp(dsdp->Signature, ACPI_SIG_DSDT, 4) != 0)
851		errx(EXIT_FAILURE, "DSDT signature mismatch");
852	if (acpi_checksum(dsdp, dsdp->Length))
853		errx(EXIT_FAILURE, "DSDT is corrupt");
854	acpi_print_dsdt(dsdp);
855}
856
857static void
858acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
859    void (*action)(ACPI_SUBTABLE_HEADER *))
860{
861	ACPI_SUBTABLE_HEADER *subtable;
862	char *end;
863
864	subtable = first;
865	end = (char *)table + table->Length;
866	while ((char *)subtable < end) {
867		printf("\n");
868		if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
869			warnx("invalid subtable length %u", subtable->Length);
870			return;
871		}
872		action(subtable);
873		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
874		    subtable->Length);
875	}
876}
877
878static void
879acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
880    void (*action)(ACPI_NFIT_HEADER *))
881{
882	ACPI_NFIT_HEADER *subtable;
883	char *end;
884
885	subtable = first;
886	end = (char *)table + table->Length;
887	while ((char *)subtable < end) {
888		printf("\n");
889		if (subtable->Length < sizeof(ACPI_NFIT_HEADER)) {
890			warnx("invalid subtable length %u", subtable->Length);
891			return;
892		}
893		action(subtable);
894		subtable = (ACPI_NFIT_HEADER *)((char *)subtable +
895		    subtable->Length);
896	}
897}
898
899static void
900acpi_print_cpu(u_char cpu_id)
901{
902
903	printf("\tACPI CPU=");
904	if (cpu_id == 0xff)
905		printf("ALL\n");
906	else
907		printf("%d\n", (u_int)cpu_id);
908}
909
910static void
911acpi_print_cpu_uid(uint32_t uid, char *uid_string)
912{
913
914	printf("\tUID=%d", uid);
915	if (uid_string != NULL)
916		printf(" (%s)", uid_string);
917	printf("\n");
918}
919
920static void
921acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
922{
923
924	printf("\tFlags={");
925	if (flags & ACPI_MADT_ENABLED)
926		printf("ENABLED");
927	else
928		printf("DISABLED");
929	printf("}\n");
930	printf("\tAPIC ID=%d\n", apic_id);
931}
932
933static void
934acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
935{
936
937	printf("\tAPIC ID=%d\n", apic_id);
938	printf("\tINT BASE=%d\n", int_base);
939	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
940}
941
942static void
943acpi_print_mps_flags(uint16_t flags)
944{
945
946	printf("\tFlags={Polarity=");
947	switch (flags & ACPI_MADT_POLARITY_MASK) {
948	case ACPI_MADT_POLARITY_CONFORMS:
949		printf("conforming");
950		break;
951	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
952		printf("active-hi");
953		break;
954	case ACPI_MADT_POLARITY_ACTIVE_LOW:
955		printf("active-lo");
956		break;
957	default:
958		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
959		break;
960	}
961	printf(", Trigger=");
962	switch (flags & ACPI_MADT_TRIGGER_MASK) {
963	case ACPI_MADT_TRIGGER_CONFORMS:
964		printf("conforming");
965		break;
966	case ACPI_MADT_TRIGGER_EDGE:
967		printf("edge");
968		break;
969	case ACPI_MADT_TRIGGER_LEVEL:
970		printf("level");
971		break;
972	default:
973		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
974	}
975	printf("}\n");
976}
977
978static void
979acpi_print_gicc_flags(uint32_t flags)
980{
981
982	printf("\tFlags={");
983	if (flags & ACPI_MADT_ENABLED)
984		printf("enabled");
985	else
986		printf("disabled");
987	printf(", Performance intr=");
988	if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
989		printf("edge");
990	else
991		printf("level");
992	printf(", VGIC intr=");
993	if (flags & ACPI_MADT_VGIC_IRQ_MODE)
994		printf("edge");
995	else
996		printf("level");
997	printf("}\n");
998}
999
1000static void
1001acpi_print_intr(uint32_t intr, uint16_t mps_flags)
1002{
1003
1004	printf("\tINTR=%d\n", intr);
1005	acpi_print_mps_flags(mps_flags);
1006}
1007
1008static void
1009acpi_print_local_nmi(u_int local_int, uint16_t mps_flags)
1010{
1011
1012	printf("\tLINT Pin=%d\n", local_int);
1013	acpi_print_mps_flags(mps_flags);
1014}
1015
1016static const char *apic_types[] = {
1017    [ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
1018    [ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
1019    [ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
1020    [ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
1021    [ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
1022    [ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
1023    [ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
1024    [ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
1025    [ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
1026    [ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
1027    [ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
1028    [ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
1029    [ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
1030    [ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
1031    [ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
1032    [ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
1033};
1034
1035static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
1036					    "Corrected Platform Error" };
1037
1038static void
1039acpi_print_gicm_flags(ACPI_MADT_GENERIC_MSI_FRAME *gicm)
1040{
1041	uint32_t flags = gicm->Flags;
1042
1043	printf("\tFLAGS={");
1044	if (flags & ACPI_MADT_OVERRIDE_SPI_VALUES)
1045		printf("SPI Count/Base Select");
1046	printf("}\n");
1047}
1048
1049static void
1050acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
1051{
1052	ACPI_MADT_LOCAL_APIC *lapic;
1053	ACPI_MADT_IO_APIC *ioapic;
1054	ACPI_MADT_INTERRUPT_OVERRIDE *over;
1055	ACPI_MADT_NMI_SOURCE *nmi;
1056	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
1057	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
1058	ACPI_MADT_IO_SAPIC *iosapic;
1059	ACPI_MADT_LOCAL_SAPIC *lsapic;
1060	ACPI_MADT_INTERRUPT_SOURCE *isrc;
1061	ACPI_MADT_LOCAL_X2APIC *x2apic;
1062	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
1063	ACPI_MADT_GENERIC_INTERRUPT *gicc;
1064	ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
1065	ACPI_MADT_GENERIC_MSI_FRAME *gicm;
1066	ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
1067	ACPI_MADT_GENERIC_TRANSLATOR *gict;
1068
1069	if (mp->Type < __arraycount(apic_types))
1070		printf("\tType=%s\n", apic_types[mp->Type]);
1071	else
1072		printf("\tType=%d (unknown)\n", mp->Type);
1073	switch (mp->Type) {
1074	case ACPI_MADT_TYPE_LOCAL_APIC:
1075		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
1076		acpi_print_cpu(lapic->ProcessorId);
1077		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
1078		break;
1079	case ACPI_MADT_TYPE_IO_APIC:
1080		ioapic = (ACPI_MADT_IO_APIC *)mp;
1081		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
1082		    ioapic->Address);
1083		break;
1084	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
1085		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
1086		printf("\tBUS=%d\n", (u_int)over->Bus);
1087		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
1088		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
1089		break;
1090	case ACPI_MADT_TYPE_NMI_SOURCE:
1091		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
1092		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
1093		break;
1094	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
1095		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
1096		acpi_print_cpu(lapic_nmi->ProcessorId);
1097		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
1098		break;
1099	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
1100		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
1101		printf("\tLocal APIC ADDR=0x%016jx\n",
1102		    (uintmax_t)lapic_over->Address);
1103		break;
1104	case ACPI_MADT_TYPE_IO_SAPIC:
1105		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
1106		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
1107		    iosapic->Address);
1108		break;
1109	case ACPI_MADT_TYPE_LOCAL_SAPIC:
1110		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
1111		acpi_print_cpu(lsapic->ProcessorId);
1112		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
1113		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
1114		if (mp->Length > offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
1115			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
1116		break;
1117	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
1118		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
1119		if (isrc->Type < __arraycount(platform_int_types))
1120			printf("\tType=%s\n", platform_int_types[isrc->Type]);
1121		else
1122			printf("\tType=%d (unknown)\n", isrc->Type);
1123		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
1124		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
1125		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
1126		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
1127		break;
1128	case ACPI_MADT_TYPE_LOCAL_X2APIC:
1129		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
1130		acpi_print_cpu_uid(x2apic->Uid, NULL);
1131		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
1132		break;
1133	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
1134		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
1135		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
1136		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
1137		break;
1138	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
1139		gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
1140		acpi_print_cpu_uid(gicc->Uid, NULL);
1141		printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
1142		acpi_print_gicc_flags(gicc->Flags);
1143		printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
1144		printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
1145		printf("\tParked ADDR=%016jx\n",
1146		    (uintmax_t)gicc->ParkedAddress);
1147		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
1148		printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
1149		printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
1150		printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
1151		printf("\tGICR ADDR=%016jx\n",
1152		    (uintmax_t)gicc->GicrBaseAddress);
1153		printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
1154		printf("\tEfficiency Class=%d\n", (u_int)gicc->EfficiencyClass);
1155		break;
1156	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
1157		gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
1158		printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
1159		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
1160		printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
1161		printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
1162		break;
1163	case ACPI_MADT_TYPE_GENERIC_MSI_FRAME:
1164		gicm = (ACPI_MADT_GENERIC_MSI_FRAME*)mp;
1165		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicm->BaseAddress);
1166		acpi_print_gicm_flags(gicm);
1167		printf("\tSPI Count=%u\n", gicm->SpiCount);
1168		printf("\tSPI Base=%u\n", gicm->SpiBase);
1169		break;
1170	case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
1171		gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
1172		printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
1173		printf("\tLength=%08x\n", gicr->Length);
1174		break;
1175	case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
1176		gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
1177		printf("\tGIC ITS ID=%d\n", gict->TranslationId);
1178		printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
1179		break;
1180	}
1181}
1182
1183#ifdef notyet
1184static void
1185acpi_print_bert_region(ACPI_BERT_REGION *region)
1186{
1187	uint32_t i, pos, entries;
1188	ACPI_HEST_GENERIC_DATA *data;
1189
1190	printf("\n");
1191	printf("\tBlockStatus={ ");
1192
1193	if (region->BlockStatus & ACPI_BERT_UNCORRECTABLE)
1194		printf("Uncorrectable");
1195	if (region->BlockStatus & ACPI_BERT_CORRECTABLE)
1196		printf("Correctable");
1197	if (region->BlockStatus & ACPI_BERT_MULTIPLE_UNCORRECTABLE)
1198		printf("Multiple Uncorrectable");
1199	if (region->BlockStatus & ACPI_BERT_MULTIPLE_CORRECTABLE)
1200		printf("Multiple Correctable");
1201	entries = region->BlockStatus & ACPI_BERT_ERROR_ENTRY_COUNT;
1202	printf(", Error Entry Count=%d", entries);
1203	printf("}\n");
1204
1205	printf("\tRaw Data Offset=0x%x\n", region->RawDataOffset);
1206	printf("\tRaw Data Length=0x%x\n", region->RawDataLength);
1207	printf("\tData Length=0x%x\n", region->DataLength);
1208
1209	acpi_print_hest_errorseverity(region->ErrorSeverity);
1210
1211	pos = sizeof(ACPI_BERT_REGION);
1212	for (i = 0; i < entries; i++) {
1213		data = (ACPI_HEST_GENERIC_DATA *)((char *)region + pos);
1214		acpi_print_hest_generic_data(data);
1215		pos += sizeof(ACPI_HEST_GENERIC_DATA);
1216	}
1217}
1218#endif
1219
1220static void
1221acpi_handle_bert(ACPI_TABLE_HEADER *sdp)
1222{
1223	ACPI_TABLE_BERT *bert;
1224
1225	printf(BEGIN_COMMENT);
1226	acpi_print_sdt(sdp);
1227	bert = (ACPI_TABLE_BERT *)sdp;
1228
1229	printf("\tLength of Boot Error Region=%d bytes\n", bert->RegionLength);
1230	printf("\tPhysical Address of Region=0x%"PRIx64"\n", bert->Address);
1231
1232	printf(END_COMMENT);
1233}
1234
1235static void
1236acpi_handle_bgrt(ACPI_TABLE_HEADER *sdp)
1237{
1238	ACPI_TABLE_BGRT *bgrt;
1239	unsigned int degree;
1240
1241	printf(BEGIN_COMMENT);
1242	acpi_print_sdt(sdp);
1243	bgrt = (ACPI_TABLE_BGRT *)sdp;
1244
1245	printf("\tVersion=%hu\n", bgrt->Version);
1246	degree = ((unsigned int)(bgrt->Status & ACPI_BGRT_ORIENTATION_OFFSET)
1247	    >> 1) * 90;
1248	printf("\tDegree=%u\n", degree);
1249	printf("\tDisplayed=%u\n", bgrt->Status & ACPI_BGRT_DISPLAYED);
1250	printf("\tImage Type=");
1251	switch (bgrt->ImageType) {
1252	case 0:
1253		printf("Bitmap\n");
1254		break;
1255	default:
1256		printf("reserved (0x%hhx)\n", bgrt->ImageType);
1257		break;
1258	}
1259	printf("\tImage Address=0x%"PRIx64"\n", bgrt->ImageAddress);
1260	printf("\tImage Offset X=0x%08x\n", bgrt->ImageOffsetX);
1261	printf("\tImage Offset Y=0x%08x\n", bgrt->ImageOffsetY);
1262
1263	printf(END_COMMENT);
1264}
1265
1266static void
1267acpi_handle_boot(ACPI_TABLE_HEADER *sdp)
1268{
1269	ACPI_TABLE_BOOT *boot;
1270
1271	printf(BEGIN_COMMENT);
1272	acpi_print_sdt(sdp);
1273	boot = (ACPI_TABLE_BOOT *)sdp;
1274	printf("\tCMOS Index=0x%02x\n", boot->CmosIndex);
1275	printf(END_COMMENT);
1276}
1277
1278static void
1279acpi_handle_cpep(ACPI_TABLE_HEADER *sdp)
1280{
1281	ACPI_TABLE_CPEP *cpep;
1282	ACPI_CPEP_POLLING *poll;
1283	uint32_t cpep_pos;
1284
1285	printf(BEGIN_COMMENT);
1286	acpi_print_sdt(sdp);
1287	cpep = (ACPI_TABLE_CPEP *)sdp;
1288
1289	cpep_pos = sizeof(ACPI_TABLE_CPEP);
1290	while (cpep_pos < sdp->Length) {
1291		poll = (ACPI_CPEP_POLLING *)((char *)cpep + cpep_pos);
1292		acpi_print_cpu(poll->Id);
1293		printf("\tACPI CPU EId=%d\n", poll->Eid);
1294		printf("\tPoll Interval=%d msec\n", poll->Interval);
1295		cpep_pos += sizeof(ACPI_CPEP_POLLING);
1296	}
1297	printf(END_COMMENT);
1298}
1299
1300static void
1301acpi_print_csrt_resource_group(ACPI_CSRT_GROUP *grp)
1302{
1303	ACPI_CSRT_DESCRIPTOR *desc;
1304
1305	printf("\tLength=%u\n", grp->Length);
1306	printf("\tVendorId=");
1307	acpi_print_string((char *)&grp->VendorId, 4);
1308	printf("\n");
1309	if (grp->SubvendorId != 0) {
1310		printf("\tSubvendorId=");
1311		acpi_print_string((char *)&grp->SubvendorId, 4);
1312		printf("\n");
1313	}
1314	printf("\tDeviceId=0x%08x\n", grp->DeviceId);
1315	if (grp->SubdeviceId != 0)
1316		printf("\tSubdeviceId=0x%08x\n", grp->SubdeviceId);
1317	printf("\tRevision=%hu\n", grp->Revision);
1318	printf("\tSharedInfoLength=%u\n", grp->SharedInfoLength);
1319
1320	/* Next is Shared Info */
1321	if (grp->SharedInfoLength != 0) {
1322		printf("\tShared Info ");
1323		acpi_dump_bytes((uint8_t *)(grp + 1),
1324		    grp->SharedInfoLength, 1);
1325	}
1326
1327	/* And then, Resource Descriptors */
1328	desc = (ACPI_CSRT_DESCRIPTOR *)
1329	    ((vaddr_t)(grp + 1) + grp->SharedInfoLength);
1330	while (desc < (ACPI_CSRT_DESCRIPTOR *)((vaddr_t)grp + grp->Length)) {
1331		bool unknownsubytpe = false;
1332		printf("\n\tLength=%u\n", desc->Length);
1333		printf("\tResource Type=");
1334		switch (desc->Type) {
1335		case ACPI_CSRT_TYPE_INTERRUPT:
1336			printf("Interrupt");
1337			switch (desc->Subtype) {
1338			case ACPI_CSRT_XRUPT_LINE:
1339				printf("(Interrupt line)\n");
1340				break;
1341			case ACPI_CSRT_XRUPT_CONTROLLER:
1342				printf("(Interrupt controller)\n");
1343				break;
1344			default:
1345				unknownsubytpe = true;
1346				break;
1347			}
1348			break;
1349		case ACPI_CSRT_TYPE_TIMER:
1350			printf("Timer");
1351			switch (desc->Subtype) {
1352			case ACPI_CSRT_TIMER:
1353				printf("\n");
1354				break;
1355			default:
1356				unknownsubytpe = true;
1357				break;
1358			}
1359			break;
1360		case ACPI_CSRT_TYPE_DMA:
1361			printf("DMA");
1362			switch (desc->Subtype) {
1363			case ACPI_CSRT_DMA_CHANNEL:
1364				printf("(DMA channel)\n");
1365				break;
1366			case ACPI_CSRT_DMA_CONTROLLER:
1367				printf("(DMA controller)\n");
1368				break;
1369			default:
1370				unknownsubytpe = true;
1371				break;
1372			}
1373			break;
1374		case 0x0004: /* XXX Platform Security */
1375			printf("Platform Security");
1376			switch (desc->Subtype) {
1377			case 0x0001:
1378				printf("\n");
1379				/* Platform Security */
1380				break;
1381			default:
1382				unknownsubytpe = true;
1383				break;
1384			}
1385			break;
1386		default:
1387			printf("Unknown (%hx)\n", desc->Type);
1388			break;
1389		}
1390		if (unknownsubytpe)
1391			printf("(unknown subtype(%hx))\n", desc->Subtype);
1392
1393		printf("\tUID=0x%08x\n", desc->Uid);
1394		printf("\tVendor defined info ");
1395		acpi_dump_bytes((uint8_t *)(desc + 1),
1396		    desc->Length - sizeof(ACPI_CSRT_DESCRIPTOR), 1);
1397
1398		/* Next */
1399		desc = (ACPI_CSRT_DESCRIPTOR *)((vaddr_t)desc + desc->Length);
1400	}
1401}
1402
1403static void
1404acpi_handle_csrt(ACPI_TABLE_HEADER *sdp)
1405{
1406	ACPI_CSRT_GROUP *grp;
1407	uint totallen = sdp->Length;
1408
1409	printf(BEGIN_COMMENT);
1410	acpi_print_sdt(sdp);
1411	grp = (ACPI_CSRT_GROUP *)(sdp + 1);
1412
1413	while (grp < (ACPI_CSRT_GROUP *)((vaddr_t)sdp + totallen)) {
1414		printf("\n");
1415		acpi_print_csrt_resource_group(grp);
1416
1417		/* Next */
1418		grp = (ACPI_CSRT_GROUP *)((vaddr_t)grp + grp->Length);
1419	}
1420
1421	printf(END_COMMENT);
1422}
1423
1424static void
1425acpi_handle_dbgp(ACPI_TABLE_HEADER *sdp)
1426{
1427	ACPI_TABLE_DBGP *dbgp;
1428
1429	printf(BEGIN_COMMENT);
1430	acpi_print_sdt(sdp);
1431	dbgp = (ACPI_TABLE_DBGP *)sdp;
1432	printf("\tType={");
1433	switch (dbgp->Type) {
1434	case 0:
1435		printf("full 16550");
1436		break;
1437	case 1:
1438		printf("subset of 16550");
1439		break;
1440	}
1441	printf("}\n");
1442	printf("\tDebugPort=");
1443	acpi_print_gas(&dbgp->DebugPort);
1444	printf("\n");
1445	printf(END_COMMENT);
1446}
1447
1448/* This function is used by DBG2 and SPCR. */
1449static void
1450acpi_print_dbg2_serial_subtype(uint16_t subtype)
1451{
1452
1453	switch (subtype) {
1454	case ACPI_DBG2_16550_COMPATIBLE:
1455		printf("Fully 16550 compatible\n");
1456		break;
1457	case ACPI_DBG2_16550_SUBSET:
1458		printf("16550 subset with DBGP Rev. 1\n");
1459		break;
1460	case ACPI_DBG2_ARM_PL011:
1461		printf("ARM PL011\n");
1462		break;
1463	case ACPI_DBG2_ARM_SBSA_32BIT:
1464		printf("ARM SBSA 32bit only\n");
1465		break;
1466	case ACPI_DBG2_ARM_SBSA_GENERIC:
1467		printf("ARM SBSA Generic\n");
1468		break;
1469	case ACPI_DBG2_ARM_DCC:
1470		printf("ARM DCC\n");
1471		break;
1472	case ACPI_DBG2_BCM2835:
1473		printf("BCM2835\n");
1474		break;
1475	default:
1476		printf("reserved (%04hx)\n", subtype);
1477		break;
1478	}
1479}
1480
1481static void
1482acpi_print_dbg2_device(ACPI_DBG2_DEVICE *dev)
1483{
1484
1485	printf("\t\tRevision=%u\n", dev->Revision);
1486	printf("\t\tLength=%u\n", dev->Length);
1487	printf("\t\tRegisterCount=%u\n", dev->RegisterCount);
1488
1489	printf("\t\tNamepath=");
1490	acpi_print_string((char *)((vaddr_t)dev + dev->NamepathOffset),
1491	    dev->NamepathLength);
1492	printf("\n");
1493
1494	if (dev->OemDataLength) {
1495		printf("\t\tOemDataLength=%u\n", dev->OemDataLength);
1496		printf("\t\tOemDataOffset=%u\n", dev->OemDataOffset);
1497		/* XXX need dump */
1498	}
1499
1500	printf("\t\tPortType=");
1501	switch (dev->PortType) {
1502	case ACPI_DBG2_SERIAL_PORT:
1503		printf("Serial\n" "\t\tPortSubtype=");
1504		acpi_print_dbg2_serial_subtype(dev->PortSubtype);
1505		break;
1506	case ACPI_DBG2_1394_PORT:
1507		printf("IEEE1394\n" "\t\tPortSubtype=");
1508		if (dev->PortSubtype == ACPI_DBG2_1394_STANDARD)
1509			printf("Standard\n");
1510		else
1511			printf("reserved (%04hx)\n", dev->PortSubtype);
1512		break;
1513	case ACPI_DBG2_USB_PORT:
1514		printf("USB\n" "\t\tPortSubtype=");
1515		switch (dev->PortSubtype) {
1516		case ACPI_DBG2_USB_XHCI:
1517			printf("XHCIn");
1518			break;
1519		case ACPI_DBG2_USB_EHCI:
1520			printf("EHCI\n");
1521			break;
1522		default:
1523			printf("reserved (%04hx)\n", dev->PortSubtype);
1524			break;
1525		}
1526		break;
1527	case ACPI_DBG2_NET_PORT:
1528		printf("Net\n" "\t\tPciVendorID=%04x\n", dev->PortSubtype);
1529		break;
1530	default:
1531		printf("reserved (%04hx)\n", dev->PortType);
1532		printf("\t\tPortSubtype=reserved (%04hx)\n", dev->PortSubtype);
1533		break;
1534	}
1535
1536	printf("\t\tBaseAddressOffset=0x%04x\n", dev->BaseAddressOffset);
1537	printf("\t\tAddressSizeOffset=0x%04x\n", dev->AddressSizeOffset);
1538}
1539
1540static void
1541acpi_handle_dbg2(ACPI_TABLE_HEADER *sdp)
1542{
1543	ACPI_TABLE_DBG2 *dbg2;
1544	ACPI_DBG2_DEVICE *device;
1545	unsigned int i;
1546
1547	printf(BEGIN_COMMENT);
1548	acpi_print_sdt(sdp);
1549	dbg2 = (ACPI_TABLE_DBG2 *)sdp;
1550
1551	printf("\tCount=%u\n", dbg2->InfoCount);
1552	device = (ACPI_DBG2_DEVICE *)((vaddr_t)sdp + dbg2->InfoOffset);
1553	for (i = 0; i < dbg2->InfoCount; i++) {
1554		printf("\tDevice %u={\n", i);
1555		acpi_print_dbg2_device(device);
1556		printf("\t}\n");
1557		device++;
1558	}
1559
1560	printf(END_COMMENT);
1561}
1562
1563static void
1564acpi_print_einj_action(ACPI_WHEA_HEADER *whea)
1565{
1566	printf("\tACTION={");
1567	switch (whea->Action) {
1568	case ACPI_EINJ_BEGIN_OPERATION:
1569		printf("Begin Operation");
1570		break;
1571	case ACPI_EINJ_GET_TRIGGER_TABLE:
1572		printf("Get Trigger Table");
1573		break;
1574	case ACPI_EINJ_SET_ERROR_TYPE:
1575		printf("Set Error Type");
1576		break;
1577	case ACPI_EINJ_GET_ERROR_TYPE:
1578		printf("Get Error Type");
1579		break;
1580	case ACPI_EINJ_END_OPERATION:
1581		printf("End Operation");
1582		break;
1583	case ACPI_EINJ_EXECUTE_OPERATION:
1584		printf("Execute Operation");
1585		break;
1586	case ACPI_EINJ_CHECK_BUSY_STATUS:
1587		printf("Check Busy Status");
1588		break;
1589	case ACPI_EINJ_GET_COMMAND_STATUS:
1590		printf("Get Command Status");
1591		break;
1592	case ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS:
1593		printf("Set Error Type With Address");
1594		break;
1595	case ACPI_EINJ_GET_EXECUTE_TIMINGS:
1596		printf("Get Execute Operation Timings");
1597		break;
1598	case ACPI_EINJ_ACTION_RESERVED:
1599		printf("Preserved");
1600		break;
1601	case ACPI_EINJ_TRIGGER_ERROR:
1602		printf("Trigger Error");
1603		break;
1604	default:
1605		printf("%d", whea->Action);
1606		break;
1607	}
1608	printf("}\n");
1609}
1610
1611static void
1612acpi_print_einj_instruction(ACPI_WHEA_HEADER *whea)
1613{
1614	uint32_t ins = whea->Instruction;
1615
1616	printf("\tINSTRUCTION={");
1617	switch (ins) {
1618	case ACPI_EINJ_READ_REGISTER:
1619		printf("Read Register");
1620		break;
1621	case ACPI_EINJ_READ_REGISTER_VALUE:
1622		printf("Read Register Value");
1623		break;
1624	case ACPI_EINJ_WRITE_REGISTER:
1625		printf("Write Register");
1626		break;
1627	case ACPI_EINJ_WRITE_REGISTER_VALUE:
1628		printf("Write Register Value");
1629		break;
1630	case ACPI_EINJ_NOOP:
1631		printf("Noop");
1632		break;
1633	case ACPI_EINJ_INSTRUCTION_RESERVED:
1634		printf("Reserved");
1635		break;
1636	default:
1637		printf("%d", ins);
1638		break;
1639	}
1640	printf("}\n");
1641}
1642
1643static void
1644acpi_print_einj_flags(ACPI_WHEA_HEADER *whea)
1645{
1646	uint32_t flags = whea->Flags;
1647
1648	printf("\tFLAGS={");
1649	if (flags & ACPI_EINJ_PRESERVE)
1650		printf("PRESERVED");
1651	printf("}\n");
1652}
1653
1654static void
1655acpi_handle_einj(ACPI_TABLE_HEADER *sdp)
1656{
1657	ACPI_TABLE_EINJ *einj;
1658	ACPI_EINJ_ENTRY *einj_entry;
1659	uint32_t einj_pos;
1660	u_int i;
1661
1662	printf(BEGIN_COMMENT);
1663	acpi_print_sdt(sdp);
1664	einj = (ACPI_TABLE_EINJ *)sdp;
1665
1666	printf("\tHeader Length=%d\n", einj->HeaderLength);
1667	printf("\tFlags=0x%x\n", einj->Flags);
1668	printf("\tEntries=%d\n", einj->Entries);
1669
1670	einj_pos = sizeof(ACPI_TABLE_EINJ);
1671	for (i = 0; i < einj->Entries; i++) {
1672		einj_entry = (ACPI_EINJ_ENTRY *)((char *)einj + einj_pos);
1673		acpi_print_whea(&einj_entry->WheaHeader,
1674		    acpi_print_einj_action, acpi_print_einj_instruction,
1675		    acpi_print_einj_flags);
1676		einj_pos += sizeof(ACPI_EINJ_ENTRY);
1677	}
1678	printf(END_COMMENT);
1679}
1680
1681static void
1682acpi_print_erst_action(ACPI_WHEA_HEADER *whea)
1683{
1684	printf("\tACTION={");
1685	switch (whea->Action) {
1686	case ACPI_ERST_BEGIN_WRITE:
1687		printf("Begin Write");
1688		break;
1689	case ACPI_ERST_BEGIN_READ:
1690		printf("Begin Read");
1691		break;
1692	case ACPI_ERST_BEGIN_CLEAR:
1693		printf("Begin Clear");
1694		break;
1695	case ACPI_ERST_END:
1696		printf("End");
1697		break;
1698	case ACPI_ERST_SET_RECORD_OFFSET:
1699		printf("Set Record Offset");
1700		break;
1701	case ACPI_ERST_EXECUTE_OPERATION:
1702		printf("Execute Operation");
1703		break;
1704	case ACPI_ERST_CHECK_BUSY_STATUS:
1705		printf("Check Busy Status");
1706		break;
1707	case ACPI_ERST_GET_COMMAND_STATUS:
1708		printf("Get Command Status");
1709		break;
1710	case ACPI_ERST_GET_RECORD_ID:
1711		printf("Get Record ID");
1712		break;
1713	case ACPI_ERST_SET_RECORD_ID:
1714		printf("Set Record ID");
1715		break;
1716	case ACPI_ERST_GET_RECORD_COUNT:
1717		printf("Get Record Count");
1718		break;
1719	case ACPI_ERST_BEGIN_DUMMY_WRIITE:
1720		printf("Begin Dummy Write");
1721		break;
1722	case ACPI_ERST_NOT_USED:
1723		printf("Unused");
1724		break;
1725	case ACPI_ERST_GET_ERROR_RANGE:
1726		printf("Get Error Range");
1727		break;
1728	case ACPI_ERST_GET_ERROR_LENGTH:
1729		printf("Get Error Length");
1730		break;
1731	case ACPI_ERST_GET_ERROR_ATTRIBUTES:
1732		printf("Get Error Attributes");
1733		break;
1734	case ACPI_ERST_EXECUTE_TIMINGS:
1735		printf("Execute Operation Timings");
1736		break;
1737	case ACPI_ERST_ACTION_RESERVED:
1738		printf("Reserved");
1739		break;
1740	default:
1741		printf("%d", whea->Action);
1742		break;
1743	}
1744	printf("}\n");
1745}
1746
1747static void
1748acpi_print_erst_instruction(ACPI_WHEA_HEADER *whea)
1749{
1750	printf("\tINSTRUCTION={");
1751	switch (whea->Instruction) {
1752	case ACPI_ERST_READ_REGISTER:
1753		printf("Read Register");
1754		break;
1755	case ACPI_ERST_READ_REGISTER_VALUE:
1756		printf("Read Register Value");
1757		break;
1758	case ACPI_ERST_WRITE_REGISTER:
1759		printf("Write Register");
1760		break;
1761	case ACPI_ERST_WRITE_REGISTER_VALUE:
1762		printf("Write Register Value");
1763		break;
1764	case ACPI_ERST_NOOP:
1765		printf("Noop");
1766		break;
1767	case ACPI_ERST_LOAD_VAR1:
1768		printf("Load Var1");
1769		break;
1770	case ACPI_ERST_LOAD_VAR2:
1771		printf("Load Var2");
1772		break;
1773	case ACPI_ERST_STORE_VAR1:
1774		printf("Store Var1");
1775		break;
1776	case ACPI_ERST_ADD:
1777		printf("Add");
1778		break;
1779	case ACPI_ERST_SUBTRACT:
1780		printf("Subtract");
1781		break;
1782	case ACPI_ERST_ADD_VALUE:
1783		printf("Add Value");
1784		break;
1785	case ACPI_ERST_SUBTRACT_VALUE:
1786		printf("Subtract Value");
1787		break;
1788	case ACPI_ERST_STALL:
1789		printf("Stall");
1790		break;
1791	case ACPI_ERST_STALL_WHILE_TRUE:
1792		printf("Stall While True");
1793		break;
1794	case ACPI_ERST_SKIP_NEXT_IF_TRUE:
1795		printf("Skip Next If True");
1796		break;
1797	case ACPI_ERST_GOTO:
1798		printf("Goto");
1799		break;
1800	case ACPI_ERST_SET_SRC_ADDRESS_BASE:
1801		printf("Set Src Address Base");
1802		break;
1803	case ACPI_ERST_SET_DST_ADDRESS_BASE:
1804		printf("Set Dst Address Base");
1805		break;
1806	case ACPI_ERST_MOVE_DATA:
1807		printf("Move Data");
1808		break;
1809	case ACPI_ERST_INSTRUCTION_RESERVED:
1810		printf("Reserved");
1811		break;
1812	default:
1813		printf("%d (reserved)", whea->Instruction);
1814		break;
1815	}
1816	printf("}\n");
1817}
1818
1819static void
1820acpi_print_erst_flags(ACPI_WHEA_HEADER *whea)
1821{
1822	uint32_t flags = whea->Flags;
1823
1824	printf("\tFLAGS={");
1825	if (flags & ACPI_ERST_PRESERVE)
1826		printf("PRESERVED");
1827	printf("}\n");
1828}
1829
1830static void
1831acpi_handle_erst(ACPI_TABLE_HEADER *sdp)
1832{
1833	ACPI_TABLE_ERST *erst;
1834	ACPI_ERST_ENTRY *erst_entry;
1835	uint32_t erst_pos;
1836	u_int i;
1837
1838	printf(BEGIN_COMMENT);
1839	acpi_print_sdt(sdp);
1840	erst = (ACPI_TABLE_ERST *)sdp;
1841
1842	printf("\tHeader Length=%d\n", erst->HeaderLength);
1843	printf("\tEntries=%d\n", erst->Entries);
1844
1845	erst_pos = sizeof(ACPI_TABLE_ERST);
1846	for (i = 0; i < erst->Entries; i++) {
1847		erst_entry = (ACPI_ERST_ENTRY *)((char *)erst + erst_pos);
1848		acpi_print_whea(&erst_entry->WheaHeader,
1849		    acpi_print_erst_action, acpi_print_erst_instruction,
1850		    acpi_print_erst_flags);
1851		erst_pos += sizeof(ACPI_ERST_ENTRY);
1852	}
1853	printf(END_COMMENT);
1854}
1855
1856static void
1857acpi_print_gtd_timer(const char *name, uint32_t interrupt, uint32_t flags)
1858{
1859
1860	printf("\t%s Timer GSIV=%d\n", name, interrupt);
1861	printf("\t%s Flags={Mode=", name);
1862	if (flags & ACPI_GTDT_INTERRUPT_MODE)
1863		printf("edge");
1864	else
1865		printf("level");
1866	printf(", Polarity=");
1867	if (flags & ACPI_GTDT_INTERRUPT_POLARITY)
1868		printf("active-lo");
1869	else
1870		printf("active-hi");
1871	if (flags & ACPI_GTDT_ALWAYS_ON)
1872		printf(", always-on");
1873	printf("}\n");
1874}
1875
1876static void
1877acpi_print_gtd_block_timer_flags(const char *name, uint32_t interrupt,
1878    uint32_t flags)
1879{
1880
1881	printf("\t\t%s Timer GSIV=%d\n", name, interrupt);
1882	printf("\t\t%s Timer Flags={Mode=", name);
1883	if (flags & ACPI_GTDT_GT_IRQ_MODE)
1884		printf("Secure");
1885	else
1886		printf("Non-Secure");
1887	printf(", Polarity=");
1888	if (flags & ACPI_GTDT_GT_IRQ_POLARITY)
1889		printf("active-lo");
1890	else
1891		printf("active-hi");
1892	printf("}\n");
1893}
1894
1895static void
1896acpi_print_gtblock(ACPI_GTDT_TIMER_BLOCK *gtblock)
1897{
1898	ACPI_GTDT_TIMER_ENTRY *entry;
1899	unsigned int i;
1900
1901	printf("\tType=GT Block\n");
1902	printf("\tLength=%d\n", gtblock->Header.Length);
1903	/* XXX might not 8byte aligned */
1904	printf("\tBlockAddress=%016jx\n",
1905	    (uintmax_t)gtblock->BlockAddress);
1906
1907	printf("\tGT Block Timer Count=%d\n", gtblock->TimerCount);
1908	entry = (ACPI_GTDT_TIMER_ENTRY *)((vaddr_t)gtblock
1909	    + gtblock->TimerOffset);
1910	for (i = 0; i < gtblock->TimerCount; i++) {
1911		printf("\n");
1912		if (entry >= (ACPI_GTDT_TIMER_ENTRY *)((vaddr_t)gtblock
1913		    + gtblock->Header.Length)) {
1914			printf("\\ttWrong Timer entry\n");
1915			break;
1916		}
1917		printf("\t\tFrame Number=%d\n", entry->FrameNumber);
1918		/* XXX might not 8byte aligned */
1919		printf("\t\tBaseAddress=%016jx\n",
1920		    (uintmax_t)entry->BaseAddress);
1921		/* XXX might not 8byte aligned */
1922		printf("\t\tEl0BaseAddress=%016jx\n",
1923		    (uintmax_t)entry->El0BaseAddress);
1924
1925		acpi_print_gtd_block_timer_flags("Physical",
1926		    entry->TimerInterrupt, entry->TimerFlags);
1927		acpi_print_gtd_block_timer_flags("Virtual",
1928		    entry->VirtualTimerInterrupt, entry->VirtualTimerFlags);
1929
1930		printf("\t\tCommon Flags={Mode=");
1931		if (entry->CommonFlags & ACPI_GTDT_GT_IS_SECURE_TIMER)
1932			printf("Secure");
1933		else
1934			printf("Non-Secure");
1935		if (entry->CommonFlags & ACPI_GTDT_GT_ALWAYS_ON)
1936			printf(", always-on");
1937		printf("}\n");
1938
1939		entry++;
1940	}
1941}
1942
1943static void
1944acpi_print_sbsa_watchdog(ACPI_GTDT_WATCHDOG *wdog)
1945{
1946
1947	printf("\tType=Watchdog GT\n");
1948	printf("\tLength=%d\n", wdog->Header.Length);
1949	/* XXX might not 8byte aligned */
1950	printf("\tRefreshFrameAddress=%016jx\n",
1951	    (uintmax_t)wdog->RefreshFrameAddress);
1952	/* XXX might not 8byte aligned */
1953	printf("\tControlFrameAddress=%016jx\n",
1954	    (uintmax_t)wdog->ControlFrameAddress);
1955	printf("\tGSIV=%d\n", wdog->TimerInterrupt);
1956
1957	printf("\tFlags={Mode=");
1958	if (wdog->TimerFlags & ACPI_GTDT_WATCHDOG_IRQ_MODE)
1959		printf("edge");
1960	else
1961		printf("level");
1962	printf(", Polarity=");
1963	if (wdog->TimerFlags & ACPI_GTDT_WATCHDOG_IRQ_POLARITY)
1964		printf("active-lo");
1965	else
1966		printf("active-hi");
1967	if (wdog->TimerFlags & ACPI_GTDT_WATCHDOG_SECURE)
1968		printf(", Secure");
1969	else
1970		printf(", Non-Secure");
1971	printf("}\n");
1972}
1973
1974static void
1975acpi_handle_gtdt(ACPI_TABLE_HEADER *sdp)
1976{
1977	ACPI_TABLE_GTDT *gtdt;
1978	ACPI_GTDT_HEADER *hdr;
1979	u_int i;
1980
1981	printf(BEGIN_COMMENT);
1982	acpi_print_sdt(sdp);
1983	gtdt = (ACPI_TABLE_GTDT *)sdp;
1984
1985	printf("\tCounterBlockAddresss=%016jx\n",
1986	    (uintmax_t)gtdt->CounterBlockAddresss); /* XXX not 8byte aligned */
1987	printf("\tCounterReadBlockAddress=%016jx\n",
1988	    (uintmax_t)gtdt->CounterReadBlockAddress);
1989
1990#define PRINTTIMER(gtdt, name) acpi_print_gtd_timer(	\
1991		#name, (gtdt)-> name## Interrupt,	\
1992	(gtdt)-> name ## Flags)
1993
1994	PRINTTIMER(gtdt, SecureEl1);
1995	PRINTTIMER(gtdt, NonSecureEl1);
1996	PRINTTIMER(gtdt, VirtualTimer);
1997	PRINTTIMER(gtdt, NonSecureEl2);
1998
1999#undef PRINTTIMER
2000
2001	printf("\tPlatform Timer Count=%d\n", gtdt->PlatformTimerCount);
2002
2003	hdr = (ACPI_GTDT_HEADER *)((vaddr_t)sdp + gtdt->PlatformTimerOffset);
2004	for (i = 0; i < gtdt->PlatformTimerCount; i++) {
2005		printf("\n");
2006		if (hdr >= (ACPI_GTDT_HEADER *)((vaddr_t)sdp + sdp->Length)) {
2007			printf("\tWrong GTDT header"
2008			    "(type = %hhu, length = %hu)\n",
2009			    hdr->Type, hdr->Length);
2010			break;
2011		}
2012
2013		switch (hdr->Type) {
2014		case ACPI_GTDT_TYPE_TIMER_BLOCK:
2015			acpi_print_gtblock((ACPI_GTDT_TIMER_BLOCK *)hdr);
2016			break;
2017		case ACPI_GTDT_TYPE_WATCHDOG:
2018			acpi_print_sbsa_watchdog((ACPI_GTDT_WATCHDOG *)hdr);
2019			break;
2020		default:
2021			printf("\tUnknown Platform Timer Type"
2022			    "(type = %hhu, length = %hu)\n",
2023			    hdr->Type, hdr->Length);
2024			break;
2025		}
2026		/* Next */
2027		hdr = (ACPI_GTDT_HEADER *)((vaddr_t)hdr + hdr->Length);
2028	}
2029	printf(END_COMMENT);
2030}
2031
2032static void
2033acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
2034{
2035	ACPI_TABLE_MADT *madt;
2036
2037	printf(BEGIN_COMMENT);
2038	acpi_print_sdt(sdp);
2039	madt = (ACPI_TABLE_MADT *)sdp;
2040	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
2041	printf("\tFlags={");
2042	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
2043		printf("PC-AT");
2044	printf("}\n");
2045	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
2046	printf(END_COMMENT);
2047}
2048
2049static void
2050acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
2051{
2052	ACPI_TABLE_HPET *hpet;
2053
2054	printf(BEGIN_COMMENT);
2055	acpi_print_sdt(sdp);
2056	hpet = (ACPI_TABLE_HPET *)sdp;
2057	printf("\tHPET Number=%d\n", hpet->Sequence);
2058	printf("\tADDR=");
2059	acpi_print_gas(&hpet->Address);
2060	printf("\n\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
2061	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
2062	    8);
2063	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
2064	    1 : 0);
2065	printf("\tLegacy IRQ routing capable={");
2066	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
2067		printf("TRUE}\n");
2068	else
2069		printf("FALSE}\n");
2070	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
2071	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
2072	printf("\tFlags=0x%02x\n", hpet->Flags);
2073	printf(END_COMMENT);
2074}
2075
2076/*
2077 * IORT
2078 * I/O Remapping Table
2079 */
2080
2081static void acpi_print_iort_its_group(ACPI_IORT_NODE *);
2082static void acpi_print_iort_named_component(ACPI_IORT_NODE *);
2083static void acpi_print_iort_root_complex(ACPI_IORT_NODE *);
2084static void acpi_print_iort_smmuv1v2(ACPI_IORT_NODE *);
2085static void acpi_print_iort_smmuv3(ACPI_IORT_NODE *);
2086
2087struct iort_node_list {
2088	uint8_t	Type;
2089	const char *gname;
2090	void (*func)(ACPI_IORT_NODE *);
2091} iort_node_list [] = {
2092#define NDMAC(name)	ACPI_IORT_NODE_## name
2093#define PRFN(name)	acpi_print_iort_## name
2094	{ NDMAC(ITS_GROUP),	   "ITS group",       PRFN(its_group)},
2095	{ NDMAC(NAMED_COMPONENT),  "Named component", PRFN(named_component)},
2096	{ NDMAC(PCI_ROOT_COMPLEX), "Root complex",    PRFN(root_complex)},
2097	{ NDMAC(SMMU),		   "SMMUv1 or v2",    PRFN(smmuv1v2)},
2098	{ NDMAC(SMMU_V3),	   "SMMUv3",	      PRFN(smmuv3)},
2099	{ 255, NULL, NULL},
2100#undef NDMAC
2101#undef PRFN
2102};
2103
2104static void
2105acpi_print_iort_memory_access(ACPI_IORT_MEMORY_ACCESS *memacc)
2106{
2107
2108	printf("\tMemory Access={\n");
2109	printf("\t\tCacheCoherency=");
2110	switch (memacc->CacheCoherency) {
2111	case ACPI_IORT_NODE_COHERENT:
2112		printf("Fully coherent\n");
2113		break;
2114	case ACPI_IORT_NODE_NOT_COHERENT:
2115		printf("Not coherent\n");
2116		break;
2117	default:
2118		printf("reserved (%u)\n", memacc->CacheCoherency);
2119		break;
2120	}
2121	printf("\t\tAllocation Hints=");
2122#define	PRINTFLAG(var, flag)	printflag((var), ACPI_IORT_HT_## flag, #flag)
2123		PRINTFLAG(memacc->Hints, TRANSIENT);
2124		PRINTFLAG(memacc->Hints, WRITE);
2125		PRINTFLAG(memacc->Hints, READ);
2126		PRINTFLAG(memacc->Hints, OVERRIDE);
2127		PRINTFLAG_END();
2128#undef PRINTFLAG
2129	printf("\t\tMemory Access Flags=");
2130#define	PRINTFLAG(var, flag)	printflag((var), ACPI_IORT_MF_## flag, #flag)
2131		PRINTFLAG(memacc->MemoryFlags, COHERENCY);
2132		PRINTFLAG(memacc->MemoryFlags, ATTRIBUTES);
2133		PRINTFLAG_END();
2134#undef PRINTFLAG
2135	printf("\t}\n");
2136}
2137
2138static void
2139acpi_print_iort_its_group(ACPI_IORT_NODE *node)
2140{
2141	ACPI_IORT_ITS_GROUP *itsg = (ACPI_IORT_ITS_GROUP *)node->NodeData;
2142	uint32_t *idp;
2143	unsigned int i;
2144
2145	idp = itsg->Identifiers;
2146	for (i = 0; i < itsg->ItsCount; i++)
2147		printf("\tGIC ITS ID=%d\n", idp[i]);
2148}
2149
2150static void
2151acpi_print_iort_named_component(ACPI_IORT_NODE *node)
2152{
2153	ACPI_IORT_NAMED_COMPONENT *ncomp
2154	    = (ACPI_IORT_NAMED_COMPONENT *)node->NodeData;
2155
2156#define	PRINTFLAG(var, flag)	printflag((var), ACPI_IORT_NC_## flag, #flag)
2157	printf("\tNode Flags={PASID_BITS=%u",
2158	    (ncomp->NodeFlags & ACPI_IORT_NC_PASID_BITS) >> 1);
2159	pf_sep = ',';
2160	PRINTFLAG(ncomp->NodeFlags, STALL_SUPPORTED);
2161	PRINTFLAG_END();
2162#undef PRINTFLAG
2163	acpi_print_iort_memory_access(
2164		(ACPI_IORT_MEMORY_ACCESS *)&ncomp->MemoryProperties);
2165	printf("\tMemory address size=%hhu\n", ncomp->MemoryAddressLimit);
2166	printf("\tDevice object Name=%s\n", ncomp->DeviceName);
2167}
2168
2169static void
2170acpi_print_iort_root_complex(ACPI_IORT_NODE *node)
2171{
2172	ACPI_IORT_ROOT_COMPLEX *rcmp
2173	    = (ACPI_IORT_ROOT_COMPLEX *)node->NodeData;
2174
2175	acpi_print_iort_memory_access(
2176		(ACPI_IORT_MEMORY_ACCESS *)&rcmp->MemoryProperties);
2177	printf("\tATS Attribute=%s\n",
2178	    (rcmp->AtsAttribute & ACPI_IORT_ATS_SUPPORTED)
2179	    ? "supported" : "not supported");
2180	printf("\tPCI Segment=%u\n", rcmp->PciSegmentNumber);
2181	printf("\tMemory address size limit=%hhu\n", rcmp->MemoryAddressLimit);
2182}
2183
2184static void
2185acpi_print_iort_smmuv1v2_intflags(uint32_t flags)
2186{
2187
2188	printf("{Mode=");
2189	if (flags & 0x01)
2190		printf("edge");
2191	else
2192		printf("level");
2193	printf("}\n");
2194}
2195
2196static void
2197acpi_print_iort_smmuv1v2(ACPI_IORT_NODE *node)
2198{
2199	ACPI_IORT_SMMU *smmu = (ACPI_IORT_SMMU *)node->NodeData;
2200	ACPI_IORT_SMMU_GSI *gsi;
2201	uint64_t *iarray;
2202	unsigned int i;
2203
2204	printf("\tBase Address=%016jx\n", (uintmax_t)smmu->BaseAddress);
2205	printf("\tSpan=%016jx\n", (uintmax_t)smmu->Span);
2206	printf("\tModel=");
2207	switch (smmu->Model) {
2208	case ACPI_IORT_SMMU_V1:
2209		printf("Generic SMMUv1\n");
2210		break;
2211	case ACPI_IORT_SMMU_V2:
2212		printf("Generic SMMUv2\n");
2213		break;
2214	case ACPI_IORT_SMMU_CORELINK_MMU400:
2215		printf("Arm Corelink MMU-400\n");
2216		break;
2217	case ACPI_IORT_SMMU_CORELINK_MMU500:
2218		printf("Arm Corelink MMU-500\n");
2219		break;
2220	case ACPI_IORT_SMMU_CORELINK_MMU401:
2221		printf("Arm Corelink MMU-401\n");
2222		break;
2223	case ACPI_IORT_SMMU_CAVIUM_THUNDERX:
2224		printf("Cavium ThunderX SMMUv2\n");
2225		break;
2226	default:
2227		printf("reserved (%u)\n", smmu->Model);
2228		break;
2229	}
2230#define	PRINTFLAG(var, flag)	printflag((var), ACPI_IORT_SMMU_## flag, #flag)
2231	printf("\tFlags=");
2232	PRINTFLAG(smmu->Flags, DVM_SUPPORTED);
2233	PRINTFLAG(smmu->Flags, COHERENT_WALK);
2234	PRINTFLAG_END();
2235#undef PRINTFLAG
2236
2237	gsi = (ACPI_IORT_SMMU_GSI *)((vaddr_t)node
2238	    + smmu->GlobalInterruptOffset);
2239	printf("\tNSgIrpt=%u\n", gsi->NSgIrpt);
2240	printf("\tNSgIrptFlags=");
2241	acpi_print_iort_smmuv1v2_intflags(gsi->NSgIrptFlags);
2242	printf("\tNSgCfgIrpt=%u\n", gsi->NSgCfgIrpt);
2243	printf("\tNSgCfgIrptFlags=");
2244	acpi_print_iort_smmuv1v2_intflags(gsi->NSgCfgIrptFlags);
2245
2246	if (smmu->ContextInterruptCount != 0) {
2247		iarray = (uint64_t *)((vaddr_t)node
2248		    + smmu->ContextInterruptOffset);
2249		printf("\tContext Interrupts={\n");
2250		for (i = 0; i < smmu->ContextInterruptCount; i++) {
2251			printf("\t\tGSIV=%u\n",
2252			    (uint32_t)(iarray[i] & 0xffffffff));
2253			printf("\t\tFlags=%u\n", (uint32_t)(iarray[i] >> 32));
2254		}
2255	}
2256	if (smmu->PmuInterruptCount != 0) {
2257		iarray = (uint64_t *)((vaddr_t)node
2258		    + smmu->PmuInterruptOffset);
2259		printf("\tPmu Interrupts={\n");
2260		for (i = 0; i < smmu->PmuInterruptCount; i++) {
2261			printf("\t\tGSIV=%u\n",
2262			    (uint32_t)(iarray[i] & 0xffffffff));
2263			printf("\t\tFlags=%u\n", (uint32_t)(iarray[i] >> 32));
2264		}
2265	}
2266}
2267
2268static void
2269acpi_print_iort_smmuv3(ACPI_IORT_NODE *node)
2270{
2271	ACPI_IORT_SMMU_V3 *smmu = (ACPI_IORT_SMMU_V3 *)node->NodeData;
2272	uint8_t httuo;
2273
2274	printf("\tBase Address=%016jx\n", (uintmax_t)smmu->BaseAddress);
2275#define	PRINTFLAG(var, flag)	printflag((var), ACPI_IORT_SMMU_V3_## flag, \
2276	    #flag)
2277	httuo = __SHIFTOUT(smmu->Flags, ACPI_IORT_SMMU_V3_HTTU_OVERRIDE);
2278	printf("\tFlags={HTTU Override=%hhx", httuo);
2279	pf_sep = ',';
2280	PRINTFLAG(smmu->Flags, HTTU_OVERRIDE);
2281	PRINTFLAG(smmu->Flags, COHACC_OVERRIDE);
2282	PRINTFLAG(smmu->Flags, PXM_VALID);
2283	PRINTFLAG_END();
2284#undef PRINTFLAG
2285	printf("\tVATOS Address=%016jx\n", (uintmax_t)smmu->VatosAddress);
2286	printf("\tModel=");
2287	switch (smmu->Model) {
2288	case ACPI_IORT_SMMU_V3_GENERIC:
2289		printf("Generic SMMUv3\n");
2290		break;
2291	case ACPI_IORT_SMMU_V3_HISILICON_HI161X:
2292		printf("HiSilicon Hi161x SMMU-v3\n");
2293		break;
2294	case ACPI_IORT_SMMU_V3_CAVIUM_CN99XX:
2295		printf("Cavium CN99xx SMMU-v3\n");
2296		break;
2297	default:
2298		printf("reserved (%u)\n", smmu->Model);
2299		break;
2300	}
2301
2302	printf("\tEvent GSIV=%u\n", smmu->EventGsiv);
2303	printf("\tPRI GSIV=%u\n", smmu->PriGsiv);
2304	printf("\tGERR GSIV=%u\n", smmu->GerrGsiv);
2305	printf("\tSync GSIV=%u\n", smmu->SyncGsiv);
2306	printf("\tProximity domain=%u\n", smmu->Pxm);
2307
2308	/* XXX should we print the referred contents? */
2309	printf("\tDevice ID mapping index=%u\n", smmu->IdMappingIndex);
2310}
2311
2312static void
2313acpi_print_iort_node(ACPI_IORT_NODE *node)
2314{
2315	ACPI_IORT_ID_MAPPING *mapping;
2316	uint32_t offset;
2317	int datasize;
2318	bool dodump = false;
2319	struct iort_node_list *list;
2320	unsigned int i;
2321
2322	printf("\tLength=%hu\n", node->Length);
2323	printf("\tRevision=%hhu\n", node->Revision);
2324	printf("\tType=");
2325
2326	datasize = node->MappingOffset - offsetof(ACPI_IORT_NODE, NodeData);
2327	if (datasize != 0)
2328		dodump = true;
2329
2330	for (list = iort_node_list; list->gname != NULL; list++) {
2331		if (node->Type == list->Type) {
2332			printf("%s\n", list->gname);
2333			if (dodump)
2334				(*list->func)(node);
2335			break;
2336		}
2337	}
2338	if (list->gname == NULL)
2339		printf("reserved (0x%hhx)\n", node->Type);
2340
2341	printf("\tMappingCount=%u\n", node->MappingCount);
2342	if (node->MappingCount == 0)
2343		return;
2344
2345	offset = node->MappingOffset;
2346	printf("\tMapping offset=%u\n", offset);
2347	for (i = 0; i < node->MappingCount; i++) {
2348		mapping = (ACPI_IORT_ID_MAPPING *)((vaddr_t)node + offset);
2349		printf("\tMapping={\n");
2350		printf("\t\tInput base=%u\n", mapping->InputBase);
2351		printf("\t\tCount=%u\n", mapping->IdCount);
2352		printf("\t\tOutput base=%u\n", mapping->OutputBase);
2353		printf("\t\tOutput reference offset=%u\n",
2354		    mapping->OutputReference);
2355#define	PRINTFLAG(var, flag)	printflag((var), ACPI_IORT_ID_## flag, #flag)
2356		printf("\t\tFlags=");
2357		PRINTFLAG(mapping->Flags, SINGLE_MAPPING);
2358		PRINTFLAG_END();
2359#undef PRINTFLAG
2360		printf("\t}\n");
2361		offset += sizeof(ACPI_IORT_ID_MAPPING);
2362	}
2363}
2364
2365static void
2366acpi_handle_iort(ACPI_TABLE_HEADER *sdp)
2367{
2368	ACPI_TABLE_IORT *iort;
2369	ACPI_IORT_NODE *node;
2370	unsigned int i;
2371
2372	printf(BEGIN_COMMENT);
2373	acpi_print_sdt(sdp);
2374	iort = (ACPI_TABLE_IORT *)sdp;
2375	printf("\tIORT Nodes=%u\n", iort->NodeCount);
2376	printf("\tNode offset=%u\n", iort->NodeOffset);
2377
2378	node = (ACPI_IORT_NODE *)((vaddr_t)iort + iort->NodeOffset);
2379	for (i = 0; i < iort->NodeCount; i++) {
2380		printf("\n");
2381		acpi_print_iort_node(node);
2382
2383		/* Next */
2384		node = (ACPI_IORT_NODE *)((vaddr_t)node + node->Length);
2385	}
2386
2387	printf(END_COMMENT);
2388}
2389
2390static void
2391acpi_print_native_lpit(ACPI_LPIT_NATIVE *nl)
2392{
2393	printf("\tEntryTrigger=");
2394	acpi_print_gas(&nl->EntryTrigger);
2395	printf("\n\tResidency=%u\n", nl->Residency);
2396	printf("\tLatency=%u\n", nl->Latency);
2397	if (nl->Header.Flags & ACPI_LPIT_NO_COUNTER)
2398		printf("\tResidencyCounter=Not Present");
2399	else {
2400		printf("\tResidencyCounter=");
2401		acpi_print_gas(&nl->ResidencyCounter);
2402		printf("\n");
2403	}
2404	if (nl->CounterFrequency)
2405		printf("\tCounterFrequency=%ju\n", nl->CounterFrequency);
2406	else
2407		printf("\tCounterFrequency=TSC\n");
2408}
2409
2410static void
2411acpi_print_lpit(ACPI_LPIT_HEADER *lpit)
2412{
2413	if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
2414		printf("\tType=ACPI_LPIT_TYPE_NATIVE_CSTATE\n");
2415	else
2416		warnx("unknown LPIT type %u", lpit->Type);
2417
2418	printf("\tLength=%u\n", lpit->Length);
2419	printf("\tUniqueId=0x%04x\n", lpit->UniqueId);
2420#define	PRINTFLAG(var, flag)	printflag((var), ACPI_LPIT_## flag, #flag)
2421	printf("\tFlags=");
2422	PRINTFLAG(lpit->Flags, STATE_DISABLED);
2423	PRINTFLAG_END();
2424#undef PRINTFLAG
2425
2426	if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
2427		acpi_print_native_lpit((ACPI_LPIT_NATIVE *)lpit);
2428}
2429
2430static void
2431acpi_walk_lpit(ACPI_TABLE_HEADER *table, void *first,
2432    void (*action)(ACPI_LPIT_HEADER *))
2433{
2434	ACPI_LPIT_HEADER *subtable;
2435	char *end;
2436
2437	subtable = first;
2438	end = (char *)table + table->Length;
2439	while ((char *)subtable < end) {
2440		printf("\n");
2441		if (subtable->Length < sizeof(ACPI_LPIT_HEADER)) {
2442			warnx("invalid subtable length %u", subtable->Length);
2443			return;
2444		}
2445		action(subtable);
2446		subtable = (ACPI_LPIT_HEADER *)((char *)subtable +
2447		    subtable->Length);
2448	}
2449}
2450
2451static void
2452acpi_handle_lpit(ACPI_TABLE_HEADER *sdp)
2453{
2454	ACPI_TABLE_LPIT *lpit;
2455
2456	printf(BEGIN_COMMENT);
2457	acpi_print_sdt(sdp);
2458	lpit = (ACPI_TABLE_LPIT *)sdp;
2459	acpi_walk_lpit(sdp, (lpit + 1), acpi_print_lpit);
2460
2461	printf(END_COMMENT);
2462}
2463
2464static void
2465acpi_handle_msct(ACPI_TABLE_HEADER *sdp)
2466{
2467	ACPI_TABLE_MSCT *msct;
2468	ACPI_MSCT_PROXIMITY *msctentry;
2469	uint32_t pos;
2470
2471	printf(BEGIN_COMMENT);
2472	acpi_print_sdt(sdp);
2473	msct = (ACPI_TABLE_MSCT *)sdp;
2474
2475	printf("\tProximity Offset=0x%x\n", msct->ProximityOffset);
2476	printf("\tMax Proximity Domains=%d\n", msct->MaxProximityDomains);
2477	printf("\tMax Clock Domains=%d\n", msct->MaxClockDomains);
2478	printf("\tMax Physical Address=0x%"PRIx64"\n", msct->MaxAddress);
2479
2480	pos = msct->ProximityOffset;
2481	while (pos < msct->Header.Length) {
2482		msctentry = (ACPI_MSCT_PROXIMITY *)((char *)msct + pos);
2483		pos += msctentry->Length;
2484
2485		printf("\n");
2486		printf("\tRevision=%d\n", msctentry->Revision);
2487		printf("\tLength=%d\n", msctentry->Length);
2488		printf("\tRange Start=%d\n", msctentry->RangeStart);
2489		printf("\tRange End=%d\n", msctentry->RangeEnd);
2490		printf("\tProcessor Capacity=%d\n",
2491		    msctentry->ProcessorCapacity);
2492		printf("\tMemory Capacity=0x%"PRIx64" byte\n",
2493		    msctentry->MemoryCapacity);
2494	}
2495
2496	printf(END_COMMENT);
2497}
2498
2499static void
2500acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
2501{
2502	ACPI_TABLE_ECDT *ecdt;
2503
2504	printf(BEGIN_COMMENT);
2505	acpi_print_sdt(sdp);
2506	ecdt = (ACPI_TABLE_ECDT *)sdp;
2507	printf("\tEC_CONTROL=");
2508	acpi_print_gas(&ecdt->Control);
2509	printf("\n\tEC_DATA=");
2510	acpi_print_gas(&ecdt->Data);
2511	printf("\n\tUID=%#x, ", ecdt->Uid);
2512	printf("GPE_BIT=%#x\n", ecdt->Gpe);
2513	printf("\tEC_ID=%s\n", ecdt->Id);
2514	printf(END_COMMENT);
2515}
2516
2517static void
2518acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
2519{
2520	ACPI_TABLE_MCFG *mcfg;
2521	ACPI_MCFG_ALLOCATION *alloc;
2522	u_int i, entries;
2523
2524	printf(BEGIN_COMMENT);
2525	acpi_print_sdt(sdp);
2526	mcfg = (ACPI_TABLE_MCFG *)sdp;
2527	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
2528	    sizeof(ACPI_MCFG_ALLOCATION);
2529	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
2530	for (i = 0; i < entries; i++, alloc++) {
2531		printf("\n");
2532		printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
2533		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
2534		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
2535		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
2536	}
2537	printf(END_COMMENT);
2538}
2539
2540static void
2541acpi_print_pcct_subspace(ACPI_PCCT_SUBSPACE *subspace)
2542{
2543	printf("\tType=Generic Subspace\n");
2544	printf("\tBase Address=0x%016jx\n", subspace->BaseAddress);
2545	printf("\tLength=%jd\n", subspace->Length);
2546	printf("\tDoorbell Address=");
2547	acpi_print_gas(&subspace->DoorbellRegister);
2548	printf("\n");
2549	printf("\tDoorbell Preserve=0x%016jx\n", subspace->PreserveMask);
2550	printf("\tDoorbell Write=0x%016jx\n", subspace->WriteMask);
2551	printf("\tLatency=%u us\n", subspace->Latency);
2552	printf("\tMax Access Rate=%u\n", subspace->MaxAccessRate);
2553	printf("\tMin Turnaround Time=%u us\n", subspace->MinTurnaroundTime);
2554}
2555
2556static void
2557acpi_print_pcct_hw_reduced(ACPI_PCCT_HW_REDUCED *subspace)
2558{
2559	printf("\tType=HW-reduced Subspace\n");
2560	printf("\tPlatform Interrupt=%u", subspace->PlatformInterrupt);
2561	if (subspace->Flags & ACPI_PCCT_INTERRUPT_POLARITY) {
2562		printf(", Edge triggered");
2563	} else {
2564		printf(", Level triggered");
2565	}
2566	if (subspace->Flags & ACPI_PCCT_INTERRUPT_MODE) {
2567		printf(", Active low");
2568	} else {
2569		printf(", Active high");
2570	}
2571	printf("\n");
2572	printf("\tBase Address=0x%016jx\n", subspace->BaseAddress);
2573	printf("\tLength=%jd\n", subspace->Length);
2574	printf("\tDoorbell Register=");
2575	acpi_print_gas(&subspace->DoorbellRegister);
2576	printf("\n");
2577	printf("\tDoorbell Preserve=0x%016jx\n", subspace->PreserveMask);
2578	printf("\tDoorbell Write=0x%016jx\n", subspace->WriteMask);
2579	printf("\tLatency=%u us\n", subspace->Latency);
2580	printf("\tMax Access Rate=%u\n", subspace->MaxAccessRate);
2581	printf("\tMin Turnaround Time=%u us\n", subspace->MinTurnaroundTime);
2582}
2583
2584static void
2585acpi_print_pcct_hw_reduced_type2(ACPI_PCCT_HW_REDUCED_TYPE2 *subspace)
2586{
2587	printf("\tType=HW-reduced Subspace Type 2\n");
2588	printf("\tPlatform Interrupt=%u", subspace->PlatformInterrupt);
2589	if (subspace->Flags & ACPI_PCCT_INTERRUPT_POLARITY) {
2590		printf(", Edge triggered");
2591	} else {
2592		printf(", Level triggered");
2593	}
2594	if (subspace->Flags & ACPI_PCCT_INTERRUPT_MODE) {
2595		printf(", Active low");
2596	} else {
2597		printf(", Active high");
2598	}
2599	printf("\n");
2600	printf("\tBase Address=0x%016jx\n", subspace->BaseAddress);
2601	printf("\tLength=%jd\n", subspace->Length);
2602	printf("\tDoorbell Register=");
2603	acpi_print_gas(&subspace->DoorbellRegister);
2604	printf("\n");
2605	printf("\tDoorbell Preserve=0x%016jx\n", subspace->PreserveMask);
2606	printf("\tDoorbell Write=0x%016jx\n", subspace->WriteMask);
2607	printf("\tLatency=%u us\n", subspace->Latency);
2608	printf("\tMax Access Rate=%u\n", subspace->MaxAccessRate);
2609	printf("\tMin Turnaround Time=%u us\n", subspace->MinTurnaroundTime);
2610	printf("\tPlatform Interrupt Ack Register=");
2611	acpi_print_gas(&subspace->PlatformAckRegister);
2612	printf("\n");
2613	printf("\tPlatform Interrupt Ack Preserve=0x%016jx\n", subspace->AckPreserveMask);
2614	printf("\tPlatform Interrupt Ack Write=0x%016jx\n", subspace->AckWriteMask);
2615}
2616
2617static void
2618acpi_print_pcct_ext_pcc_master(ACPI_PCCT_EXT_PCC_MASTER *subspace)
2619{
2620	printf("\tType=Extended PCC Master Subspace\n");
2621	printf("\tPlatform Interrupt=%u", subspace->PlatformInterrupt);
2622	if (subspace->Flags & ACPI_PCCT_INTERRUPT_POLARITY) {
2623		printf(", Edge triggered");
2624	} else {
2625		printf(", Level triggered");
2626	}
2627	if (subspace->Flags & ACPI_PCCT_INTERRUPT_MODE) {
2628		printf(", Active low");
2629	} else {
2630		printf(", Active high");
2631	}
2632	printf("\n");
2633	printf("\tBase Address=0x%016jx\n", subspace->BaseAddress);
2634	printf("\tLength=%d\n", subspace->Length);
2635	printf("\tDoorbell Register=");
2636	acpi_print_gas(&subspace->DoorbellRegister);
2637	printf("\n");
2638	printf("\tDoorbell Preserve=0x%016jx\n", subspace->PreserveMask);
2639	printf("\tDoorbell Write=0x%016jx\n", subspace->WriteMask);
2640	printf("\tLatency=%u us\n", subspace->Latency);
2641	printf("\tMax Access Rate=%u\n", subspace->MaxAccessRate);
2642	printf("\tMin Turnaround Time=%u us\n", subspace->MinTurnaroundTime);
2643	printf("\tPlatform Interrupt Ack Register=");
2644	acpi_print_gas(&subspace->PlatformAckRegister);
2645	printf("\n");
2646	printf("\tPlatform Interrupt Ack Preserve=0x%016jx\n", subspace->AckPreserveMask);
2647	printf("\tPlatform Interrupt Ack Set=0x%016jx\n", subspace->AckSetMask);
2648	printf("\tCommand Complete Register=");
2649	acpi_print_gas(&subspace->CmdCompleteRegister);
2650	printf("\n");
2651	printf("\tCommand Complete Mask=0x%016jx\n", subspace->CmdCompleteMask);
2652	printf("\tCommand Update Register=");
2653	acpi_print_gas(&subspace->CmdUpdateRegister);
2654	printf("\n");
2655	printf("\tCommand Update Preserve Mask=0x%016jx\n", subspace->CmdUpdatePreserveMask);
2656	printf("\tCommand Update Set Mask=0x%016jx\n", subspace->CmdUpdateSetMask);
2657	printf("\tError Status Register=");
2658	acpi_print_gas(&subspace->ErrorStatusRegister);
2659	printf("\n");
2660	printf("\tError Status Mask=0x%016jx\n", subspace->ErrorStatusMask);
2661}
2662
2663static void
2664acpi_print_pcct_ext_pcc_slave(ACPI_PCCT_EXT_PCC_SLAVE *subspace)
2665{
2666	printf("\tType=Extended PCC Slave Subspace\n");
2667	printf("\tPlatform Interrupt=%u", subspace->PlatformInterrupt);
2668	if (subspace->Flags & ACPI_PCCT_INTERRUPT_POLARITY) {
2669		printf(", Edge triggered");
2670	} else {
2671		printf(", Level triggered");
2672	}
2673	if (subspace->Flags & ACPI_PCCT_INTERRUPT_MODE) {
2674		printf(", Active low");
2675	} else {
2676		printf(", Active high");
2677	}
2678	printf("\n");
2679	printf("\tBase Address=0x%016jx\n", subspace->BaseAddress);
2680	printf("\tLength=%d\n", subspace->Length);
2681	printf("\tDoorbell Register=");
2682	acpi_print_gas(&subspace->DoorbellRegister);
2683	printf("\n");
2684	printf("\tDoorbell Preserve=0x%016jx\n", subspace->PreserveMask);
2685	printf("\tDoorbell Write=0x%016jx\n", subspace->WriteMask);
2686	printf("\tLatency=%u us\n", subspace->Latency);
2687	printf("\tMax Access Rate=%u\n", subspace->MaxAccessRate);
2688	printf("\tMin Turnaround Time=%u us\n", subspace->MinTurnaroundTime);
2689	printf("\tPlatform Interrupt Ack Register=");
2690	acpi_print_gas(&subspace->PlatformAckRegister);
2691	printf("\n");
2692	printf("\tPlatform Interrupt Ack Preserve=0x%016jx\n", subspace->AckPreserveMask);
2693	printf("\tPlatform Interrupt Ack Set=0x%016jx\n", subspace->AckSetMask);
2694	printf("\tCommand Complete Register=");
2695	acpi_print_gas(&subspace->CmdCompleteRegister);
2696	printf("\n");
2697	printf("\tCommand Complete Mask=0x%016jx\n", subspace->CmdCompleteMask);
2698	printf("\tCommand Update Register=");
2699	acpi_print_gas(&subspace->CmdUpdateRegister);
2700	printf("\n");
2701	printf("\tCommand Update Preserve Mask=0x%016jx\n", subspace->CmdUpdatePreserveMask);
2702	printf("\tCommand Update Set Mask=0x%016jx\n", subspace->CmdUpdateSetMask);
2703	printf("\tError Status Register=");
2704	acpi_print_gas(&subspace->ErrorStatusRegister);
2705	printf("\n");
2706	printf("\tError Status Mask=0x%016jx\n", subspace->ErrorStatusMask);
2707}
2708
2709static void
2710acpi_print_pcct(ACPI_SUBTABLE_HEADER *hdr)
2711{
2712	switch (hdr->Type) {
2713	case ACPI_PCCT_TYPE_GENERIC_SUBSPACE:
2714		acpi_print_pcct_subspace((ACPI_PCCT_SUBSPACE *)hdr);
2715		break;
2716	case ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE:
2717		acpi_print_pcct_hw_reduced((ACPI_PCCT_HW_REDUCED *)hdr);
2718		break;
2719	case ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2:
2720		acpi_print_pcct_hw_reduced_type2((ACPI_PCCT_HW_REDUCED_TYPE2 *)hdr);
2721		break;
2722	case ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE:
2723		acpi_print_pcct_ext_pcc_master((ACPI_PCCT_EXT_PCC_MASTER *)hdr);
2724		break;
2725	case ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE:
2726		acpi_print_pcct_ext_pcc_slave((ACPI_PCCT_EXT_PCC_SLAVE *)hdr);
2727		break;
2728	default:
2729		printf("\tUnknown structure"
2730		    "(type = %hhu, length = %hhu)\n",
2731		    hdr->Type, hdr->Length);
2732		break;
2733	}
2734}
2735
2736static void
2737acpi_handle_pcct(ACPI_TABLE_HEADER *sdp)
2738{
2739	ACPI_TABLE_PCCT *pcct;
2740
2741	printf(BEGIN_COMMENT);
2742	acpi_print_sdt(sdp);
2743
2744	pcct = (ACPI_TABLE_PCCT *)sdp;
2745#define PRINTFLAG(var, flag)	printflag((var), ACPI_PCCT_## flag, #flag)
2746	printf("\tFlags=");
2747	PRINTFLAG(pcct->Flags, DOORBELL);
2748	PRINTFLAG_END();
2749#undef PRINTFLAG
2750
2751	acpi_walk_subtables(sdp, (pcct + 1), acpi_print_pcct);
2752
2753	printf(END_COMMENT);
2754}
2755
2756static void
2757acpi_print_pptt_processor(ACPI_PPTT_PROCESSOR *processor)
2758{
2759	uint32_t *private;
2760	unsigned int i;
2761
2762	printf("\tType=processor\n");
2763	printf("\tLength=%d\n", processor->Header.Length);
2764#define PRINTFLAG(var, flag)	printflag((var), ACPI_PPTT_## flag, #flag)
2765
2766	printf("\tFlags=");
2767	PRINTFLAG(processor->Flags, PHYSICAL_PACKAGE);
2768	PRINTFLAG(processor->Flags, ACPI_PROCESSOR_ID_VALID);
2769	PRINTFLAG_END();
2770
2771#undef PRINTFLAG
2772	printf("\tParent=%08x\n", processor->Parent);
2773	printf("\tACPI Processor ID=0x%08x\n", processor->AcpiProcessorId);
2774	printf("\tprivate resources=%d\n", processor->NumberOfPrivResources);
2775
2776	private = (uint32_t *)(processor + 1);
2777	for (i = 0; i < processor->NumberOfPrivResources; i++)
2778		printf("\tprivate resources%d=%08x\n", i, private[i]);
2779}
2780
2781static void
2782acpi_print_pptt_cache(ACPI_PPTT_CACHE *cache)
2783{
2784
2785	printf("\tType=cache\n");
2786	printf("\tLength=%d\n", cache->Header.Length);
2787
2788#define	PRINTFLAG(var, flag)	printflag((var), ACPI_PPTT_## flag, #flag)
2789	printf("\tFlags=");
2790	PRINTFLAG(cache->Flags, SIZE_PROPERTY_VALID);
2791	PRINTFLAG(cache->Flags, NUMBER_OF_SETS_VALID);
2792	PRINTFLAG(cache->Flags, ASSOCIATIVITY_VALID);
2793	PRINTFLAG(cache->Flags, ALLOCATION_TYPE_VALID);
2794	PRINTFLAG(cache->Flags, CACHE_TYPE_VALID);
2795	PRINTFLAG(cache->Flags, WRITE_POLICY_VALID);
2796	PRINTFLAG(cache->Flags, LINE_SIZE_VALID);
2797	PRINTFLAG_END();
2798#undef PRINTFLAG
2799
2800	printf("\tNextLevel=0x%08x\n", cache->NextLevelOfCache);
2801	if (cache->Flags & ACPI_PPTT_SIZE_PROPERTY_VALID)
2802		printf("\tSize=%d\n", cache->Size);
2803	if (cache->Flags & ACPI_PPTT_NUMBER_OF_SETS_VALID)
2804		printf("\tSets=%d\n", cache->NumberOfSets);
2805	if (cache->Flags & ACPI_PPTT_ASSOCIATIVITY_VALID)
2806		printf("\tAssociativity=%d\n", cache->Associativity);
2807	if (cache->Flags & ACPI_PPTT_ALLOCATION_TYPE_VALID) {
2808		printf("\tAllocation type=");
2809		switch (cache->Attributes & ACPI_PPTT_MASK_ALLOCATION_TYPE) {
2810		case ACPI_PPTT_CACHE_READ_ALLOCATE:
2811			printf("Read allocate\n");
2812			break;
2813		case ACPI_PPTT_CACHE_WRITE_ALLOCATE:
2814			printf("Write allocate\n");
2815			break;
2816		case ACPI_PPTT_CACHE_RW_ALLOCATE:
2817		case ACPI_PPTT_CACHE_RW_ALLOCATE_ALT:
2818			printf("Read and Write allocate\n");
2819			break;
2820		}
2821	}
2822	if (cache->Flags & ACPI_PPTT_CACHE_TYPE_VALID) {
2823		printf("\tCache type=");
2824		switch (cache->Attributes & ACPI_PPTT_MASK_CACHE_TYPE) {
2825		case ACPI_PPTT_CACHE_TYPE_DATA:
2826			printf("Data\n");
2827			break;
2828		case ACPI_PPTT_CACHE_TYPE_INSTR:
2829			printf("Instruction\n");
2830			break;
2831		case ACPI_PPTT_CACHE_TYPE_UNIFIED:
2832		case ACPI_PPTT_CACHE_TYPE_UNIFIED_ALT:
2833			printf("Unified\n");
2834			break;
2835		}
2836	}
2837	if (cache->Flags & ACPI_PPTT_WRITE_POLICY_VALID)
2838		printf("\tWrite Policy=Write %s \n",
2839		    (cache->Attributes & ACPI_PPTT_MASK_WRITE_POLICY) ?
2840		    "through" : "back");
2841
2842	if (cache->Flags & ACPI_PPTT_LINE_SIZE_VALID)
2843		printf("\tLine size=%d\n", cache->LineSize);
2844}
2845
2846static void
2847acpi_print_pptt_id(ACPI_PPTT_ID *id)
2848{
2849
2850	printf("\tType=id\n");
2851	printf("\tLength=%d\n", id->Header.Length);
2852
2853	printf("\tVENDOR_ID=");
2854	acpi_print_string((char *)&id->VendorId, 4);
2855	printf("\n");
2856
2857	printf("\tLEVEL_1_ID=%016" PRIx64 "\n", id->Level1Id);
2858	printf("\tLEVEL_2_ID=%016" PRIx64 "\n", id->Level2Id);
2859	printf("\tMajor=%hu", id->MajorRev);
2860	printf("\tMinor=%hu", id->MinorRev);
2861	printf("\tSpin=%hu", id->SpinRev);
2862}
2863
2864static void
2865acpi_print_pptt(ACPI_SUBTABLE_HEADER *hdr)
2866{
2867	switch (hdr->Type) {
2868	case ACPI_PPTT_TYPE_PROCESSOR:
2869		acpi_print_pptt_processor((ACPI_PPTT_PROCESSOR *)hdr);
2870		break;
2871	case ACPI_PPTT_TYPE_CACHE:
2872		acpi_print_pptt_cache((ACPI_PPTT_CACHE *)hdr);
2873		break;
2874	case ACPI_PPTT_TYPE_ID:
2875		acpi_print_pptt_id((ACPI_PPTT_ID *)hdr);
2876		break;
2877	default:
2878		printf("\tUnknown structure"
2879		    "(type = %hhu, length = %hhu)\n",
2880		    hdr->Type, hdr->Length);
2881		break;
2882	}
2883}
2884
2885static void
2886acpi_handle_pptt(ACPI_TABLE_HEADER *sdp)
2887{
2888	ACPI_TABLE_PPTT *pptt;
2889
2890	printf(BEGIN_COMMENT);
2891	acpi_print_sdt(sdp);
2892
2893	pptt = (ACPI_TABLE_PPTT *)sdp;
2894	acpi_walk_subtables(sdp, (pptt + 1), acpi_print_pptt);
2895
2896	printf(END_COMMENT);
2897}
2898
2899static void
2900acpi_handle_sbst(ACPI_TABLE_HEADER *sdp)
2901{
2902	ACPI_TABLE_SBST *sbst;
2903
2904	printf(BEGIN_COMMENT);
2905	acpi_print_sdt(sdp);
2906	sbst = (ACPI_TABLE_SBST *)sdp;
2907
2908	printf("\tWarning Level=%d mWh\n", sbst->WarningLevel);
2909	printf("\tLow Level=%d mWh\n", sbst->LowLevel);
2910	printf("\tCritical Level=%d mWh\n", sbst->CriticalLevel);
2911
2912	printf(END_COMMENT);
2913}
2914
2915static void
2916acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
2917{
2918	ACPI_TABLE_SLIT *slit;
2919	u_int idx;
2920	uint64_t cnt;
2921
2922	printf(BEGIN_COMMENT);
2923	acpi_print_sdt(sdp);
2924	slit = (ACPI_TABLE_SLIT *)sdp;
2925
2926	cnt = slit->LocalityCount * slit->LocalityCount;
2927	printf("\tLocalityCount=%ju\n", (uintmax_t)slit->LocalityCount);
2928	printf("\tEntry=\n\t");
2929	for (idx = 0; idx < cnt; idx++) {
2930		printf("%u ", slit->Entry[idx]);
2931		if ((idx % slit->LocalityCount) == (slit->LocalityCount - 1)) {
2932			printf("\n");
2933			if (idx < cnt - 1)
2934				printf("\t");
2935		}
2936	}
2937
2938	printf(END_COMMENT);
2939}
2940
2941static void
2942acpi_handle_spcr(ACPI_TABLE_HEADER *sdp)
2943{
2944	ACPI_TABLE_SPCR *spcr;
2945
2946	printf(BEGIN_COMMENT);
2947	acpi_print_sdt(sdp);
2948	spcr = (ACPI_TABLE_SPCR *)sdp;
2949
2950	printf("\n\tInterface Type=");
2951	switch (sdp->Revision) {
2952	case 1:
2953		printf("full 16550%s\n",
2954		    (spcr->InterfaceType == 1) ?
2955		    "(must also accept writing FCR register)" : "");
2956		break;
2957	case 2:
2958		acpi_print_dbg2_serial_subtype(spcr->InterfaceType);
2959		break;
2960	default:
2961		printf("unknown Revision\n");
2962		break;
2963	}
2964
2965	printf("\tSerial Port=");
2966	acpi_print_gas(&spcr->SerialPort);
2967	printf("\n\tInterrupt Type={");
2968	if (spcr->InterruptType & 0x1) {
2969		printf("\n\t\tdual-8259 IRQ=");
2970		switch (spcr->PcInterrupt) {
2971		case 2 ... 7:
2972		case 9 ... 12:
2973		case 14 ... 15:
2974			printf("%d", spcr->PcInterrupt);
2975			break;
2976		default:
2977			printf("%d (invalid entry)", spcr->PcInterrupt);
2978			break;
2979		}
2980	}
2981	if (spcr->InterruptType & 0x2) {
2982		printf("\n\t\tIO APIC={ GSI=%d }", spcr->Interrupt);
2983	}
2984	if (spcr->InterruptType & 0x4) {
2985		printf("\n\t\tIO SAPIC={ GSI=%d }", spcr->Interrupt);
2986	}
2987	if (spcr->InterruptType & 0x8) {
2988		printf("\n\t\tARMH GIC={ GSI=%d }", spcr->Interrupt);
2989	}
2990	printf("\n\t}\n");
2991
2992	printf("\tBaud Rate=");
2993	switch (spcr->BaudRate) {
2994	case 3:
2995		printf("9600");
2996		break;
2997	case 4:
2998		printf("19200");
2999		break;
3000	case 6:
3001		printf("57600");
3002		break;
3003	case 7:
3004		printf("115200");
3005		break;
3006	default:
3007		printf("unknown speed index %d", spcr->BaudRate);
3008		break;
3009	}
3010	printf("\n\tParity={");
3011	switch (spcr->Parity) {
3012	case 0:
3013		printf("OFF");
3014		break;
3015	default:
3016		printf("ON");
3017		break;
3018	}
3019	printf("}\n");
3020
3021	printf("\tStop Bits={");
3022	switch (spcr->StopBits) {
3023	case 1:
3024		printf("ON");
3025		break;
3026	default:
3027		printf("OFF");
3028		break;
3029	}
3030	printf("}\n");
3031
3032	printf("\tFlow Control={");
3033	if (spcr->FlowControl & 0x1)
3034		printf("DCD, ");
3035	if (spcr->FlowControl & 0x2)
3036		printf("RTS/CTS hardware, ");
3037	if (spcr->FlowControl & 0x4)
3038		printf("XON/XOFF software");
3039	printf("}\n");
3040
3041	printf("\tTerminal=");
3042	switch (spcr->TerminalType) {
3043	case 0:
3044		printf("VT100");
3045		break;
3046	case 1:
3047		printf("VT100+");
3048		break;
3049	case 2:
3050		printf("VT-UTF8");
3051		break;
3052	case 3:
3053		printf("ANSI");
3054		break;
3055	default:
3056		printf("unknown type %d", spcr->TerminalType);
3057		break;
3058	}
3059	printf("\n");
3060
3061	acpi_print_pci(spcr->PciVendorId, spcr->PciDeviceId,
3062	    spcr->PciSegment, spcr->PciBus, spcr->PciDevice, spcr->PciFunction);
3063
3064	printf("\tPCI Flags={");
3065	if (spcr->PciFlags & ACPI_SPCR_DO_NOT_DISABLE)
3066		printf("DONOT_DISABLE");
3067	printf("}\n");
3068
3069	printf(END_COMMENT);
3070}
3071
3072static void
3073acpi_handle_spmi(ACPI_TABLE_HEADER *sdp)
3074{
3075	ACPI_TABLE_SPMI *spmi;
3076
3077	printf(BEGIN_COMMENT);
3078	acpi_print_sdt(sdp);
3079	spmi = (ACPI_TABLE_SPMI *)sdp;
3080
3081	printf("\tInterface Type=");
3082	switch (spmi->InterfaceType) {
3083	case ACPI_SPMI_KEYBOARD:
3084		printf("Keyboard Controller Stype (KCS)");
3085		break;
3086	case ACPI_SPMI_SMI:
3087		printf("Server Management Interface Chip (SMIC)");
3088		break;
3089	case ACPI_SPMI_BLOCK_TRANSFER:
3090		printf("Block Transfer (BT)");
3091		break;
3092	case ACPI_SPMI_SMBUS:
3093		printf("SMBus System Interface (SSIF)");
3094		break;
3095	default:
3096		printf("Reserved(%d)", spmi->InterfaceType);
3097		break;
3098	}
3099	printf("\n\tSpecRevision=%d.%d", spmi->SpecRevision >> 8,
3100		spmi->SpecRevision & 0xff);
3101
3102	printf("\n\tInterrupt Type={");
3103	if (spmi->InterruptType & 0x1) {
3104		printf("\n\t\tSCI triggered GPE=%d", spmi->GpeNumber);
3105	}
3106	if (spmi->InterruptType & 0x2) {
3107		printf("\n\t\tIO APIC/SAPIC={ GSI=%d }", spmi->Interrupt);
3108	}
3109	printf("\n\t}\n");
3110
3111	printf("\tBase Address=");
3112	acpi_print_gas(&spmi->IpmiRegister);
3113	printf("\n");
3114
3115	if ((spmi->PciDeviceFlag & 0x01) != 0)
3116		acpi_print_pci_sbdf(spmi->PciSegment, spmi->PciBus,
3117		    spmi->PciDevice, spmi->PciFunction);
3118
3119	printf(END_COMMENT);
3120}
3121
3122static void
3123acpi_print_srat_cpu(uint8_t type, uint32_t apic_id, uint32_t proximity_domain,
3124    uint32_t flags, uint32_t clockdomain, uint8_t sapic_eid)
3125{
3126
3127	printf("\tFlags={");
3128	if (flags & ACPI_SRAT_CPU_ENABLED)
3129		printf("ENABLED");
3130	else
3131		printf("DISABLED");
3132	printf("}\n");
3133	printf("\t%s ID=%d\n",
3134	    (type == ACPI_SRAT_TYPE_GIC_ITS_AFFINITY) ? "ITS" : "APIC",
3135	    apic_id);
3136	if (type == ACPI_SRAT_TYPE_CPU_AFFINITY)
3137		printf("\tSAPIC EID=%d\n", sapic_eid);
3138	printf("\tProximity Domain=%d\n", proximity_domain);
3139	if (type != ACPI_SRAT_TYPE_GIC_ITS_AFFINITY)
3140		printf("\tClock Domain=%d\n", clockdomain);
3141}
3142
3143static void
3144acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
3145{
3146
3147	printf("\tFlags={");
3148	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
3149		printf("ENABLED");
3150	else
3151		printf("DISABLED");
3152	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
3153		printf(",HOT_PLUGGABLE");
3154	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
3155		printf(",NON_VOLATILE");
3156	printf("}\n");
3157	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
3158	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
3159	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
3160}
3161
3162static const char *srat_types[] = {
3163    [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
3164    [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
3165    [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
3166    [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
3167    [ACPI_SRAT_TYPE_GIC_ITS_AFFINITY] = "GIC ITS",
3168};
3169
3170static void
3171acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
3172{
3173	ACPI_SRAT_CPU_AFFINITY *cpu;
3174	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
3175	ACPI_SRAT_GICC_AFFINITY *gicc;
3176	ACPI_SRAT_GIC_ITS_AFFINITY *gici;
3177
3178	if (srat->Type < __arraycount(srat_types))
3179		printf("\tType=%s\n", srat_types[srat->Type]);
3180	else
3181		printf("\tType=%d (unknown)\n", srat->Type);
3182	switch (srat->Type) {
3183	case ACPI_SRAT_TYPE_CPU_AFFINITY:
3184		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
3185		acpi_print_srat_cpu(srat->Type, cpu->ApicId,
3186		    cpu->ProximityDomainHi[2] << 24 |
3187		    cpu->ProximityDomainHi[1] << 16 |
3188		    cpu->ProximityDomainHi[0] << 0 |
3189		    cpu->ProximityDomainLo,
3190		    cpu->Flags, cpu->ClockDomain, cpu->LocalSapicEid);
3191		break;
3192	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
3193		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
3194		break;
3195	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
3196		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
3197		acpi_print_srat_cpu(srat->Type, x2apic->ApicId,
3198		    x2apic->ProximityDomain,
3199		    x2apic->Flags, x2apic->ClockDomain, 0 /* dummy */);
3200		break;
3201	case ACPI_SRAT_TYPE_GICC_AFFINITY:
3202		gicc = (ACPI_SRAT_GICC_AFFINITY *)srat;
3203		acpi_print_srat_cpu(srat->Type, gicc->AcpiProcessorUid,
3204		    gicc->ProximityDomain,
3205		    gicc->Flags, gicc->ClockDomain, 0 /* dummy */);
3206		break;
3207	case ACPI_SRAT_TYPE_GIC_ITS_AFFINITY:
3208		gici = (ACPI_SRAT_GIC_ITS_AFFINITY *)srat;
3209		acpi_print_srat_cpu(srat->Type, gici->ItsId,
3210		    gici->ProximityDomain,
3211		    0 /* dummy */, 0 /* dummy */, 0 /* dummy */);
3212		break;
3213	}
3214}
3215
3216static void
3217acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
3218{
3219	ACPI_TABLE_SRAT *srat;
3220
3221	printf(BEGIN_COMMENT);
3222	acpi_print_sdt(sdp);
3223	srat = (ACPI_TABLE_SRAT *)sdp;
3224	printf("\tTable Revision=%d\n", srat->TableRevision);
3225	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
3226	printf(END_COMMENT);
3227}
3228
3229static const char *nfit_types[] = {
3230    [ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
3231    [ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
3232    [ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
3233    [ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
3234    [ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
3235    [ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
3236    [ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address"
3237};
3238
3239
3240static void
3241acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
3242{
3243	char *uuidstr;
3244	uint32_t status;
3245
3246	ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
3247	ACPI_NFIT_MEMORY_MAP *mmap;
3248	ACPI_NFIT_INTERLEAVE *ileave;
3249	ACPI_NFIT_SMBIOS *smbios __unused;
3250	ACPI_NFIT_CONTROL_REGION *ctlreg;
3251	ACPI_NFIT_DATA_REGION *datareg;
3252	ACPI_NFIT_FLUSH_ADDRESS *fladdr;
3253
3254	if (nfit->Type < __arraycount(nfit_types))
3255		printf("\tType=%s\n", nfit_types[nfit->Type]);
3256	else
3257		printf("\tType=%u (unknown)\n", nfit->Type);
3258	switch (nfit->Type) {
3259	case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
3260		sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
3261		printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
3262		printf("\tProximityDomain=%u\n",
3263		    (u_int)sysaddr->ProximityDomain);
3264		uuid_to_string((uuid_t *)(sysaddr->RangeGuid),
3265		    &uuidstr, &status);
3266		if (status != uuid_s_ok)
3267			errx(1, "uuid_to_string: status=%u", status);
3268		printf("\tRangeGuid=%s\n", uuidstr);
3269		free(uuidstr);
3270		printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
3271		printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
3272		printf("\tMemoryMapping=0x%016jx\n",
3273		    (uintmax_t)sysaddr->MemoryMapping);
3274
3275#define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
3276
3277		printf("\tFlags=");
3278		PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
3279		PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
3280		PRINTFLAG_END();
3281
3282#undef PRINTFLAG
3283
3284		break;
3285	case ACPI_NFIT_TYPE_MEMORY_MAP:
3286		mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
3287		printf("\tDeviceHandle=%u\n", (u_int)mmap->DeviceHandle);
3288		printf("\tPhysicalId=%u\n", (u_int)mmap->PhysicalId);
3289		printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
3290		printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
3291		printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
3292		printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
3293		printf("\tRegionOffset=0x%016jx\n",
3294		    (uintmax_t)mmap->RegionOffset);
3295		printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
3296		printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
3297		printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
3298
3299#define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_MEM_## flag, #flag)
3300
3301		printf("\tFlags=");
3302		PRINTFLAG(mmap->Flags, SAVE_FAILED);
3303		PRINTFLAG(mmap->Flags, RESTORE_FAILED);
3304		PRINTFLAG(mmap->Flags, FLUSH_FAILED);
3305		PRINTFLAG(mmap->Flags, NOT_ARMED);
3306		PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
3307		PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
3308		PRINTFLAG(mmap->Flags, MAP_FAILED);
3309		PRINTFLAG_END();
3310
3311#undef PRINTFLAG
3312
3313		break;
3314	case ACPI_NFIT_TYPE_INTERLEAVE:
3315		ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
3316		printf("\tInterleaveIndex=%u\n",
3317		    (u_int)ileave->InterleaveIndex);
3318		printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
3319		printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
3320		/* XXX ileave->LineOffset[i] output is not supported */
3321		break;
3322	case ACPI_NFIT_TYPE_SMBIOS:
3323		smbios = (ACPI_NFIT_SMBIOS *)nfit;
3324		/* XXX smbios->Data[x] output is not supported */
3325		break;
3326	case ACPI_NFIT_TYPE_CONTROL_REGION:
3327		ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
3328		printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
3329		printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
3330		printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
3331		printf("\tRevisionId=%u\n", (u_int)ctlreg->RevisionId);
3332		printf("\tSubsystemVendorId=0x%04x\n",
3333		    (u_int)ctlreg->SubsystemVendorId);
3334		printf("\tSubsystemDeviceId=0x%04x\n",
3335		    (u_int)ctlreg->SubsystemDeviceId);
3336		printf("\tSubsystemRevisionId=%u\n",
3337		    (u_int)ctlreg->SubsystemRevisionId);
3338		printf("\tValidFields=%02x\n", (u_int)ctlreg->ValidFields);
3339		printf("\tManufacturingLocation=%u\n",
3340		    (u_int)ctlreg->ManufacturingLocation);
3341		printf("\tManufacturingDate=%u\n",
3342		    (u_int)ctlreg->ManufacturingDate);
3343		printf("\tSerialNumber=%u\n",
3344		    (u_int)ctlreg->SerialNumber);
3345		printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
3346		printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
3347		printf("\tWindowSize=0x%016jx\n",
3348		    (uintmax_t)ctlreg->WindowSize);
3349		printf("\tCommandOffset=0x%016jx\n",
3350		    (uintmax_t)ctlreg->CommandOffset);
3351		printf("\tCommandSize=0x%016jx\n",
3352		    (uintmax_t)ctlreg->CommandSize);
3353		printf("\tStatusOffset=0x%016jx\n",
3354		    (uintmax_t)ctlreg->StatusOffset);
3355		printf("\tStatusSize=0x%016jx\n",
3356		    (uintmax_t)ctlreg->StatusSize);
3357
3358#define PRINTFLAG(var, flag)	printflag((var), ACPI_NFIT_## flag, #flag)
3359
3360		printf("\tFlags=");
3361		PRINTFLAG(ctlreg->Flags, CONTROL_BUFFERED);
3362		PRINTFLAG_END();
3363
3364#undef PRINTFLAG
3365
3366		break;
3367	case ACPI_NFIT_TYPE_DATA_REGION:
3368		datareg = (ACPI_NFIT_DATA_REGION *)nfit;
3369		printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
3370		printf("\tWindows=%u\n", (u_int)datareg->Windows);
3371		printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
3372		printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
3373		printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
3374		printf("\tStartAddress=0x%016jx\n",
3375		    (uintmax_t)datareg->StartAddress);
3376		break;
3377	case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
3378		fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
3379		printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
3380		printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
3381		/* XXX fladdr->HintAddress[i] output is not supported */
3382		break;
3383	}
3384}
3385
3386static void
3387acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
3388{
3389	ACPI_TABLE_NFIT *nfit;
3390
3391	printf(BEGIN_COMMENT);
3392	acpi_print_sdt(sdp);
3393	nfit = (ACPI_TABLE_NFIT *)sdp;
3394	acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
3395	printf(END_COMMENT);
3396}
3397
3398static char *
3399acpi_tcpa_evname(struct TCPAevent *event)
3400{
3401	struct TCPApc_event *pc_event;
3402	char *eventname = NULL;
3403
3404	pc_event = (struct TCPApc_event *)(event + 1);
3405
3406	switch (event->event_type) {
3407	case PREBOOT:
3408	case POST_CODE:
3409	case UNUSED:
3410	case NO_ACTION:
3411	case SEPARATOR:
3412	case SCRTM_CONTENTS:
3413	case SCRTM_VERSION:
3414	case CPU_MICROCODE:
3415	case PLATFORM_CONFIG_FLAGS:
3416	case TABLE_OF_DEVICES:
3417	case COMPACT_HASH:
3418	case IPL:
3419	case IPL_PARTITION_DATA:
3420	case NONHOST_CODE:
3421	case NONHOST_CONFIG:
3422	case NONHOST_INFO:
3423		asprintf(&eventname, "%s",
3424		    tcpa_event_type_strings[event->event_type]);
3425		break;
3426
3427	case ACTION:
3428		eventname = calloc(event->event_size + 1, sizeof(char));
3429		memcpy(eventname, pc_event, event->event_size);
3430		break;
3431
3432	case EVENT_TAG:
3433		switch (pc_event->event_id) {
3434		case SMBIOS:
3435		case BIS_CERT:
3436		case CMOS:
3437		case NVRAM:
3438		case OPTION_ROM_EXEC:
3439		case OPTION_ROM_CONFIG:
3440		case S_CRTM_VERSION:
3441		case POST_BIOS_ROM:
3442		case ESCD:
3443		case OPTION_ROM_MICROCODE:
3444		case S_CRTM_CONTENTS:
3445		case POST_CONTENTS:
3446			asprintf(&eventname, "%s",
3447			    TCPA_pcclient_strings[pc_event->event_id]);
3448			break;
3449
3450		default:
3451			asprintf(&eventname, "<unknown tag 0x%02x>",
3452			    pc_event->event_id);
3453			break;
3454		}
3455		break;
3456
3457	default:
3458		asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
3459		break;
3460	}
3461
3462	return eventname;
3463}
3464
3465static void
3466acpi_print_tcpa(struct TCPAevent *event)
3467{
3468	int i;
3469	char *eventname;
3470
3471	eventname = acpi_tcpa_evname(event);
3472
3473	printf("\t%d", event->pcr_index);
3474	printf(" 0x");
3475	for (i = 0; i < 20; i++)
3476		printf("%02x", event->pcr_value[i]);
3477	printf(" [%s]\n", eventname ? eventname : "<unknown>");
3478
3479	free(eventname);
3480}
3481
3482static void
3483acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
3484{
3485	struct TCPAbody *tcpa;
3486	struct TCPAevent *event;
3487	uintmax_t len, paddr;
3488	unsigned char *vaddr = NULL;
3489	unsigned char *vend = NULL;
3490
3491	printf(BEGIN_COMMENT);
3492	acpi_print_sdt(sdp);
3493	tcpa = (struct TCPAbody *) sdp;
3494
3495	switch (tcpa->platform_class) {
3496	case ACPI_TCPA_BIOS_CLIENT:
3497		len = tcpa->client.log_max_len;
3498		paddr = tcpa->client.log_start_addr;
3499		break;
3500
3501	case ACPI_TCPA_BIOS_SERVER:
3502		len = tcpa->server.log_max_len;
3503		paddr = tcpa->server.log_start_addr;
3504		break;
3505
3506	default:
3507		printf("XXX");
3508		printf(END_COMMENT);
3509		return;
3510	}
3511	printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
3512	    tcpa->platform_class, paddr, len);
3513
3514	if (len == 0) {
3515		printf("\tEmpty TCPA table\n");
3516		printf(END_COMMENT);
3517		return;
3518	}
3519	if (sdp->Revision == 1) {
3520		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
3521		printf(END_COMMENT);
3522		return;
3523	}
3524
3525	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
3526	vend = vaddr + len;
3527
3528	while (vaddr != NULL) {
3529		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
3530		    (vaddr + sizeof(struct TCPAevent) < vaddr))
3531			break;
3532		event = (struct TCPAevent *)(void *)vaddr;
3533		if (vaddr + event->event_size >= vend)
3534			break;
3535		if (vaddr + event->event_size < vaddr)
3536			break;
3537		if (event->event_type == 0 && event->event_size == 0)
3538			break;
3539#if 0
3540		{
3541		unsigned int i, j, k;
3542
3543		printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
3544		for (j = 0, i = 0; i <
3545		    sizeof(struct TCPAevent) + event->event_size; i++) {
3546			printf("%02x ", vaddr[i]);
3547			if ((i+1) % 8 == 0) {
3548				for (k = 0; k < 8; k++)
3549					printf("%c", isprint(vaddr[j+k]) ?
3550					    vaddr[j+k] : '.');
3551				printf("\n\t\t%p ", &vaddr[i + 1]);
3552				j = i + 1;
3553			}
3554		}
3555		printf("\n"); }
3556#endif
3557		acpi_print_tcpa(event);
3558
3559		vaddr += sizeof(struct TCPAevent) + event->event_size;
3560	}
3561
3562	printf(END_COMMENT);
3563}
3564
3565static void
3566acpi_handle_tpm2(ACPI_TABLE_HEADER *sdp)
3567{
3568	ACPI_TABLE_TPM2 *tpm2;
3569	const char *class;
3570
3571	printf(BEGIN_COMMENT);
3572
3573	acpi_print_sdt(sdp);
3574	tpm2 = (ACPI_TABLE_TPM2 *)sdp;
3575
3576	if (tpm2->PlatformClass == 0) {
3577		class = "Client";
3578	} else if (tpm2->PlatformClass == 1) {
3579		class = "Server";
3580	} else {
3581		class = "Unknown";
3582	}
3583	printf("\tClass=%s (%u)\n", class, tpm2->PlatformClass);
3584	printf("\tControl Address=0x%"PRIx64"\n", tpm2->ControlAddress);
3585	printf("\tStart Method=%u\n", tpm2->StartMethod);
3586
3587	printf(END_COMMENT);
3588}
3589
3590static const char *
3591devscope_type2str(int type)
3592{
3593	static char typebuf[16];
3594
3595	switch (type) {
3596	case 1:
3597		return ("PCI Endpoint Device");
3598	case 2:
3599		return ("PCI Sub-Hierarchy");
3600	case 3:
3601		return ("IOAPIC");
3602	case 4:
3603		return ("HPET");
3604	case 5:
3605		return ("ACPI Name space");
3606	default:
3607		snprintf(typebuf, sizeof(typebuf), "%d", type);
3608		return (typebuf);
3609	}
3610}
3611
3612static int
3613acpi_handle_dmar_devscope(void *addr, int remaining)
3614{
3615	char sep;
3616	int pathlen;
3617	ACPI_DMAR_PCI_PATH *path, *pathend;
3618	ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
3619
3620	if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
3621		return (-1);
3622
3623	if (remaining < devscope->Length)
3624		return (-1);
3625
3626	printf("\n");
3627	printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
3628	printf("\t\tLength=%d\n", devscope->Length);
3629	printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
3630	printf("\t\tStartBusNumber=%d\n", devscope->Bus);
3631
3632	path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
3633	pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
3634	pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
3635	if (path < pathend) {
3636		sep = '{';
3637		printf("\t\tPath=");
3638		do {
3639			printf("%c%d:%d", sep, path->Device, path->Function);
3640			sep=',';
3641			path++;
3642		} while (path < pathend);
3643		printf("}\n");
3644	}
3645
3646	return (devscope->Length);
3647}
3648
3649static void
3650acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
3651{
3652	char *cp;
3653	int remaining, consumed;
3654
3655	printf("\n");
3656	printf("\tType=DRHD\n");
3657	printf("\tLength=%d\n", drhd->Header.Length);
3658
3659#define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
3660
3661	printf("\tFlags=");
3662	PRINTFLAG(drhd->Flags, INCLUDE_ALL);
3663	PRINTFLAG_END();
3664
3665#undef PRINTFLAG
3666
3667	printf("\tSegment=%d\n", drhd->Segment);
3668	printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
3669
3670	remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
3671	if (remaining > 0)
3672		printf("\tDevice Scope:");
3673	while (remaining > 0) {
3674		cp = (char *)drhd + drhd->Header.Length - remaining;
3675		consumed = acpi_handle_dmar_devscope(cp, remaining);
3676		if (consumed <= 0)
3677			break;
3678		else
3679			remaining -= consumed;
3680	}
3681}
3682
3683static void
3684acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
3685{
3686	char *cp;
3687	int remaining, consumed;
3688
3689	printf("\n");
3690	printf("\tType=RMRR\n");
3691	printf("\tLength=%d\n", rmrr->Header.Length);
3692	printf("\tSegment=%d\n", rmrr->Segment);
3693	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
3694	printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
3695
3696	remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
3697	if (remaining > 0)
3698		printf("\tDevice Scope:");
3699	while (remaining > 0) {
3700		cp = (char *)rmrr + rmrr->Header.Length - remaining;
3701		consumed = acpi_handle_dmar_devscope(cp, remaining);
3702		if (consumed <= 0)
3703			break;
3704		else
3705			remaining -= consumed;
3706	}
3707}
3708
3709static void
3710acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
3711{
3712	char *cp;
3713	int remaining, consumed;
3714
3715	printf("\n");
3716	printf("\tType=ATSR\n");
3717	printf("\tLength=%d\n", atsr->Header.Length);
3718
3719#define	PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
3720
3721	printf("\tFlags=");
3722	PRINTFLAG(atsr->Flags, ALL_PORTS);
3723	PRINTFLAG_END();
3724
3725#undef PRINTFLAG
3726
3727	printf("\tSegment=%d\n", atsr->Segment);
3728
3729	remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
3730	if (remaining > 0)
3731		printf("\tDevice Scope:");
3732	while (remaining > 0) {
3733		cp = (char *)atsr + atsr->Header.Length - remaining;
3734		consumed = acpi_handle_dmar_devscope(cp, remaining);
3735		if (consumed <= 0)
3736			break;
3737		else
3738			remaining -= consumed;
3739	}
3740}
3741
3742static void
3743acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
3744{
3745
3746	printf("\n");
3747	printf("\tType=RHSA\n");
3748	printf("\tLength=%d\n", rhsa->Header.Length);
3749	printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
3750	printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
3751}
3752
3753static void
3754acpi_handle_dmar_andd(ACPI_DMAR_ANDD *andd)
3755{
3756
3757	printf("\n");
3758	printf("\tType=ANDD\n");
3759	printf("\tLength=%d\n", andd->Header.Length);
3760	printf("\tDeviceNumber=%d\n", andd->DeviceNumber);
3761	printf("\tDeviceName=0x%s\n", andd->DeviceName);
3762}
3763
3764static int
3765acpi_handle_dmar_remapping_structure(void *addr, int remaining)
3766{
3767	ACPI_DMAR_HEADER *hdr = addr;
3768
3769	if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
3770		return (-1);
3771
3772	if (remaining < hdr->Length)
3773		return (-1);
3774
3775	switch (hdr->Type) {
3776	case ACPI_DMAR_TYPE_HARDWARE_UNIT:
3777		acpi_handle_dmar_drhd(addr);
3778		break;
3779	case ACPI_DMAR_TYPE_RESERVED_MEMORY:
3780		acpi_handle_dmar_rmrr(addr);
3781		break;
3782	case ACPI_DMAR_TYPE_ROOT_ATS:
3783		acpi_handle_dmar_atsr(addr);
3784		break;
3785	case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
3786		acpi_handle_dmar_rhsa(addr);
3787		break;
3788	case ACPI_DMAR_TYPE_NAMESPACE:
3789		acpi_handle_dmar_andd(addr);
3790		break;
3791	default:
3792		printf("\n");
3793		printf("\tType=%d\n", hdr->Type);
3794		printf("\tLength=%d\n", hdr->Length);
3795		break;
3796	}
3797	return (hdr->Length);
3798}
3799
3800#ifndef ACPI_DMAR_X2APIC_OPT_OUT
3801#define	ACPI_DMAR_X2APIC_OPT_OUT	(0x2)
3802#endif
3803
3804static void
3805acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
3806{
3807	char *cp;
3808	int remaining, consumed;
3809	ACPI_TABLE_DMAR *dmar;
3810
3811	printf(BEGIN_COMMENT);
3812	acpi_print_sdt(sdp);
3813	dmar = (ACPI_TABLE_DMAR *)sdp;
3814	printf("\tHost Address Width=%d\n", dmar->Width + 1);
3815
3816#define PRINTFLAG(var, flag)	printflag((var), ACPI_DMAR_## flag, #flag)
3817
3818	printf("\tFlags=");
3819	PRINTFLAG(dmar->Flags, INTR_REMAP);
3820	PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
3821	PRINTFLAG(dmar->Flags, X2APIC_MODE);
3822	PRINTFLAG_END();
3823
3824#undef PRINTFLAG
3825
3826	remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
3827	while (remaining > 0) {
3828		cp = (char *)sdp + sdp->Length - remaining;
3829		consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
3830		if (consumed <= 0)
3831			break;
3832		else
3833			remaining -= consumed;
3834	}
3835
3836	printf(END_COMMENT);
3837}
3838
3839static void
3840acpi_handle_uefi(ACPI_TABLE_HEADER *sdp)
3841{
3842	ACPI_TABLE_UEFI *uefi;
3843	char *uuidstr;
3844	uint32_t status;
3845
3846	printf(BEGIN_COMMENT);
3847	acpi_print_sdt(sdp);
3848	uefi = (ACPI_TABLE_UEFI *)sdp;
3849
3850	uuid_to_string((uuid_t *)(uefi->Identifier),
3851	    &uuidstr, &status);
3852	if (status != uuid_s_ok)
3853		errx(1, "uuid_to_string: status=%u", status);
3854	printf("\tUUID=%s\n", uuidstr);
3855	free(uuidstr);
3856
3857	printf("\tDataOffset=%04hx\n", uefi->DataOffset);
3858	/* XXX need write */
3859
3860	printf(END_COMMENT);
3861}
3862
3863static void
3864acpi_handle_waet(ACPI_TABLE_HEADER *sdp)
3865{
3866	ACPI_TABLE_WAET *waet;
3867
3868	printf(BEGIN_COMMENT);
3869	acpi_print_sdt(sdp);
3870	waet = (ACPI_TABLE_WAET *)sdp;
3871
3872	printf("\tRTC Timer={");
3873	if (waet->Flags & ACPI_WAET_RTC_NO_ACK)
3874		printf("No ACK required");
3875	else
3876		printf("default behaviour");
3877	printf("}\n");
3878	printf("\t ACPI PM Timer={");
3879	if (waet->Flags & ACPI_WAET_TIMER_ONE_READ)
3880		printf("One Read sufficient");
3881	else
3882		printf("default behaviour");
3883	printf("}\n");
3884
3885	printf(END_COMMENT);
3886}
3887
3888static void
3889acpi_print_wdat_action(ACPI_WHEA_HEADER *whea)
3890{
3891	printf("\tACTION={");
3892	switch (whea->Action) {
3893	case ACPI_WDAT_RESET:
3894		printf("RESET");
3895		break;
3896	case ACPI_WDAT_GET_CURRENT_COUNTDOWN:
3897		printf("GET_CURRENT_COUNTDOWN");
3898		break;
3899	case ACPI_WDAT_GET_COUNTDOWN:
3900		printf("GET_COUNTDOWN");
3901		break;
3902	case ACPI_WDAT_SET_COUNTDOWN:
3903		printf("SET_COUNTDOWN");
3904		break;
3905	case ACPI_WDAT_GET_RUNNING_STATE:
3906		printf("GET_RUNNING_STATE");
3907		break;
3908	case ACPI_WDAT_SET_RUNNING_STATE:
3909		printf("SET_RUNNING_STATE");
3910		break;
3911	case ACPI_WDAT_GET_STOPPED_STATE:
3912		printf("GET_STOPPED_STATE");
3913		break;
3914	case ACPI_WDAT_SET_STOPPED_STATE:
3915		printf("SET_STOPPED_STATE");
3916		break;
3917	case ACPI_WDAT_GET_REBOOT:
3918		printf("GET_REBOOT");
3919		break;
3920	case ACPI_WDAT_SET_REBOOT:
3921		printf("SET_REBOOT");
3922		break;
3923	case ACPI_WDAT_GET_SHUTDOWN:
3924		printf("GET_SHUTDOWN");
3925		break;
3926	case ACPI_WDAT_SET_SHUTDOWN:
3927		printf("SET_SHUTDOWN");
3928		break;
3929	case ACPI_WDAT_GET_STATUS:
3930		printf("GET_STATUS");
3931		break;
3932	case ACPI_WDAT_SET_STATUS:
3933		printf("SET_STATUS");
3934		break;
3935	case ACPI_WDAT_ACTION_RESERVED:
3936		printf("ACTION_RESERVED");
3937		break;
3938	default:
3939		printf("%d", whea->Action);
3940		break;
3941	}
3942	printf("}\n");
3943}
3944
3945static void
3946acpi_print_wdat_instruction(ACPI_WHEA_HEADER *whea)
3947{
3948	uint32_t ins;
3949
3950	ins = whea->Instruction & ~ACPI_WDAT_PRESERVE_REGISTER;
3951
3952	printf("\tINSTRUCTION={");
3953	switch (ins) {
3954	case ACPI_WDAT_READ_VALUE:
3955		printf("READ_VALUE");
3956		break;
3957	case ACPI_WDAT_READ_COUNTDOWN:
3958		printf("READ_COUNTDOWN");
3959		break;
3960	case ACPI_WDAT_WRITE_VALUE:
3961		printf("WRITE_VALUE");
3962		break;
3963	case ACPI_WDAT_WRITE_COUNTDOWN:
3964		printf("WRITE_COUNTDOWN");
3965		break;
3966	case ACPI_WDAT_INSTRUCTION_RESERVED:
3967		printf("INSTRUCTION_RESERVED");
3968		break;
3969	default:
3970		printf("%d", ins);
3971		break;
3972	}
3973
3974	if (whea->Instruction & ACPI_WDAT_PRESERVE_REGISTER)
3975		printf(", Preserve Register");
3976
3977	printf("}\n");
3978}
3979
3980static void
3981acpi_handle_wdat(ACPI_TABLE_HEADER *sdp)
3982{
3983	ACPI_TABLE_WDAT *wdat;
3984	ACPI_WHEA_HEADER *whea;
3985	ACPI_WDAT_ENTRY *wdat_pos;
3986	u_int i;
3987
3988	printf(BEGIN_COMMENT);
3989	acpi_print_sdt(sdp);
3990	wdat = (ACPI_TABLE_WDAT *)sdp;
3991
3992	printf("\tHeader Length=%d\n", wdat->HeaderLength);
3993
3994	acpi_print_pci_sbdf(wdat->PciSegment, wdat->PciBus, wdat->PciDevice,
3995	    wdat->PciFunction);
3996	printf("\n\tTimer Counter Period=%d msec\n", wdat->TimerPeriod);
3997	printf("\tTimer Maximum Counter Value=%d\n", wdat->MaxCount);
3998	printf("\tTimer Minimum Counter Value=%d\n", wdat->MinCount);
3999
4000	printf("\tFlags={");
4001	if (wdat->Flags & ACPI_WDAT_ENABLED)
4002		printf("ENABLED");
4003	if (wdat->Flags & ACPI_WDAT_STOPPED)
4004		printf(", STOPPED");
4005	printf("}\n");
4006
4007	wdat_pos = (ACPI_WDAT_ENTRY *)((char *)wdat + sizeof(ACPI_TABLE_WDAT));
4008
4009	for (i = 0; i < wdat->Entries; i++) {
4010		whea = (ACPI_WHEA_HEADER *)wdat_pos;
4011		acpi_print_whea(whea,
4012		    acpi_print_wdat_action, acpi_print_wdat_instruction,
4013		    NULL);
4014		wdat_pos++;
4015	}
4016	printf(END_COMMENT);
4017}
4018
4019static void
4020acpi_handle_wddt(ACPI_TABLE_HEADER *sdp)
4021{
4022	ACPI_TABLE_WDDT *wddt;
4023
4024	printf(BEGIN_COMMENT);
4025	acpi_print_sdt(sdp);
4026	wddt = (ACPI_TABLE_WDDT *)sdp;
4027
4028	printf("\tSpecVersion=%04hx\n", wddt->SpecVersion);
4029	printf("\tTableVersion=%04hx\n", wddt->TableVersion);
4030	printf("\tPciVendorID=%04hx\n", wddt->PciVendorId);
4031	printf("\tAddress=");
4032	acpi_print_gas(&wddt->Address);
4033	printf("\n\tTimer Maximum Counter Value=%d\n", wddt->MaxCount);
4034	printf("\tTimer Minimum Counter Value=%d\n", wddt->MinCount);
4035	printf("\tTimer Counter Period=%d\n", wddt->Period);
4036
4037#define PRINTFLAG(var, flag)	printflag((var), ACPI_WDDT_## flag, #flag)
4038
4039	printf("\tStatus=");
4040	PRINTFLAG(wddt->Status, AVAILABLE);
4041	PRINTFLAG(wddt->Status, ACTIVE);
4042	PRINTFLAG(wddt->Status, TCO_OS_OWNED);
4043	PRINTFLAG(wddt->Status, USER_RESET);
4044	PRINTFLAG(wddt->Status, WDT_RESET);
4045	PRINTFLAG(wddt->Status, POWER_FAIL);
4046	PRINTFLAG(wddt->Status, UNKNOWN_RESET);
4047	PRINTFLAG_END();
4048
4049	printf("\tCapability=");
4050	PRINTFLAG(wddt->Capability, AUTO_RESET);
4051	PRINTFLAG(wddt->Capability, ALERT_SUPPORT);
4052	PRINTFLAG_END();
4053
4054#undef PRINTFLAG
4055
4056	printf(END_COMMENT);
4057}
4058
4059static void
4060acpi_handle_wdrt(ACPI_TABLE_HEADER *sdp)
4061{
4062	ACPI_TABLE_WDRT *wdrt;
4063
4064	printf(BEGIN_COMMENT);
4065	acpi_print_sdt(sdp);
4066	wdrt = (ACPI_TABLE_WDRT *)sdp;
4067
4068	printf("\tControl Register=");
4069	acpi_print_gas(&wdrt->ControlRegister);
4070	printf("\n\tCount Register=");
4071	acpi_print_gas(&wdrt->CountRegister);
4072	printf("\n");
4073	acpi_print_pci(wdrt->PciVendorId, wdrt->PciDeviceId,
4074	    wdrt->PciSegment, wdrt->PciBus, wdrt->PciDevice, wdrt->PciFunction);
4075
4076	/* Value must be >= 511 and < 65535 */
4077	printf("\tMaxCount=%d", wdrt->MaxCount);
4078	if (wdrt->MaxCount < 511)
4079		printf(" (Out of Range. Valid range: 511 <= maxcount < 65535)");
4080	printf("\n");
4081
4082	printf("\tUnit={");
4083	switch (wdrt->Units) {
4084	case 0:
4085		printf("1 seconds/count");
4086		break;
4087	case 1:
4088		printf("100 milliseconds/count");
4089		break;
4090	case 2:
4091		printf("10 milliseconds/count");
4092		break;
4093	default:
4094		printf("%d", wdrt->Units);
4095		break;
4096	}
4097	printf("}\n");
4098
4099	printf(END_COMMENT);
4100}
4101
4102static void
4103acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
4104{
4105	printf("  ");
4106	acpi_print_string(sdp->Signature, ACPI_NAMESEG_SIZE);
4107	printf(": Length=%d, Revision=%d, Checksum=%d",
4108	       sdp->Length, sdp->Revision, sdp->Checksum);
4109	if (acpi_checksum(sdp, sdp->Length))
4110		printf(" (Incorrect)");
4111	printf(",\n\tOEMID=");
4112	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
4113	printf(", OEM Table ID=");
4114	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
4115	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
4116	printf("\tCreator ID=");
4117	acpi_print_string(sdp->AslCompilerId, ACPI_NAMESEG_SIZE);
4118	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
4119}
4120
4121void
4122acpi_print_tabs(unsigned int n)
4123{
4124
4125	while (n-- > 0)
4126		printf("\t");
4127}
4128
4129static void
4130acpi_dump_bytes(uint8_t *p, uint32_t len, unsigned int ntabs)
4131{
4132	unsigned int i;
4133
4134	acpi_print_tabs(ntabs);
4135	printf("Data={");
4136	for (i = 0; i < len; i++) {
4137		if (cflag) {
4138			if (i % 64 == 0) {
4139				printf("\n");
4140				acpi_print_tabs(ntabs);
4141				printf(" ");
4142			}else if (i % 16 == 0)
4143				printf(" ");
4144			printf("%c", (p[i] >= ' ' && p[i] <= '~') ? p[i] : '.');
4145		} else {
4146			if (i % 16 == 0) {
4147				printf("\n");
4148				acpi_print_tabs(ntabs + 1);
4149			} else if (i % 8 == 0)
4150				printf("   ");
4151			printf(" %02x", p[i]);
4152		}
4153	}
4154	printf("\n");
4155	acpi_print_tabs(ntabs);
4156	printf("}\n");
4157}
4158
4159/* Dump data which has ACPI_TABLE_HEADER */
4160static void
4161acpi_dump_table(ACPI_TABLE_HEADER *sdp)
4162{
4163
4164	acpi_dump_bytes((uint8_t *)sdp, sdp->Length, 1);
4165}
4166
4167static void
4168acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
4169{
4170	ACPI_TABLE_RSDT *rsdt;
4171	ACPI_TABLE_XSDT *xsdt;
4172	int	i, entries;
4173
4174	rsdt = (ACPI_TABLE_RSDT *)rsdp;
4175	xsdt = (ACPI_TABLE_XSDT *)rsdp;
4176	printf(BEGIN_COMMENT);
4177	acpi_print_sdt(rsdp);
4178	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
4179	printf("\tEntries={ ");
4180	for (i = 0; i < entries; i++) {
4181		if (i > 0)
4182			printf(", ");
4183		if (addr_size == 4)
4184			printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
4185		else
4186			printf("0x%016jx",
4187			    (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
4188	}
4189	printf(" }\n");
4190	printf(END_COMMENT);
4191}
4192
4193static const char *acpi_pm_profiles[] = {
4194	"Unspecified", "Desktop", "Mobile", "Workstation",
4195	"Enterprise Server", "SOHO Server", "Appliance PC",
4196	"Performance Server", "Tablet"
4197};
4198
4199static void
4200acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
4201{
4202	ACPI_TABLE_FADT *fadt;
4203	const char *pm;
4204
4205	fadt = (ACPI_TABLE_FADT *)sdp;
4206	printf(BEGIN_COMMENT);
4207	acpi_print_sdt(sdp);
4208	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
4209	       fadt->Dsdt);
4210	/* XXX ACPI 2.0 eliminated this */
4211	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
4212	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
4213		pm = "Reserved";
4214	else
4215		pm = acpi_pm_profiles[fadt->PreferredProfile];
4216	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
4217	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
4218	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
4219	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
4220	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
4221	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
4222	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
4223	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
4224	       fadt->Pm1aEventBlock,
4225	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
4226	if (fadt->Pm1bEventBlock != 0)
4227		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
4228		       fadt->Pm1bEventBlock,
4229		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
4230	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
4231	       fadt->Pm1aControlBlock,
4232	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
4233	if (fadt->Pm1bControlBlock != 0)
4234		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
4235		       fadt->Pm1bControlBlock,
4236		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
4237	if (fadt->Pm2ControlBlock != 0)
4238		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
4239		       fadt->Pm2ControlBlock,
4240		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
4241	if (fadt->PmTimerBlock != 0)
4242		printf("\tPM_TMR_BLK=0x%x-0x%x\n",
4243		    fadt->PmTimerBlock,
4244		    fadt->PmTimerBlock + fadt->PmTimerLength - 1);
4245	if (fadt->Gpe0Block != 0)
4246		printf("\tGPE0_BLK=0x%x-0x%x\n",
4247		       fadt->Gpe0Block,
4248		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
4249	if (fadt->Gpe1Block != 0)
4250		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
4251		       fadt->Gpe1Block,
4252		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
4253		       fadt->Gpe1Base);
4254	if (fadt->CstControl != 0)
4255		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
4256	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
4257	       fadt->C2Latency, fadt->C3Latency);
4258	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
4259	       fadt->FlushSize, fadt->FlushStride);
4260	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
4261	       fadt->DutyOffset, fadt->DutyWidth);
4262	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
4263	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
4264
4265#define PRINTFLAG(var, flag)	printflag((var), ACPI_FADT_## flag, #flag)
4266
4267	printf("\tIAPC_BOOT_ARCH=");
4268	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
4269	PRINTFLAG(fadt->BootFlags, 8042);
4270	PRINTFLAG(fadt->BootFlags, NO_VGA);
4271	PRINTFLAG(fadt->BootFlags, NO_MSI);
4272	PRINTFLAG(fadt->BootFlags, NO_ASPM);
4273	PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
4274	PRINTFLAG_END();
4275
4276	printf("\tFlags=");
4277	PRINTFLAG(fadt->Flags, WBINVD);
4278	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
4279	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
4280	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
4281	PRINTFLAG(fadt->Flags, POWER_BUTTON);
4282	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
4283	PRINTFLAG(fadt->Flags, FIXED_RTC);
4284	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
4285	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
4286	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
4287	PRINTFLAG(fadt->Flags, RESET_REGISTER);
4288	PRINTFLAG(fadt->Flags, SEALED_CASE);
4289	PRINTFLAG(fadt->Flags, HEADLESS);
4290	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
4291	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
4292	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
4293	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
4294	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
4295	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
4296	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
4297	PRINTFLAG(fadt->Flags, HW_REDUCED);
4298	PRINTFLAG(fadt->Flags, LOW_POWER_S0);
4299	PRINTFLAG_END();
4300
4301	if (sdp->Length < ACPI_FADT_V2_SIZE)
4302		goto out;
4303
4304	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
4305		printf("\tRESET_REG=");
4306		acpi_print_gas(&fadt->ResetRegister);
4307		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
4308	}
4309
4310	printf("\tArmBootFlags=");
4311	PRINTFLAG(fadt->ArmBootFlags, PSCI_COMPLIANT);
4312	PRINTFLAG(fadt->ArmBootFlags, PSCI_USE_HVC);
4313	PRINTFLAG_END();
4314
4315#undef PRINTFLAG
4316
4317	printf("\tMinorRevision=%u\n", fadt->MinorRevision);
4318
4319	if (sdp->Length < ACPI_FADT_V3_SIZE)
4320		goto out;
4321
4322	printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
4323	printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
4324	printf("\tX_PM1a_EVT_BLK=");
4325	acpi_print_gas(&fadt->XPm1aEventBlock);
4326	if (fadt->XPm1bEventBlock.Address != 0) {
4327		printf("\n\tX_PM1b_EVT_BLK=");
4328		acpi_print_gas(&fadt->XPm1bEventBlock);
4329	}
4330	printf("\n\tX_PM1a_CNT_BLK=");
4331	acpi_print_gas(&fadt->XPm1aControlBlock);
4332	if (fadt->XPm1bControlBlock.Address != 0) {
4333		printf("\n\tX_PM1b_CNT_BLK=");
4334		acpi_print_gas(&fadt->XPm1bControlBlock);
4335	}
4336	if (fadt->XPm2ControlBlock.Address != 0) {
4337		printf("\n\tX_PM2_CNT_BLK=");
4338		acpi_print_gas(&fadt->XPm2ControlBlock);
4339	}
4340	if (fadt->XPmTimerBlock.Address != 0) {
4341		printf("\n\tX_PM_TMR_BLK=");
4342		acpi_print_gas(&fadt->XPmTimerBlock);
4343	}
4344	if (fadt->XGpe0Block.Address != 0) {
4345		printf("\n\tX_GPE0_BLK=");
4346		acpi_print_gas(&fadt->XGpe0Block);
4347	}
4348	if (fadt->XGpe1Block.Address != 0) {
4349		printf("\n\tX_GPE1_BLK=");
4350		acpi_print_gas(&fadt->XGpe1Block);
4351	}
4352	printf("\n");
4353
4354	if (sdp->Length < ACPI_FADT_V5_SIZE)
4355		goto out;
4356
4357	if (fadt->SleepControl.Address != 0) {
4358		printf("\tSleepControl=");
4359		acpi_print_gas(&fadt->SleepControl);
4360		printf("\n");
4361	}
4362	if (fadt->SleepStatus.Address != 0) {
4363		printf("\n\tSleepStatus=");
4364		acpi_print_gas(&fadt->SleepStatus);
4365		printf("\n");
4366	}
4367
4368	if (sdp->Length < ACPI_FADT_V6_SIZE)
4369		goto out;
4370
4371	printf("\tHypervisorId=0x%016"PRIx64"\n", fadt->HypervisorId);
4372
4373out:
4374	printf(END_COMMENT);
4375}
4376
4377static void
4378acpi_print_facs(ACPI_TABLE_FACS *facs)
4379{
4380	printf(BEGIN_COMMENT);
4381	printf("  FACS:\tLength=%u, ", facs->Length);
4382	printf("HwSig=0x%08x, ", facs->HardwareSignature);
4383	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
4384
4385#define PRINTFLAG(var, flag)	printflag((var), ACPI_GLOCK_## flag, #flag)
4386
4387	printf("\tGlobal_Lock=");
4388	PRINTFLAG(facs->GlobalLock, PENDING);
4389	PRINTFLAG(facs->GlobalLock, OWNED);
4390	PRINTFLAG_END();
4391
4392#undef PRINTFLAG
4393
4394#define PRINTFLAG(var, flag)	printflag((var), ACPI_FACS_## flag, #flag)
4395
4396	printf("\tFlags=");
4397	PRINTFLAG(facs->Flags, S4_BIOS_PRESENT);
4398	PRINTFLAG(facs->Flags, 64BIT_WAKE);
4399	PRINTFLAG_END();
4400
4401#undef PRINTFLAG
4402
4403	if (facs->XFirmwareWakingVector != 0)
4404		printf("\tX_Firm_Wake_Vec=%016jx\n",
4405		    (uintmax_t)facs->XFirmwareWakingVector);
4406	printf("\tVersion=%u\n", facs->Version);
4407
4408	printf("\tOspmFlags={");
4409	if (facs->OspmFlags & ACPI_FACS_64BIT_ENVIRONMENT)
4410		printf("64BIT_WAKE");
4411	printf("}\n");
4412
4413	printf(END_COMMENT);
4414}
4415
4416static void
4417acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
4418{
4419	printf(BEGIN_COMMENT);
4420	acpi_print_sdt(dsdp);
4421	printf(END_COMMENT);
4422}
4423
4424int
4425acpi_checksum(void *p, size_t length)
4426{
4427	uint8_t *bp;
4428	uint8_t sum;
4429
4430	bp = p;
4431	sum = 0;
4432	while (length--)
4433		sum += *bp++;
4434
4435	return (sum);
4436}
4437
4438static ACPI_TABLE_HEADER *
4439acpi_map_sdt(vm_offset_t pa)
4440{
4441	ACPI_TABLE_HEADER *sp;
4442
4443	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
4444	sp = acpi_map_physical(pa, sp->Length);
4445	return (sp);
4446}
4447
4448static void
4449acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
4450{
4451	printf(BEGIN_COMMENT);
4452	printf("  RSD PTR: OEM=");
4453	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
4454	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
4455	       rp->Revision);
4456	if (rp->Revision < 2) {
4457		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
4458		    rp->Checksum);
4459	} else {
4460		printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
4461		    (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
4462		    rp->ExtendedChecksum);
4463	}
4464	printf(END_COMMENT);
4465}
4466
4467static void
4468acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
4469{
4470	ACPI_TABLE_HEADER *sdp;
4471	ACPI_TABLE_RSDT *rsdt;
4472	ACPI_TABLE_XSDT *xsdt;
4473	vm_offset_t addr = 0;
4474	int entries, i;
4475
4476	acpi_print_rsdt(rsdp);
4477	rsdt = (ACPI_TABLE_RSDT *)rsdp;
4478	xsdt = (ACPI_TABLE_XSDT *)rsdp;
4479	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
4480	for (i = 0; i < entries; i++) {
4481		if (addr_size == 4)
4482			addr = le32toh(rsdt->TableOffsetEntry[i]);
4483		else
4484			addr = le64toh(xsdt->TableOffsetEntry[i]);
4485		if (addr == 0)
4486			continue;
4487		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
4488		if (acpi_checksum(sdp, sdp->Length)) {
4489			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
4490			    sdp->Signature);
4491			if (sflag)
4492				continue;
4493		}
4494		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
4495			acpi_handle_fadt(sdp);
4496		else if (!memcmp(sdp->Signature, ACPI_SIG_BERT, 4))
4497			acpi_handle_bert(sdp);
4498		else if (!memcmp(sdp->Signature, ACPI_SIG_BGRT, 4))
4499			acpi_handle_bgrt(sdp);
4500		else if (!memcmp(sdp->Signature, ACPI_SIG_BOOT, 4))
4501			acpi_handle_boot(sdp);
4502		else if (!memcmp(sdp->Signature, ACPI_SIG_CPEP, 4))
4503			acpi_handle_cpep(sdp);
4504		else if (!memcmp(sdp->Signature, ACPI_SIG_CSRT, 4))
4505			acpi_handle_csrt(sdp);
4506		else if (!memcmp(sdp->Signature, ACPI_SIG_DBGP, 4))
4507			acpi_handle_dbgp(sdp);
4508		else if (!memcmp(sdp->Signature, ACPI_SIG_DBG2, 4))
4509			acpi_handle_dbg2(sdp);
4510		else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
4511			acpi_handle_dmar(sdp);
4512		else if (!memcmp(sdp->Signature, ACPI_SIG_EINJ, 4))
4513			acpi_handle_einj(sdp);
4514		else if (!memcmp(sdp->Signature, ACPI_SIG_ERST, 4))
4515			acpi_handle_erst(sdp);
4516		else if (!memcmp(sdp->Signature, ACPI_SIG_GTDT, 4))
4517			acpi_handle_gtdt(sdp);
4518		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
4519			acpi_handle_madt(sdp);
4520		else if (!memcmp(sdp->Signature, ACPI_SIG_MSCT, 4))
4521			acpi_handle_msct(sdp);
4522		else if (!memcmp(sdp->Signature, ACPI_SIG_HEST, 4))
4523			acpi_handle_hest(sdp);
4524		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
4525			acpi_handle_hpet(sdp);
4526		else if (!memcmp(sdp->Signature, ACPI_SIG_IORT, 4))
4527			acpi_handle_iort(sdp);
4528		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
4529			acpi_handle_ecdt(sdp);
4530		else if (!memcmp(sdp->Signature, ACPI_SIG_LPIT, 4))
4531			acpi_handle_lpit(sdp);
4532		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
4533			acpi_handle_mcfg(sdp);
4534		else if (!memcmp(sdp->Signature, ACPI_SIG_PCCT, 4))
4535			acpi_handle_pcct(sdp);
4536		else if (!memcmp(sdp->Signature, ACPI_SIG_PPTT, 4))
4537			acpi_handle_pptt(sdp);
4538		else if (!memcmp(sdp->Signature, ACPI_SIG_SBST, 4))
4539			acpi_handle_sbst(sdp);
4540		else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
4541			acpi_handle_slit(sdp);
4542		else if (!memcmp(sdp->Signature, ACPI_SIG_SPCR, 4))
4543			acpi_handle_spcr(sdp);
4544		else if (!memcmp(sdp->Signature, ACPI_SIG_SPMI, 4))
4545			acpi_handle_spmi(sdp);
4546		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
4547			acpi_handle_srat(sdp);
4548		else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
4549			acpi_handle_tcpa(sdp);
4550		else if (!memcmp(sdp->Signature, ACPI_SIG_TPM2, 4))
4551			acpi_handle_tpm2(sdp);
4552		else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
4553			acpi_handle_nfit(sdp);
4554		else if (!memcmp(sdp->Signature, ACPI_SIG_UEFI, 4))
4555			acpi_handle_uefi(sdp);
4556		else if (!memcmp(sdp->Signature, ACPI_SIG_WAET, 4))
4557			acpi_handle_waet(sdp);
4558		else if (!memcmp(sdp->Signature, ACPI_SIG_WDAT, 4))
4559			acpi_handle_wdat(sdp);
4560		else if (!memcmp(sdp->Signature, ACPI_SIG_WDDT, 4))
4561			acpi_handle_wddt(sdp);
4562		else if (!memcmp(sdp->Signature, ACPI_SIG_WDRT, 4))
4563			acpi_handle_wdrt(sdp);
4564		else {
4565			printf(BEGIN_COMMENT);
4566			acpi_print_sdt(sdp);
4567			printf("\n");
4568			acpi_dump_table(sdp);
4569			printf(END_COMMENT);
4570		}
4571	}
4572}
4573
4574ACPI_TABLE_HEADER *
4575sdt_load_devmem(void)
4576{
4577	ACPI_TABLE_RSDP *rp;
4578	ACPI_TABLE_HEADER *rsdp;
4579
4580	rp = acpi_find_rsd_ptr();
4581	if (!rp)
4582		errx(EXIT_FAILURE, "Can't find ACPI information");
4583
4584	if (tflag)
4585		acpi_print_rsd_ptr(rp);
4586	if (rp->Revision < 2) {
4587		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
4588		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
4589		    acpi_checksum(rsdp, rsdp->Length) != 0)
4590			errx(EXIT_FAILURE, "RSDT is corrupted");
4591		addr_size = sizeof(uint32_t);
4592	} else {
4593		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
4594		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
4595		    acpi_checksum(rsdp, rsdp->Length) != 0)
4596			errx(EXIT_FAILURE, "XSDT is corrupted");
4597		addr_size = sizeof(uint64_t);
4598	}
4599	return (rsdp);
4600}
4601
4602/* Write the DSDT to a file, concatenating any SSDTs (if present). */
4603static int
4604write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
4605{
4606	ACPI_TABLE_HEADER sdt;
4607	ACPI_TABLE_HEADER *ssdt;
4608	uint8_t sum;
4609
4610	/* Create a new checksum to account for the DSDT and any SSDTs. */
4611	sdt = *dsdt;
4612	if (rsdt != NULL) {
4613		sdt.Checksum = 0;
4614		sum = acpi_checksum(dsdt + 1, dsdt->Length -
4615		    sizeof(ACPI_TABLE_HEADER));
4616		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
4617		while (ssdt != NULL) {
4618			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
4619			sum += acpi_checksum(ssdt + 1,
4620			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
4621			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
4622		}
4623		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
4624		sdt.Checksum -= sum;
4625	}
4626
4627	/* Write out the DSDT header and body. */
4628	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
4629	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
4630
4631	/* Write out any SSDTs (if present.) */
4632	if (rsdt != NULL) {
4633		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
4634		while (ssdt != NULL) {
4635			write(fd, ssdt + 1, ssdt->Length -
4636			    sizeof(ACPI_TABLE_HEADER));
4637			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
4638		}
4639	}
4640	return (0);
4641}
4642
4643void
4644dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
4645{
4646	int	fd;
4647	mode_t	mode;
4648
4649	assert(outfile != NULL);
4650	mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
4651	fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
4652	if (fd == -1) {
4653		perror("dsdt_save_file");
4654		return;
4655	}
4656	write_dsdt(fd, rsdt, dsdp);
4657	close(fd);
4658}
4659
4660void
4661aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
4662{
4663	char buf[MAXPATHLEN], tmpstr[MAXPATHLEN], wrkdir[MAXPATHLEN];
4664	const char *iname = "/acpdump.din";
4665	const char *oname = "/acpdump.dsl";
4666	const char *tmpdir;
4667	FILE *fp;
4668	size_t len;
4669	int fd, status;
4670	pid_t pid;
4671
4672	if (rsdt == NULL)
4673		errx(EXIT_FAILURE, "aml_disassemble: invalid rsdt");
4674	if (dsdp == NULL)
4675		errx(EXIT_FAILURE, "aml_disassemble: invalid dsdp");
4676
4677	tmpdir = getenv("TMPDIR");
4678	if (tmpdir == NULL)
4679		tmpdir = _PATH_TMP;
4680	if (realpath(tmpdir, buf) == NULL) {
4681		perror("realpath tmp dir");
4682		return;
4683	}
4684	len = sizeof(wrkdir) - strlen(iname);
4685	if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
4686		fprintf(stderr, "$TMPDIR too long\n");
4687		return;
4688	}
4689	if  (mkdtemp(wrkdir) == NULL) {
4690		perror("mkdtemp tmp working dir");
4691		return;
4692	}
4693	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
4694	assert(len <= sizeof(tmpstr) - 1);
4695	fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
4696	if (fd < 0) {
4697		perror("iasl tmp file");
4698		return;
4699	}
4700	write_dsdt(fd, rsdt, dsdp);
4701	close(fd);
4702
4703	/* Run iasl -d on the temp file */
4704	if ((pid = fork()) == 0) {
4705		close(STDOUT_FILENO);
4706		if (vflag == 0)
4707			close(STDERR_FILENO);
4708		execl("/usr/bin/iasl", "iasl", "-d", tmpstr, NULL);
4709		err(EXIT_FAILURE, "exec");
4710	}
4711	if (pid > 0)
4712		wait(&status);
4713	if (unlink(tmpstr) < 0) {
4714		perror("unlink");
4715		goto out;
4716	}
4717	if (pid < 0) {
4718		perror("fork");
4719		goto out;
4720	}
4721	if (status != 0) {
4722		fprintf(stderr, "iasl exit status = %d\n", status);
4723	}
4724
4725	/* Dump iasl's output to stdout */
4726	len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
4727	assert(len <= sizeof(tmpstr) - 1);
4728	fp = fopen(tmpstr, "r");
4729	if (unlink(tmpstr) < 0) {
4730		perror("unlink");
4731		goto out;
4732	}
4733	if (fp == NULL) {
4734		perror("iasl tmp file (read)");
4735		goto out;
4736	}
4737	while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
4738		fwrite(buf, 1, len, stdout);
4739	fclose(fp);
4740
4741    out:
4742	if (rmdir(wrkdir) < 0)
4743		perror("rmdir");
4744}
4745
4746void
4747sdt_print_all(ACPI_TABLE_HEADER *rsdp)
4748{
4749	acpi_handle_rsdt(rsdp);
4750}
4751
4752/* Fetch a table matching the given signature via the RSDT. */
4753ACPI_TABLE_HEADER *
4754sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
4755{
4756	ACPI_TABLE_HEADER *sdt;
4757	ACPI_TABLE_RSDT *rsdt;
4758	ACPI_TABLE_XSDT *xsdt;
4759	vm_offset_t addr = 0;
4760	int entries, i;
4761
4762	rsdt = (ACPI_TABLE_RSDT *)rsdp;
4763	xsdt = (ACPI_TABLE_XSDT *)rsdp;
4764	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
4765	for (i = 0; i < entries; i++) {
4766		if (addr_size == 4)
4767			addr = le32toh(rsdt->TableOffsetEntry[i]);
4768		else
4769			addr = le64toh(xsdt->TableOffsetEntry[i]);
4770		if (addr == 0)
4771			continue;
4772		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
4773		if (last != NULL) {
4774			if (sdt == last)
4775				last = NULL;
4776			continue;
4777		}
4778		if (memcmp(sdt->Signature, sig, strlen(sig)))
4779			continue;
4780		if (acpi_checksum(sdt, sdt->Length))
4781			errx(EXIT_FAILURE, "RSDT entry %d is corrupt", i);
4782		return (sdt);
4783	}
4784
4785	return (NULL);
4786}
4787
4788ACPI_TABLE_HEADER *
4789dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
4790{
4791	ACPI_TABLE_HEADER	*sdt;
4792
4793	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
4794	sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(
4795		acpi_select_address(fadt->Dsdt, fadt->XDsdt));
4796	if (acpi_checksum(sdt, sdt->Length))
4797		errx(EXIT_FAILURE, "DSDT is corrupt");
4798	return (sdt);
4799}
4800