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