acpi.c revision 1.19 1 /* $NetBSD: acpi.c,v 1.19 2017/08/31 06:53:58 msaitoh 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.19 2017/08/31 06:53:58 msaitoh Exp $");
34
35 #include <sys/param.h>
36 #include <sys/endian.h>
37 #include <sys/stat.h>
38 #include <sys/wait.h>
39 #include <assert.h>
40 #include <err.h>
41 #include <fcntl.h>
42 #include <paths.h>
43 #include <stdio.h>
44 #include <stdint.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <stddef.h>
49 #include <uuid.h>
50
51 #include "acpidump.h"
52
53 #define BEGIN_COMMENT "/*\n"
54 #define END_COMMENT " */\n"
55
56 static void acpi_print_string(char *s, size_t length);
57 static void acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
58 static void acpi_print_pci(uint16_t vendorid, uint16_t deviceid,
59 uint8_t seg, uint8_t bus, uint8_t device, uint8_t func);
60 static void acpi_print_pci_sbfd(uint8_t seg, uint8_t bus, uint8_t device,
61 uint8_t func);
62 #ifdef notyet
63 static void acpi_print_hest_generic_status(ACPI_HEST_GENERIC_STATUS *);
64 static void acpi_print_hest_generic_data(ACPI_HEST_GENERIC_DATA *);
65 #endif
66 static void acpi_print_whea(ACPI_WHEA_HEADER *whea,
67 void (*print_action)(ACPI_WHEA_HEADER *),
68 void (*print_ins)(ACPI_WHEA_HEADER *),
69 void (*print_flags)(ACPI_WHEA_HEADER *));
70 static int acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
71 static uint64_t acpi_select_address(uint32_t, uint64_t);
72 static void acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
73 static void acpi_print_cpu(u_char cpu_id);
74 static void acpi_print_cpu_uid(uint32_t uid, char *uid_string);
75 static void acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
76 static void acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
77 uint64_t apic_addr);
78 static void acpi_print_mps_flags(uint16_t flags);
79 static void acpi_print_intr(uint32_t intr, uint16_t mps_flags);
80 static void acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
81 static void acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
82 static void acpi_handle_bert(ACPI_TABLE_HEADER *sdp);
83 static void acpi_handle_boot(ACPI_TABLE_HEADER *sdp);
84 static void acpi_handle_cpep(ACPI_TABLE_HEADER *sdp);
85 static void acpi_handle_dbgp(ACPI_TABLE_HEADER *sdp);
86 static void acpi_handle_einj(ACPI_TABLE_HEADER *sdp);
87 static void acpi_handle_erst(ACPI_TABLE_HEADER *sdp);
88 static void acpi_handle_hest(ACPI_TABLE_HEADER *sdp);
89 static void acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
90 static void acpi_handle_msct(ACPI_TABLE_HEADER *sdp);
91 static void acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
92 static void acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
93 static void acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
94 static void acpi_handle_sbst(ACPI_TABLE_HEADER *sdp);
95 static void acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
96 static void acpi_handle_spcr(ACPI_TABLE_HEADER *sdp);
97 static void acpi_print_srat_cpu(uint32_t apic_id,
98 uint32_t proximity_domain,
99 uint32_t flags, uint32_t clockdomain);
100 static void acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
101 static void acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
102 static void acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
103 static void acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
104 static void acpi_print_nfit(ACPI_NFIT_HEADER *nfit);
105 static void acpi_handle_nfit(ACPI_TABLE_HEADER *sdp);
106 static void acpi_handle_waet(ACPI_TABLE_HEADER *sdp);
107 static void acpi_handle_wdat(ACPI_TABLE_HEADER *sdp);
108 static void acpi_handle_wdrt(ACPI_TABLE_HEADER *sdp);
109 static void acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
110 static void acpi_dump_bytes(ACPI_TABLE_HEADER *sdp);
111 static void acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
112 static void acpi_print_facs(ACPI_TABLE_FACS *facs);
113 static void acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
114 static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
115 static void acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
116 static void acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
117 static void acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
118 void (*action)(ACPI_SUBTABLE_HEADER *));
119 static void acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
120 void (*action)(ACPI_NFIT_HEADER *));
121
122 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
123 static int addr_size;
124
125 /* Strings used in the TCPA table */
126 static const char *tcpa_event_type_strings[] = {
127 "PREBOOT Certificate",
128 "POST Code",
129 "Unused",
130 "No Action",
131 "Separator",
132 "Action",
133 "Event Tag",
134 "S-CRTM Contents",
135 "S-CRTM Version",
136 "CPU Microcode",
137 "Platform Config Flags",
138 "Table of Devices",
139 "Compact Hash",
140 "IPL",
141 "IPL Partition Data",
142 "Non-Host Code",
143 "Non-Host Config",
144 "Non-Host Info"
145 };
146
147 static const char *TCPA_pcclient_strings[] = {
148 "<undefined>",
149 "SMBIOS",
150 "BIS Certificate",
151 "POST BIOS ROM Strings",
152 "ESCD",
153 "CMOS",
154 "NVRAM",
155 "Option ROM Execute",
156 "Option ROM Configurateion",
157 "<undefined>",
158 "Option ROM Microcode Update ",
159 "S-CRTM Version String",
160 "S-CRTM Contents",
161 "POST Contents",
162 "Table of Devices",
163 };
164
165 #define PRINTFLAG_END() printflag_end()
166
167 static char pf_sep = '{';
168
169 static void
170 printflag_end(void)
171 {
172
173 if (pf_sep != '{') {
174 printf("}");
175 pf_sep = '{';
176 }
177 printf("\n");
178 }
179
180 static void
181 printflag(uint64_t var, uint64_t mask, const char *name)
182 {
183
184 if (var & mask) {
185 printf("%c%s", pf_sep, name);
186 pf_sep = ',';
187 }
188 }
189
190 static void
191 acpi_print_string(char *s, size_t length)
192 {
193 int c;
194
195 /* Trim trailing spaces and NULLs */
196 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
197 length--;
198
199 while (length--) {
200 c = *s++;
201 putchar(c);
202 }
203 }
204
205 static void
206 acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
207 {
208 switch(gas->SpaceId) {
209 case ACPI_GAS_MEMORY:
210 if (gas->BitWidth <= 32)
211 printf("0x%08x:%u[%u] (Memory)",
212 (u_int)gas->Address, gas->BitOffset,
213 gas->BitWidth);
214 else
215 printf("0x%016jx:%u[%u] (Memory)",
216 (uintmax_t)gas->Address, gas->BitOffset,
217 gas->BitWidth);
218 break;
219 case ACPI_GAS_IO:
220 printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address,
221 gas->BitOffset, gas->BitWidth);
222 break;
223 case ACPI_GAS_PCI:
224 printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
225 (uint16_t)((gas->Address >> 16) & 0xffff),
226 (uint16_t)gas->Address);
227 break;
228 /* XXX How to handle these below? */
229 case ACPI_GAS_EMBEDDED:
230 printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
231 gas->BitOffset, gas->BitWidth);
232 break;
233 case ACPI_GAS_SMBUS:
234 printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
235 gas->BitOffset, gas->BitWidth);
236 break;
237 case ACPI_GAS_CMOS:
238 case ACPI_GAS_PCIBAR:
239 case ACPI_GAS_DATATABLE:
240 case ACPI_GAS_FIXED:
241 default:
242 printf("0x%016jx (?)", (uintmax_t)gas->Address);
243 break;
244 }
245 }
246
247 static void
248 acpi_print_pci(uint16_t vendorid, uint16_t deviceid,
249 uint8_t seg, uint8_t bus, uint8_t device, uint8_t func)
250 {
251 if (vendorid == 0xffff && deviceid == 0xffff) {
252 printf("\tPCI Device=NONE\n");
253 return;
254 }
255
256 printf("\tPCI device={\n");
257 printf("\t\tVendor=0x%x\n", vendorid);
258 printf("\t\tDevice=0x%x\n", deviceid);
259 printf("\n");
260 printf("\t\tSegment Group=%d\n", seg);
261 printf("\t\tBus=%d\n", bus);
262 printf("\t\tDevice=%d\n", device);
263 printf("\t\tFunction=%d\n", func);
264 printf("\t}\n");
265 }
266
267 static void
268 acpi_print_pci_sbfd(uint8_t seg, uint8_t bus, uint8_t device, uint8_t func)
269 {
270 if (bus == 0xff && device == 0xff && func == 0xff) {
271 printf("\tPCI Device=NONE\n");
272 return;
273 }
274
275 printf("\tPCI device={\n");
276 printf("\t\tSegment Group=%d\n", seg);
277 printf("\t\tBus=%d\n", bus);
278 printf("\t\tDevice=%d\n", device);
279 printf("\t\tFunction=%d\n", func);
280 printf("\t}\n");
281 }
282
283 #ifdef notyet
284 static void
285 acpi_print_hest_errorseverity(uint32_t error)
286 {
287 printf("\tError Severity={ ");
288 switch (error) {
289 case 0:
290 printf("Recoverable");
291 break;
292 case 1:
293 printf("Fatal");
294 break;
295 case 2:
296 printf("Corrected");
297 break;
298 case 3:
299 printf("None");
300 break;
301 default:
302 printf("%d (reserved)", error);
303 break;
304 }
305 printf("}\n");
306 }
307 #endif
308
309 static void
310 acpi_print_hest_errorbank(ACPI_HEST_IA_ERROR_BANK *bank)
311 {
312 printf("\n");
313 printf("\tBank Number=%d\n", bank->BankNumber);
314 printf("\tClear Status On Init={ %s }\n",
315 bank->ClearStatusOnInit ? "NO" : "YES");
316 printf("\tStatus Data Format={ ");
317 switch (bank->StatusFormat) {
318 case 0:
319 printf("IA32 MCA");
320 break;
321 case 1:
322 printf("EMT64 MCA");
323 break;
324 case 2:
325 printf("AMD64 MCA");
326 break;
327 }
328 printf(" }\n");
329
330 if (bank->ControlRegister)
331 printf("\tControl Register=0x%x\n", bank->ControlRegister);
332 printf("\tControl Init Data=0x%"PRIx64"\n", bank->ControlData);
333 printf("\tStatus MSR=0x%x\n", bank->StatusRegister);
334 printf("\tAddress MSR=0x%x\n", bank->AddressRegister);
335 printf("\tMisc MSR=0x%x\n", bank->MiscRegister);
336 }
337
338 static void
339 acpi_print_hest_header(ACPI_HEST_HEADER *hest)
340 {
341 printf("\tType={ ");
342 switch (hest->Type) {
343 case ACPI_HEST_TYPE_IA32_CHECK:
344 printf("IA32 Machine Check Exception");
345 break;
346 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
347 printf("IA32 Corrected Machine Check\n");
348 break;
349 case ACPI_HEST_TYPE_IA32_NMI:
350 printf("IA32 Non-Maskable Interrupt\n");
351 break;
352 case ACPI_HEST_TYPE_NOT_USED3:
353 case ACPI_HEST_TYPE_NOT_USED4:
354 case ACPI_HEST_TYPE_NOT_USED5:
355 printf("unused type: %d\n", hest->Type);
356 break;
357 case ACPI_HEST_TYPE_AER_ROOT_PORT:
358 printf("PCI Express Root Port AER\n");
359 break;
360 case ACPI_HEST_TYPE_AER_ENDPOINT:
361 printf("PCI Express Endpoint AER\n");
362 break;
363 case ACPI_HEST_TYPE_AER_BRIDGE:
364 printf("PCI Express/PCI-X Bridge AER\n");
365 break;
366 case ACPI_HEST_TYPE_GENERIC_ERROR:
367 printf("Generic Hardware Error Source\n");
368 break;
369 case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
370 printf("Generic Hardware Error Source version 2\n");
371 break;
372 case ACPI_HEST_TYPE_RESERVED:
373 default:
374 printf("Reserved\n");
375 break;
376 }
377 printf(" }\n");
378 printf("\tSourceId=%d\n", hest->SourceId);
379 }
380
381 static void
382 acpi_print_hest_aer_common(ACPI_HEST_AER_COMMON *data)
383 {
384 printf("\tFlags={ ");
385 if (data->Flags & ACPI_HEST_FIRMWARE_FIRST)
386 printf("FIRMWARE_FIRST");
387 if (data->Flags & ACPI_HEST_GLOBAL)
388 printf("GLOBAL");
389 printf(" }\n");
390 printf("\tEnabled={ %s ", data->Flags ? "YES" : "NO");
391 if (data->Flags & ACPI_HEST_FIRMWARE_FIRST)
392 printf("(ignored) ");
393 printf("}\n");
394 printf("\tNumber of Record to pre-allocate=%d\n",
395 data->RecordsToPreallocate);
396 printf("\tMax. Sections per Record=%d\n", data->MaxSectionsPerRecord);
397 if (!(data->Flags & ACPI_HEST_GLOBAL))
398 acpi_print_pci_sbfd(0, data->Bus, data->Device, data->Function);
399 printf("\tDevice Control=0x%x\n", data->DeviceControl);
400 printf("\tUncorrectable Error Mask Register=0x%x\n",
401 data->UncorrectableMask);
402 printf("\tUncorrectable Error Severity Register=0x%x\n",
403 data->UncorrectableSeverity);
404 printf("\tCorrectable Error Mask Register=0x%x\n",
405 data->CorrectableMask);
406 printf("\tAdvanced Capabilities Register=0x%x\n",
407 data->AdvancedCapabilities);
408 }
409
410 static void
411 acpi_print_hest_notify(ACPI_HEST_NOTIFY *notify)
412 {
413 printf("\tHW Error Notification={\n");
414 printf("\t\tType={ ");
415 switch (notify->Type) {
416 case ACPI_HEST_NOTIFY_POLLED:
417 printf("POLLED");
418 break;
419 case ACPI_HEST_NOTIFY_EXTERNAL:
420 printf("EXTERN");
421 break;
422 case ACPI_HEST_NOTIFY_LOCAL:
423 printf("LOCAL");
424 break;
425 case ACPI_HEST_NOTIFY_SCI:
426 printf("SCI");
427 break;
428 case ACPI_HEST_NOTIFY_NMI:
429 printf("NMI");
430 break;
431 case ACPI_HEST_NOTIFY_CMCI:
432 printf("CMCI");
433 break;
434 case ACPI_HEST_NOTIFY_MCE:
435 printf("MCE");
436 break;
437 case ACPI_HEST_NOTIFY_GPIO:
438 printf("GPIO-Signal");
439 break;
440 case ACPI_HEST_NOTIFY_SEA:
441 printf("ARMv8 SEA");
442 break;
443 case ACPI_HEST_NOTIFY_SEI:
444 printf("ARMv8 SEI");
445 break;
446 case ACPI_HEST_NOTIFY_GSIV:
447 printf("External Interrupt - GSIV");
448 break;
449 case ACPI_HEST_NOTIFY_RESERVED:
450 printf("RESERVED");
451 break;
452 default:
453 printf(" %d (reserved)", notify->Type);
454 break;
455 }
456 printf(" }\n");
457
458 printf("\t\tLength=%d\n", notify->Length);
459 printf("\t\tConfig Write Enable={\n");
460 if (notify->ConfigWriteEnable & ACPI_HEST_TYPE)
461 printf("TYPE");
462 if (notify->ConfigWriteEnable & ACPI_HEST_POLL_INTERVAL)
463 printf("POLL INTERVAL");
464 if (notify->ConfigWriteEnable & ACPI_HEST_POLL_THRESHOLD_VALUE)
465 printf("THRESHOLD VALUE");
466 if (notify->ConfigWriteEnable & ACPI_HEST_POLL_THRESHOLD_WINDOW)
467 printf("THRESHOLD WINDOW");
468 if (notify->ConfigWriteEnable & ACPI_HEST_ERR_THRESHOLD_VALUE)
469 printf("THRESHOLD VALUE");
470 if (notify->ConfigWriteEnable & ACPI_HEST_ERR_THRESHOLD_WINDOW)
471 printf("THRESHOLD WINDOW");
472 printf("}\n");
473
474 printf("\t\tPoll Interval=%d msec\n", notify->PollInterval);
475 printf("\t\tInterrupt Vector=%d\n", notify->Vector);
476 printf("\t\tSwitch To Polling Threshold Value=%d\n",
477 notify->PollingThresholdValue);
478 printf("\t\tSwitch To Polling Threshold Window=%d msec\n",
479 notify->PollingThresholdWindow);
480 printf("\t\tError Threshold Value=%d\n",
481 notify->ErrorThresholdValue);
482 printf("\t\tError Threshold Window=%d msec\n",
483 notify->ErrorThresholdWindow);
484 printf("\t}\n");
485 }
486
487 #ifdef notyet
488 static void
489 acpi_print_hest_generic_status(ACPI_HEST_GENERIC_STATUS *data)
490 {
491 uint32_t i, pos, entries;
492 ACPI_HEST_GENERIC_DATA *gen;
493
494 entries = data->BlockStatus & ACPI_HEST_ERROR_ENTRY_COUNT;
495
496 printf("\tGeneric Error Status={\n");
497 printf("\t\tBlock Status={ ");
498 if (data->BlockStatus & ACPI_HEST_UNCORRECTABLE)
499 printf("UNCORRECTABLE");
500 if (data->BlockStatus & ACPI_HEST_CORRECTABLE)
501 printf("CORRECTABLE");
502 if (data->BlockStatus & ACPI_HEST_MULTIPLE_UNCORRECTABLE)
503 printf("MULTIPLE UNCORRECTABLE");
504 if (data->BlockStatus & ACPI_HEST_MULTIPLE_CORRECTABLE)
505 printf("MULTIPLE CORRECTABLE");
506 printf(" }\n");
507 printf("\t\tEntry Count=%d\n", entries);
508 printf("\t\tRaw Data Offset=%d\n", data->RawDataOffset);
509 printf("\t\tRaw Data Length=%d\n", data->RawDataLength);
510 printf("\t\tData Length=%d\n", data->DataLength);
511 printf("\t");
512 acpi_print_hest_errorseverity(data->ErrorSeverity);
513 printf("\t}\n");
514
515 pos = sizeof(ACPI_HEST_GENERIC_STATUS);
516 for (i = 0; i < entries; i++) {
517 gen = (ACPI_HEST_GENERIC_DATA *)((char *)data + pos);
518 acpi_print_hest_generic_data(gen);
519 pos += sizeof(ACPI_HEST_GENERIC_DATA);
520 }
521 }
522 #endif
523
524 #ifdef notyet
525 static void
526 acpi_print_hest_generic_data(ACPI_HEST_GENERIC_DATA *data)
527 {
528 printf("\tGeneric Error Data={\n");
529 printf("\t\tSectionType=");
530 acpi_print_string((char *)data->SectionType, sizeof(data->SectionType));
531 printf("\n\t");
532 acpi_print_hest_errorseverity(data->ErrorSeverity);
533 printf("\t\tRevision=0x%x\n", data->Revision);
534 printf("\t\tValidation Bits=0x%x\n", data->ValidationBits);
535 printf("\t\tFlags=0x%x\n", data->Flags);
536 printf("\t\tData Length=%d\n", data->ErrorDataLength);
537 printf("\t\tField Replication Unit Id=");
538 acpi_print_string((char *)data->FruId, sizeof(data->FruId));
539 printf("\n");
540 printf("\t\tField Replication Unit=");
541 acpi_print_string((char *)data->FruText, sizeof(data->FruText));
542 printf("\n");
543 printf("\t}\n");
544 }
545 #endif
546
547 static void
548 acpi_print_whea(ACPI_WHEA_HEADER *whea,
549 void (*print_action)(ACPI_WHEA_HEADER *),
550 void (*print_ins)(ACPI_WHEA_HEADER *),
551 void (*print_flags)(ACPI_WHEA_HEADER *))
552 {
553 printf("\n");
554
555 print_action(whea);
556 print_ins(whea);
557 if (print_flags)
558 print_flags(whea);
559 printf("\tRegisterRegion=");
560 acpi_print_gas(&whea->RegisterRegion);
561 printf("\n");
562 printf("\tMASK=0x%08"PRIx64"\n", whea->Mask);
563 }
564
565 static void
566 acpi_print_hest_ia32_check(ACPI_HEST_IA_MACHINE_CHECK *data)
567 {
568 uint32_t i, pos;
569 ACPI_HEST_IA_ERROR_BANK *bank;
570
571 acpi_print_hest_header(&data->Header);
572 printf("\tFlags={ ");
573 if (data->Flags & ACPI_HEST_FIRMWARE_FIRST)
574 printf("FIRMWARE_FIRST");
575 printf(" }\n");
576 printf("\tEnabled={ %s }\n", data->Enabled ? "YES" : "NO");
577 printf("\tNumber of Record to pre-allocate=%d\n",
578 data->RecordsToPreallocate);
579 printf("\tMax Sections per Record=%d\n",
580 data->MaxSectionsPerRecord);
581 printf("\tGlobal Capability Init Data=0x%"PRIx64"\n",
582 data->GlobalCapabilityData);
583 printf("\tGlobal Control Init Data=0x%"PRIx64"\n",
584 data->GlobalControlData);
585 printf("\tNumber of Hardware Error Reporting Banks=%d\n",
586 data->NumHardwareBanks);
587
588 pos = sizeof(ACPI_HEST_IA_MACHINE_CHECK);
589 for (i = 0; i < data->NumHardwareBanks; i++) {
590 bank = (ACPI_HEST_IA_ERROR_BANK *)((char *)data + pos);
591 acpi_print_hest_errorbank(bank);
592 pos += sizeof(ACPI_HEST_IA_ERROR_BANK);
593 }
594 }
595
596 static void
597 acpi_print_hest_ia32_correctedcheck(ACPI_HEST_IA_CORRECTED *data)
598 {
599 uint32_t i, pos;
600 ACPI_HEST_IA_ERROR_BANK *bank;
601
602 acpi_print_hest_header(&data->Header);
603 printf("\tFlags={ ");
604 if (data->Flags & ACPI_HEST_FIRMWARE_FIRST)
605 printf("FIRMWARE_FIRST");
606 printf(" }\n");
607 printf("\tEnabled={ %s }\n", data->Enabled ? "YES" : "NO");
608 printf("\tNumber of Record to pre-allocate=%d\n",
609 data->RecordsToPreallocate);
610 printf("\tMax Sections per Record=%d\n",
611 data->MaxSectionsPerRecord);
612 acpi_print_hest_notify(&data->Notify);
613
614 printf("\tNumber of Hardware Error Reporting Banks=%d\n",
615 data->NumHardwareBanks);
616
617 pos = sizeof(ACPI_HEST_IA_MACHINE_CHECK);
618 for (i = 0; i < data->NumHardwareBanks; i++) {
619 bank = (ACPI_HEST_IA_ERROR_BANK *)((char *)data + pos);
620 acpi_print_hest_errorbank(bank);
621 pos += sizeof(ACPI_HEST_IA_ERROR_BANK);
622 }
623 }
624
625 static void
626 acpi_print_hest_ia32_nmi(ACPI_HEST_IA_NMI *data)
627 {
628 acpi_print_hest_header(&data->Header);
629 printf("\tNumber of Record to pre-allocate=%d\n",
630 data->RecordsToPreallocate);
631 printf("\tMax Sections per Record=%d\n",
632 data->MaxSectionsPerRecord);
633 printf("\tMax Raw Data Length=%d\n",
634 data->MaxRawDataLength);
635 }
636
637 static void
638 acpi_print_hest_aer_root(ACPI_HEST_AER_ROOT *data)
639 {
640 acpi_print_hest_header(&data->Header);
641 acpi_print_hest_aer_common(&data->Aer);
642 printf("Root Error Command Register=0x%x\n", data->RootErrorCommand);
643 }
644
645 static void
646 acpi_print_hest_aer_endpoint(ACPI_HEST_AER *data)
647 {
648 acpi_print_hest_header(&data->Header);
649 acpi_print_hest_aer_common(&data->Aer);
650 }
651
652 static void
653 acpi_print_hest_aer_bridge(ACPI_HEST_AER_BRIDGE *data)
654 {
655 acpi_print_hest_header(&data->Header);
656 acpi_print_hest_aer_common(&data->Aer);
657
658 printf("\tSecondary Uncorrectable Error Mask Register=0x%x\n",
659 data->UncorrectableMask2);
660 printf("\tSecondary Uncorrectable Error Severity Register=0x%x\n",
661 data->UncorrectableSeverity2);
662 printf("\tSecondory Advanced Capabilities Register=0x%x\n",
663 data->AdvancedCapabilities2);
664 }
665
666 static void
667 acpi_print_hest_generic(ACPI_HEST_GENERIC *data)
668 {
669 acpi_print_hest_header(&data->Header);
670 if (data->RelatedSourceId != 0xffff)
671 printf("\tReleated SourceId=%d\n", data->RelatedSourceId);
672 printf("\tEnabled={ %s }\n", data->Enabled ? "YES" : "NO");
673 printf("\tNumber of Records to pre-allocate=%d\n",
674 data->RecordsToPreallocate);
675 printf("\tMax Sections per Record=%d\n",
676 data->MaxSectionsPerRecord);
677 printf("\tMax Raw Data Length=%d\n", data->MaxRawDataLength);
678 printf("\tError Status Address=");
679 acpi_print_gas(&data->ErrorStatusAddress);
680 acpi_print_hest_notify(&data->Notify);
681 printf("\tError Block Length=%d\n", data->ErrorBlockLength);
682 }
683
684 static void
685 acpi_print_hest_generic_v2(ACPI_HEST_GENERIC_V2 *data)
686 {
687
688 /* The first 64 bytes are the same as ACPI_HEST_GENERIC */
689 acpi_print_hest_generic((ACPI_HEST_GENERIC *)data);
690
691 printf("\tError Status Address");
692 acpi_print_gas(&data->ReadAckRegister);
693 printf("\tRead Ack Preserve=0x%016jx\n",
694 (uintmax_t)data->ReadAckPreserve);
695 printf("\tRead Ack Write=0x%016jx\n",
696 (uintmax_t)data->ReadAckWrite);
697 }
698
699 static void
700 acpi_handle_hest(ACPI_TABLE_HEADER *sdp)
701 {
702 ACPI_TABLE_HEST *hest;
703 ACPI_HEST_HEADER *subhest;
704 uint32_t i, pos;
705 void *subtable;
706
707 printf(BEGIN_COMMENT);
708 acpi_print_sdt(sdp);
709 hest = (ACPI_TABLE_HEST *)sdp;
710
711 printf("\tError Source Count=%d\n", hest->ErrorSourceCount);
712 pos = sizeof(ACPI_TABLE_HEST);
713 for (i = 0; i < hest->ErrorSourceCount; i++) {
714 subhest = (ACPI_HEST_HEADER *)((char *)hest + pos);
715 subtable = (void *)((char *)subhest + sizeof(ACPI_HEST_HEADER));
716 printf("\n");
717
718 printf("\tType={ ");
719 switch (subhest->Type) {
720 case ACPI_HEST_TYPE_IA32_CHECK:
721 acpi_print_hest_ia32_check(subtable);
722 pos += sizeof(ACPI_HEST_IA_MACHINE_CHECK);
723 break;
724
725 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
726 acpi_print_hest_ia32_correctedcheck(subtable);
727 pos += sizeof(ACPI_HEST_IA_CORRECTED);
728 break;
729
730 case ACPI_HEST_TYPE_IA32_NMI:
731 acpi_print_hest_ia32_nmi(subtable);
732 pos += sizeof(ACPI_HEST_IA_NMI);
733 break;
734
735 case ACPI_HEST_TYPE_NOT_USED3:
736 case ACPI_HEST_TYPE_NOT_USED4:
737 case ACPI_HEST_TYPE_NOT_USED5:
738 pos += sizeof(ACPI_HEST_HEADER);
739 break;
740
741 case ACPI_HEST_TYPE_AER_ROOT_PORT:
742 acpi_print_hest_aer_root(subtable);
743 pos += sizeof(ACPI_HEST_AER_ROOT);
744 break;
745
746 case ACPI_HEST_TYPE_AER_ENDPOINT:
747 acpi_print_hest_aer_endpoint(subtable);
748 pos += sizeof(ACPI_HEST_AER_ROOT);
749 break;
750
751 case ACPI_HEST_TYPE_AER_BRIDGE:
752 acpi_print_hest_aer_bridge(subtable);
753 pos += sizeof(ACPI_HEST_AER_BRIDGE);
754 break;
755
756 case ACPI_HEST_TYPE_GENERIC_ERROR:
757 acpi_print_hest_generic(subtable);
758 pos += sizeof(ACPI_HEST_GENERIC);
759 break;
760
761 case ACPI_HEST_TYPE_GENERIC_ERROR_V2:
762 acpi_print_hest_generic_v2(subtable);
763 pos += sizeof(ACPI_HEST_GENERIC_V2);
764 break;
765
766 case ACPI_HEST_TYPE_RESERVED:
767 default:
768 pos += sizeof(ACPI_HEST_HEADER);
769 break;
770 }
771 }
772
773 printf(END_COMMENT);
774 }
775
776 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
777 static int
778 acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
779 {
780 int fadt_revision;
781
782 /* Set the FADT revision separately from the RSDP version. */
783 if (addr_size == 8) {
784 fadt_revision = 2;
785
786 /*
787 * A few systems (e.g., IBM T23) have an RSDP that claims
788 * revision 2 but the 64 bit addresses are invalid. If
789 * revision 2 and the 32 bit address is non-zero but the
790 * 32 and 64 bit versions don't match, prefer the 32 bit
791 * version for all subsequent tables.
792 */
793 if (fadt->Facs != 0 &&
794 (fadt->XFacs & 0xffffffff) != fadt->Facs)
795 fadt_revision = 1;
796 } else
797 fadt_revision = 1;
798 return (fadt_revision);
799 }
800
801 static uint64_t
802 acpi_select_address(uint32_t addr32, uint64_t addr64)
803 {
804
805 if (addr64 == 0)
806 return addr32;
807
808 if ((addr32 != 0) && ((addr64 & 0xfffffff) != addr32)) {
809 /*
810 * A few systems (e.g., IBM T23) have an RSDP that claims
811 * revision 2 but the 64 bit addresses are invalid. If
812 * revision 2 and the 32 bit address is non-zero but the
813 * 32 and 64 bit versions don't match, prefer the 32 bit
814 * version for all subsequent tables.
815 */
816 return addr32;
817 }
818
819 return addr64;
820 }
821
822 static void
823 acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
824 {
825 ACPI_TABLE_HEADER *dsdp;
826 ACPI_TABLE_FACS *facs;
827 ACPI_TABLE_FADT *fadt;
828
829 fadt = (ACPI_TABLE_FADT *)sdp;
830 acpi_print_fadt(sdp);
831
832 facs = (ACPI_TABLE_FACS *)acpi_map_sdt(
833 acpi_select_address(fadt->Facs, fadt->XFacs));
834 if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
835 errx(EXIT_FAILURE, "FACS is corrupt");
836 acpi_print_facs(facs);
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_handle_dbgp(ACPI_TABLE_HEADER *sdp)
1256 {
1257 ACPI_TABLE_DBGP *dbgp;
1258
1259 printf(BEGIN_COMMENT);
1260 acpi_print_sdt(sdp);
1261 dbgp = (ACPI_TABLE_DBGP *)sdp;
1262 printf("\tType={");
1263 switch (dbgp->Type) {
1264 case 0:
1265 printf("full 16550");
1266 break;
1267 case 1:
1268 printf("subset of 16550");
1269 break;
1270 }
1271 printf("}\n");
1272 printf("DebugPort=");
1273 acpi_print_gas(&dbgp->DebugPort);
1274 printf(END_COMMENT);
1275 }
1276
1277 static void
1278 acpi_print_einj_action(ACPI_WHEA_HEADER *whea)
1279 {
1280 printf("\tACTION={");
1281 switch (whea->Action) {
1282 case ACPI_EINJ_BEGIN_OPERATION:
1283 printf("Begin Operation");
1284 break;
1285 case ACPI_EINJ_GET_TRIGGER_TABLE:
1286 printf("Get Trigger Table");
1287 break;
1288 case ACPI_EINJ_SET_ERROR_TYPE:
1289 printf("Set Error Type");
1290 break;
1291 case ACPI_EINJ_GET_ERROR_TYPE:
1292 printf("Get Error Type");
1293 break;
1294 case ACPI_EINJ_END_OPERATION:
1295 printf("End Operation");
1296 break;
1297 case ACPI_EINJ_EXECUTE_OPERATION:
1298 printf("Execute Operation");
1299 break;
1300 case ACPI_EINJ_CHECK_BUSY_STATUS:
1301 printf("Check Busy Status");
1302 break;
1303 case ACPI_EINJ_GET_COMMAND_STATUS:
1304 printf("Get Command Status");
1305 break;
1306 case ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS:
1307 printf("Set Error Type With Address");
1308 break;
1309 case ACPI_EINJ_GET_EXECUTE_TIMINGS:
1310 printf("Get Execute Operation Timings");
1311 break;
1312 case ACPI_EINJ_ACTION_RESERVED:
1313 printf("Preserved");
1314 break;
1315 case ACPI_EINJ_TRIGGER_ERROR:
1316 printf("Trigger Error");
1317 break;
1318 default:
1319 printf("%d", whea->Action);
1320 break;
1321 }
1322 printf("}\n");
1323 }
1324
1325 static void
1326 acpi_print_einj_instruction(ACPI_WHEA_HEADER *whea)
1327 {
1328 uint32_t ins = whea->Instruction;
1329
1330 printf("\tINSTRUCTION={");
1331 switch (ins) {
1332 case ACPI_EINJ_READ_REGISTER:
1333 printf("Read Register");
1334 break;
1335 case ACPI_EINJ_READ_REGISTER_VALUE:
1336 printf("Read Register Value");
1337 break;
1338 case ACPI_EINJ_WRITE_REGISTER:
1339 printf("Write Register");
1340 break;
1341 case ACPI_EINJ_WRITE_REGISTER_VALUE:
1342 printf("Write Register Value");
1343 break;
1344 case ACPI_EINJ_NOOP:
1345 printf("Noop");
1346 break;
1347 case ACPI_EINJ_INSTRUCTION_RESERVED:
1348 printf("Reserved");
1349 break;
1350 default:
1351 printf("%d", ins);
1352 break;
1353 }
1354 printf("}\n");
1355 }
1356
1357 static void
1358 acpi_print_einj_flags(ACPI_WHEA_HEADER *whea)
1359 {
1360 uint32_t flags = whea->Flags;
1361
1362 printf("\tFLAGS={ ");
1363 if (flags & ACPI_EINJ_PRESERVE)
1364 printf("PRESERVED");
1365 printf("}\n");
1366 }
1367
1368 static void
1369 acpi_handle_einj(ACPI_TABLE_HEADER *sdp)
1370 {
1371 ACPI_TABLE_EINJ *einj;
1372 ACPI_EINJ_ENTRY *einj_entry;
1373 uint32_t einj_pos;
1374 u_int i;
1375
1376 printf(BEGIN_COMMENT);
1377 acpi_print_sdt(sdp);
1378 einj = (ACPI_TABLE_EINJ *)sdp;
1379
1380 printf("\tHeader Length=%d\n", einj->HeaderLength);
1381 printf("\tFlags=0x%x\n", einj->Flags);
1382 printf("\tEntries=%d\n", einj->Entries);
1383
1384 einj_pos = sizeof(ACPI_TABLE_EINJ);
1385 for (i = 0; i < einj->Entries; i++) {
1386 einj_entry = (ACPI_EINJ_ENTRY *)((char *)einj + einj_pos);
1387 acpi_print_whea(&einj_entry->WheaHeader,
1388 acpi_print_einj_action, acpi_print_einj_instruction,
1389 acpi_print_einj_flags);
1390 einj_pos += sizeof(ACPI_EINJ_ENTRY);
1391 }
1392 printf(END_COMMENT);
1393 }
1394
1395 static void
1396 acpi_print_erst_action(ACPI_WHEA_HEADER *whea)
1397 {
1398 printf("\tACTION={");
1399 switch (whea->Action) {
1400 case ACPI_ERST_BEGIN_WRITE:
1401 printf("Begin Write");
1402 break;
1403 case ACPI_ERST_BEGIN_READ:
1404 printf("Begin Read");
1405 break;
1406 case ACPI_ERST_BEGIN_CLEAR:
1407 printf("Begin Clear");
1408 break;
1409 case ACPI_ERST_END:
1410 printf("End");
1411 break;
1412 case ACPI_ERST_SET_RECORD_OFFSET:
1413 printf("Set Record Offset");
1414 break;
1415 case ACPI_ERST_EXECUTE_OPERATION:
1416 printf("Execute Operation");
1417 break;
1418 case ACPI_ERST_CHECK_BUSY_STATUS:
1419 printf("Check Busy Status");
1420 break;
1421 case ACPI_ERST_GET_COMMAND_STATUS:
1422 printf("Get Command Status");
1423 break;
1424 case ACPI_ERST_GET_RECORD_ID:
1425 printf("Get Record ID");
1426 break;
1427 case ACPI_ERST_SET_RECORD_ID:
1428 printf("Set Record ID");
1429 break;
1430 case ACPI_ERST_GET_RECORD_COUNT:
1431 printf("Get Record Count");
1432 break;
1433 case ACPI_ERST_BEGIN_DUMMY_WRIITE:
1434 printf("Begin Dummy Write");
1435 break;
1436 case ACPI_ERST_NOT_USED:
1437 printf("Unused");
1438 break;
1439 case ACPI_ERST_GET_ERROR_RANGE:
1440 printf("Get Error Range");
1441 break;
1442 case ACPI_ERST_GET_ERROR_LENGTH:
1443 printf("Get Error Length");
1444 break;
1445 case ACPI_ERST_GET_ERROR_ATTRIBUTES:
1446 printf("Get Error Attributes");
1447 break;
1448 case ACPI_ERST_EXECUTE_TIMINGS:
1449 printf("Execute Operation Timings");
1450 break;
1451 case ACPI_ERST_ACTION_RESERVED:
1452 printf("Reserved");
1453 break;
1454 default:
1455 printf("%d", whea->Action);
1456 break;
1457 }
1458 printf("}\n");
1459 }
1460
1461 static void
1462 acpi_print_erst_instruction(ACPI_WHEA_HEADER *whea)
1463 {
1464 printf("\tINSTRUCTION={");
1465 switch (whea->Instruction) {
1466 case ACPI_ERST_READ_REGISTER:
1467 printf("Read Register");
1468 break;
1469 case ACPI_ERST_READ_REGISTER_VALUE:
1470 printf("Read Register Value");
1471 break;
1472 case ACPI_ERST_WRITE_REGISTER:
1473 printf("Write Register");
1474 break;
1475 case ACPI_ERST_WRITE_REGISTER_VALUE:
1476 printf("Write Register Value");
1477 break;
1478 case ACPI_ERST_NOOP:
1479 printf("Noop");
1480 break;
1481 case ACPI_ERST_LOAD_VAR1:
1482 printf("Load Var1");
1483 break;
1484 case ACPI_ERST_LOAD_VAR2:
1485 printf("Load Var2");
1486 break;
1487 case ACPI_ERST_STORE_VAR1:
1488 printf("Store Var1");
1489 break;
1490 case ACPI_ERST_ADD:
1491 printf("Add");
1492 break;
1493 case ACPI_ERST_SUBTRACT:
1494 printf("Subtract");
1495 break;
1496 case ACPI_ERST_ADD_VALUE:
1497 printf("Add Value");
1498 break;
1499 case ACPI_ERST_SUBTRACT_VALUE:
1500 printf("Subtract Value");
1501 break;
1502 case ACPI_ERST_STALL:
1503 printf("Stall");
1504 break;
1505 case ACPI_ERST_STALL_WHILE_TRUE:
1506 printf("Stall While True");
1507 break;
1508 case ACPI_ERST_SKIP_NEXT_IF_TRUE:
1509 printf("Skip Next If True");
1510 break;
1511 case ACPI_ERST_GOTO:
1512 printf("Goto");
1513 break;
1514 case ACPI_ERST_SET_SRC_ADDRESS_BASE:
1515 printf("Set Src Address Base");
1516 break;
1517 case ACPI_ERST_SET_DST_ADDRESS_BASE:
1518 printf("Set Dst Address Base");
1519 break;
1520 case ACPI_ERST_MOVE_DATA:
1521 printf("Move Data");
1522 break;
1523 case ACPI_ERST_INSTRUCTION_RESERVED:
1524 printf("Reserved");
1525 break;
1526 default:
1527 printf("%d (reserved)", whea->Instruction);
1528 break;
1529 }
1530 printf("}\n");
1531 }
1532
1533 static void
1534 acpi_print_erst_flags(ACPI_WHEA_HEADER *whea)
1535 {
1536 uint32_t flags = whea->Flags;
1537
1538 printf("\tFLAGS={ ");
1539 if (flags & ACPI_ERST_PRESERVE)
1540 printf("PRESERVED");
1541 printf("}\n");
1542 }
1543
1544 static void
1545 acpi_handle_erst(ACPI_TABLE_HEADER *sdp)
1546 {
1547 ACPI_TABLE_ERST *erst;
1548 ACPI_ERST_ENTRY *erst_entry;
1549 uint32_t erst_pos;
1550 u_int i;
1551
1552 printf(BEGIN_COMMENT);
1553 acpi_print_sdt(sdp);
1554 erst = (ACPI_TABLE_ERST *)sdp;
1555
1556 printf("\tHeader Length=%d\n", erst->HeaderLength);
1557 printf("\tEntries=%d\n", erst->Entries);
1558
1559 erst_pos = sizeof(ACPI_TABLE_ERST);
1560 for (i = 0; i < erst->Entries; i++) {
1561 erst_entry = (ACPI_ERST_ENTRY *)((char *)erst + erst_pos);
1562 acpi_print_whea(&erst_entry->WheaHeader,
1563 acpi_print_erst_action, acpi_print_erst_instruction,
1564 acpi_print_erst_flags);
1565 erst_pos += sizeof(ACPI_ERST_ENTRY);
1566 }
1567 printf(END_COMMENT);
1568 }
1569
1570 static void
1571 acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
1572 {
1573 ACPI_TABLE_MADT *madt;
1574
1575 printf(BEGIN_COMMENT);
1576 acpi_print_sdt(sdp);
1577 madt = (ACPI_TABLE_MADT *)sdp;
1578 printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
1579 printf("\tFlags={");
1580 if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
1581 printf("PC-AT");
1582 printf("}\n");
1583 acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
1584 printf(END_COMMENT);
1585 }
1586
1587 static void
1588 acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
1589 {
1590 ACPI_TABLE_HPET *hpet;
1591
1592 printf(BEGIN_COMMENT);
1593 acpi_print_sdt(sdp);
1594 hpet = (ACPI_TABLE_HPET *)sdp;
1595 printf("\tHPET Number=%d\n", hpet->Sequence);
1596 printf("\tADDR=");
1597 acpi_print_gas(&hpet->Address);
1598 printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
1599 printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
1600 8);
1601 printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
1602 1 : 0);
1603 printf("\tLegacy IRQ routing capable={");
1604 if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
1605 printf("TRUE}\n");
1606 else
1607 printf("FALSE}\n");
1608 printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
1609 printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
1610 printf("\tFlags=0x%02x\n", hpet->Flags);
1611 printf(END_COMMENT);
1612 }
1613
1614 static void
1615 acpi_handle_msct(ACPI_TABLE_HEADER *sdp)
1616 {
1617 ACPI_TABLE_MSCT *msct;
1618 ACPI_MSCT_PROXIMITY *msctentry;
1619 uint32_t pos;
1620
1621 printf(BEGIN_COMMENT);
1622 acpi_print_sdt(sdp);
1623 msct = (ACPI_TABLE_MSCT *)sdp;
1624
1625 printf("\tProximity Offset=0x%x\n", msct->ProximityOffset);
1626 printf("\tMax Proximity Domains=%d\n", msct->MaxProximityDomains);
1627 printf("\tMax Clock Domains=%d\n", msct->MaxClockDomains);
1628 printf("\tMax Physical Address=0x%"PRIx64"\n", msct->MaxAddress);
1629
1630 pos = msct->ProximityOffset;
1631 while (pos < msct->Header.Length) {
1632 msctentry = (ACPI_MSCT_PROXIMITY *)((char *)msct + pos);
1633 pos += msctentry->Length;
1634
1635 printf("\n");
1636 printf("\tRevision=%d\n", msctentry->Revision);
1637 printf("\tLength=%d\n", msctentry->Length);
1638 printf("\tRange Start=%d\n", msctentry->RangeStart);
1639 printf("\tRange End=%d\n", msctentry->RangeEnd);
1640 printf("\tProcessor Capacity=%d\n",
1641 msctentry->ProcessorCapacity);
1642 printf("\tMemory Capacity=0x%"PRIx64" byte\n",
1643 msctentry->MemoryCapacity);
1644 }
1645
1646 printf(END_COMMENT);
1647 }
1648
1649 static void
1650 acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
1651 {
1652 ACPI_TABLE_ECDT *ecdt;
1653
1654 printf(BEGIN_COMMENT);
1655 acpi_print_sdt(sdp);
1656 ecdt = (ACPI_TABLE_ECDT *)sdp;
1657 printf("\tEC_CONTROL=");
1658 acpi_print_gas(&ecdt->Control);
1659 printf("\n\tEC_DATA=");
1660 acpi_print_gas(&ecdt->Data);
1661 printf("\n\tUID=%#x, ", ecdt->Uid);
1662 printf("GPE_BIT=%#x\n", ecdt->Gpe);
1663 printf("\tEC_ID=%s\n", ecdt->Id);
1664 printf(END_COMMENT);
1665 }
1666
1667 static void
1668 acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
1669 {
1670 ACPI_TABLE_MCFG *mcfg;
1671 ACPI_MCFG_ALLOCATION *alloc;
1672 u_int i, entries;
1673
1674 printf(BEGIN_COMMENT);
1675 acpi_print_sdt(sdp);
1676 mcfg = (ACPI_TABLE_MCFG *)sdp;
1677 entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
1678 sizeof(ACPI_MCFG_ALLOCATION);
1679 alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
1680 for (i = 0; i < entries; i++, alloc++) {
1681 printf("\n");
1682 printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
1683 printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
1684 printf("\tStart Bus=%d\n", alloc->StartBusNumber);
1685 printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
1686 }
1687 printf(END_COMMENT);
1688 }
1689
1690 static void
1691 acpi_handle_sbst(ACPI_TABLE_HEADER *sdp)
1692 {
1693 ACPI_TABLE_SBST *sbst;
1694
1695 printf(BEGIN_COMMENT);
1696 acpi_print_sdt(sdp);
1697 sbst = (ACPI_TABLE_SBST *)sdp;
1698
1699 printf("\tWarning Level=%d mWh\n", sbst->WarningLevel);
1700 printf("\tLow Level=%d mWh\n", sbst->LowLevel);
1701 printf("\tCritical Level=%d mWh\n", sbst->CriticalLevel);
1702
1703 printf(END_COMMENT);
1704 }
1705
1706 static void
1707 acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
1708 {
1709 ACPI_TABLE_SLIT *slit;
1710 u_int idx;
1711 uint64_t cnt;
1712
1713 printf(BEGIN_COMMENT);
1714 acpi_print_sdt(sdp);
1715 slit = (ACPI_TABLE_SLIT *)sdp;
1716
1717 cnt = slit->LocalityCount * slit->LocalityCount;
1718 printf("\tLocalityCount=%ju\n", (uintmax_t)slit->LocalityCount);
1719 printf("\tEntry=\n\t");
1720 for (idx = 0; idx < cnt; idx++) {
1721 printf("%u ", slit->Entry[idx]);
1722 if ((idx % slit->LocalityCount) == (slit->LocalityCount - 1)) {
1723 printf("\n");
1724 if (idx < cnt - 1)
1725 printf("\t");
1726 }
1727 }
1728
1729 printf(END_COMMENT);
1730 }
1731
1732 static void
1733 acpi_handle_spcr(ACPI_TABLE_HEADER *sdp)
1734 {
1735 ACPI_TABLE_SPCR *spcr;
1736
1737 printf(BEGIN_COMMENT);
1738 acpi_print_sdt(sdp);
1739 spcr = (ACPI_TABLE_SPCR *)sdp;
1740
1741 printf("\tSerial Port=");
1742 acpi_print_gas(&spcr->SerialPort);
1743 printf("\n\tInterrupt Type={");
1744 if (spcr->InterruptType & 0x1) {
1745 printf("\n\t\tdual-8259 IRQ=");
1746 switch (spcr->PcInterrupt) {
1747 case 2 ... 7:
1748 case 9 ... 12:
1749 case 14 ... 15:
1750 printf("%d", spcr->PcInterrupt);
1751 break;
1752 default:
1753 printf("%d (invalid entry)", spcr->PcInterrupt);
1754 break;
1755 }
1756 }
1757 if (spcr->InterruptType & 0x2) {
1758 printf("\n\t\tIO APIC={ GSI=%d }", spcr->Interrupt);
1759 }
1760 if (spcr->InterruptType & 0x4) {
1761 printf("\n\t\tIO SAPIC={ GSI=%d }", spcr->Interrupt);
1762 }
1763 printf("\n\t}\n");
1764
1765 printf("\tBaud Rate=");
1766 switch (spcr->BaudRate) {
1767 case 3:
1768 printf("9600");
1769 break;
1770 case 4:
1771 printf("19200");
1772 break;
1773 case 6:
1774 printf("57600");
1775 break;
1776 case 7:
1777 printf("115200");
1778 break;
1779 default:
1780 printf("unknown speed index %d", spcr->BaudRate);
1781 break;
1782 }
1783 printf("\n\tParity={");
1784 switch (spcr->Parity) {
1785 case 0:
1786 printf("OFF");
1787 break;
1788 default:
1789 printf("ON");
1790 break;
1791 }
1792 printf("}\n");
1793
1794 printf("\tStop Bits={");
1795 switch (spcr->StopBits) {
1796 case 1:
1797 printf("ON");
1798 break;
1799 default:
1800 printf("OFF");
1801 break;
1802 }
1803 printf("}\n");
1804
1805 printf("\tFlow Control={");
1806 if (spcr->FlowControl & 0x1)
1807 printf("DCD, ");
1808 if (spcr->FlowControl & 0x2)
1809 printf("RTS/CTS hardware, ");
1810 if (spcr->FlowControl & 0x4)
1811 printf("XON/XOFF software");
1812 printf("}\n");
1813
1814 printf("\tTerminal=");
1815 switch (spcr->TerminalType) {
1816 case 0:
1817 printf("VT100");
1818 break;
1819 case 1:
1820 printf("VT100+");
1821 break;
1822 case 2:
1823 printf("VT-UTF8");
1824 break;
1825 case 3:
1826 printf("ANSI");
1827 break;
1828 default:
1829 printf("unknown type %d", spcr->TerminalType);
1830 break;
1831 }
1832 printf("\n");
1833
1834 acpi_print_pci(spcr->PciVendorId, spcr->PciDeviceId,
1835 spcr->PciSegment, spcr->PciBus, spcr->PciDevice, spcr->PciFunction);
1836
1837 printf("\tPCI Flags={");
1838 if (spcr->PciFlags & ACPI_SPCR_DO_NOT_DISABLE)
1839 printf("DONOT_DISABLE");
1840 printf("}\n");
1841
1842 printf(END_COMMENT);
1843 }
1844
1845 static void
1846 acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
1847 uint32_t flags, uint32_t clockdomain)
1848 {
1849
1850 printf("\tFlags={");
1851 if (flags & ACPI_SRAT_CPU_ENABLED)
1852 printf("ENABLED");
1853 else
1854 printf("DISABLED");
1855 printf("}\n");
1856 printf("\tAPIC ID=%d\n", apic_id);
1857 printf("\tProximity Domain=%d\n", proximity_domain);
1858 printf("\tClock Domain=%d\n", clockdomain);
1859 }
1860
1861 static void
1862 acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1863 {
1864
1865 printf("\tFlags={");
1866 if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1867 printf("ENABLED");
1868 else
1869 printf("DISABLED");
1870 if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1871 printf(",HOT_PLUGGABLE");
1872 if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1873 printf(",NON_VOLATILE");
1874 printf("}\n");
1875 printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1876 printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1877 printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1878 }
1879
1880 static const char *srat_types[] = {
1881 [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
1882 [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
1883 [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
1884 [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
1885 };
1886
1887 static void
1888 acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1889 {
1890 ACPI_SRAT_CPU_AFFINITY *cpu;
1891 ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
1892 ACPI_SRAT_GICC_AFFINITY *gic;
1893
1894 if (srat->Type < __arraycount(srat_types))
1895 printf("\tType=%s\n", srat_types[srat->Type]);
1896 else
1897 printf("\tType=%d (unknown)\n", srat->Type);
1898 switch (srat->Type) {
1899 case ACPI_SRAT_TYPE_CPU_AFFINITY:
1900 cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1901 acpi_print_srat_cpu(cpu->ApicId,
1902 cpu->ProximityDomainHi[2] << 24 |
1903 cpu->ProximityDomainHi[1] << 16 |
1904 cpu->ProximityDomainHi[0] << 0 |
1905 cpu->ProximityDomainLo,
1906 cpu->Flags, cpu->ClockDomain);
1907 break;
1908 case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1909 acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1910 break;
1911 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1912 x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1913 acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1914 x2apic->Flags, x2apic->ClockDomain);
1915 break;
1916 case ACPI_SRAT_TYPE_GICC_AFFINITY:
1917 gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
1918 acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
1919 gic->Flags, gic->ClockDomain);
1920 break;
1921 }
1922 }
1923
1924 static void
1925 acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1926 {
1927 ACPI_TABLE_SRAT *srat;
1928
1929 printf(BEGIN_COMMENT);
1930 acpi_print_sdt(sdp);
1931 srat = (ACPI_TABLE_SRAT *)sdp;
1932 printf("\tTable Revision=%d\n", srat->TableRevision);
1933 acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1934 printf(END_COMMENT);
1935 }
1936
1937 static const char *nfit_types[] = {
1938 [ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
1939 [ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
1940 [ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
1941 [ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
1942 [ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
1943 [ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
1944 [ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address"
1945 };
1946
1947
1948 static void
1949 acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
1950 {
1951 char *uuidstr;
1952 uint32_t status;
1953
1954 ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
1955 ACPI_NFIT_MEMORY_MAP *mmap;
1956 ACPI_NFIT_INTERLEAVE *ileave;
1957 ACPI_NFIT_SMBIOS *smbios __unused;
1958 ACPI_NFIT_CONTROL_REGION *ctlreg;
1959 ACPI_NFIT_DATA_REGION *datareg;
1960 ACPI_NFIT_FLUSH_ADDRESS *fladdr;
1961
1962 if (nfit->Type < __arraycount(nfit_types))
1963 printf("\tType=%s\n", nfit_types[nfit->Type]);
1964 else
1965 printf("\tType=%u (unknown)\n", nfit->Type);
1966 switch (nfit->Type) {
1967 case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
1968 sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
1969 printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
1970 printf("\tProximityDomain=%u\n",
1971 (u_int)sysaddr->ProximityDomain);
1972 uuid_to_string((uuid_t *)(sysaddr->RangeGuid),
1973 &uuidstr, &status);
1974 if (status != uuid_s_ok)
1975 errx(1, "uuid_to_string: status=%u", status);
1976 printf("\tRangeGuid=%s\n", uuidstr);
1977 free(uuidstr);
1978 printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
1979 printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
1980 printf("\tMemoryMapping=0x%016jx\n",
1981 (uintmax_t)sysaddr->MemoryMapping);
1982
1983 #define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_## flag, #flag)
1984
1985 printf("\tFlags=");
1986 PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
1987 PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
1988 PRINTFLAG_END();
1989
1990 #undef PRINTFLAG
1991
1992 break;
1993 case ACPI_NFIT_TYPE_MEMORY_MAP:
1994 mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
1995 printf("\tDeviceHandle=%u\n", (u_int)mmap->DeviceHandle);
1996 printf("\tPhysicalId=%u\n", (u_int)mmap->PhysicalId);
1997 printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
1998 printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
1999 printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
2000 printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
2001 printf("\tRegionOffset=0x%016jx\n",
2002 (uintmax_t)mmap->RegionOffset);
2003 printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
2004 printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
2005 printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
2006
2007 #define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_MEM_## flag, #flag)
2008
2009 printf("\tFlags=");
2010 PRINTFLAG(mmap->Flags, SAVE_FAILED);
2011 PRINTFLAG(mmap->Flags, RESTORE_FAILED);
2012 PRINTFLAG(mmap->Flags, FLUSH_FAILED);
2013 PRINTFLAG(mmap->Flags, NOT_ARMED);
2014 PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
2015 PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
2016 PRINTFLAG(mmap->Flags, MAP_FAILED);
2017 PRINTFLAG_END();
2018
2019 #undef PRINTFLAG
2020
2021 break;
2022 case ACPI_NFIT_TYPE_INTERLEAVE:
2023 ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
2024 printf("\tInterleaveIndex=%u\n",
2025 (u_int)ileave->InterleaveIndex);
2026 printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
2027 printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
2028 /* XXX ileave->LineOffset[i] output is not supported */
2029 break;
2030 case ACPI_NFIT_TYPE_SMBIOS:
2031 smbios = (ACPI_NFIT_SMBIOS *)nfit;
2032 /* XXX smbios->Data[x] output is not supported */
2033 break;
2034 case ACPI_NFIT_TYPE_CONTROL_REGION:
2035 ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
2036 printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
2037 printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
2038 printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
2039 printf("\tRevisionId=%u\n", (u_int)ctlreg->RevisionId);
2040 printf("\tSubsystemVendorId=0x%04x\n",
2041 (u_int)ctlreg->SubsystemVendorId);
2042 printf("\tSubsystemDeviceId=0x%04x\n",
2043 (u_int)ctlreg->SubsystemDeviceId);
2044 printf("\tSubsystemRevisionId=%u\n",
2045 (u_int)ctlreg->SubsystemRevisionId);
2046 printf("\tValidFields=%u\n", (u_int)ctlreg->ValidFields);
2047 printf("\tManufacturingLocation=%u\n",
2048 (u_int)ctlreg->ManufacturingLocation);
2049 printf("\tManufacturingDate=%u\n",
2050 (u_int)ctlreg->ManufacturingDate);
2051 printf("\tSerialNumber=%u\n",
2052 (u_int)ctlreg->SerialNumber);
2053 printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
2054 printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
2055 printf("\tWindowSize=0x%016jx\n",
2056 (uintmax_t)ctlreg->WindowSize);
2057 printf("\tCommandOffset=0x%016jx\n",
2058 (uintmax_t)ctlreg->CommandOffset);
2059 printf("\tCommandSize=0x%016jx\n",
2060 (uintmax_t)ctlreg->CommandSize);
2061 printf("\tStatusOffset=0x%016jx\n",
2062 (uintmax_t)ctlreg->StatusOffset);
2063 printf("\tStatusSize=0x%016jx\n",
2064 (uintmax_t)ctlreg->StatusSize);
2065
2066 #define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_## flag, #flag)
2067
2068 printf("\tFlags=");
2069 PRINTFLAG(ctlreg->Flags, ADD_ONLINE_ONLY);
2070 PRINTFLAG(ctlreg->Flags, PROXIMITY_VALID);
2071 PRINTFLAG_END();
2072
2073 #undef PRINTFLAG
2074
2075 break;
2076 case ACPI_NFIT_TYPE_DATA_REGION:
2077 datareg = (ACPI_NFIT_DATA_REGION *)nfit;
2078 printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
2079 printf("\tWindows=%u\n", (u_int)datareg->Windows);
2080 printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
2081 printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
2082 printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
2083 printf("\tStartAddress=0x%016jx\n",
2084 (uintmax_t)datareg->StartAddress);
2085 break;
2086 case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
2087 fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
2088 printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
2089 printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
2090 /* XXX fladdr->HintAddress[i] output is not supported */
2091 break;
2092 }
2093 }
2094
2095 static void
2096 acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
2097 {
2098 ACPI_TABLE_NFIT *nfit;
2099
2100 printf(BEGIN_COMMENT);
2101 acpi_print_sdt(sdp);
2102 nfit = (ACPI_TABLE_NFIT *)sdp;
2103 acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
2104 printf(END_COMMENT);
2105 }
2106
2107 static char *
2108 acpi_tcpa_evname(struct TCPAevent *event)
2109 {
2110 struct TCPApc_event *pc_event;
2111 char *eventname = NULL;
2112
2113 pc_event = (struct TCPApc_event *)(event + 1);
2114
2115 switch(event->event_type) {
2116 case PREBOOT:
2117 case POST_CODE:
2118 case UNUSED:
2119 case NO_ACTION:
2120 case SEPARATOR:
2121 case SCRTM_CONTENTS:
2122 case SCRTM_VERSION:
2123 case CPU_MICROCODE:
2124 case PLATFORM_CONFIG_FLAGS:
2125 case TABLE_OF_DEVICES:
2126 case COMPACT_HASH:
2127 case IPL:
2128 case IPL_PARTITION_DATA:
2129 case NONHOST_CODE:
2130 case NONHOST_CONFIG:
2131 case NONHOST_INFO:
2132 asprintf(&eventname, "%s",
2133 tcpa_event_type_strings[event->event_type]);
2134 break;
2135
2136 case ACTION:
2137 eventname = calloc(event->event_size + 1, sizeof(char));
2138 memcpy(eventname, pc_event, event->event_size);
2139 break;
2140
2141 case EVENT_TAG:
2142 switch (pc_event->event_id) {
2143 case SMBIOS:
2144 case BIS_CERT:
2145 case CMOS:
2146 case NVRAM:
2147 case OPTION_ROM_EXEC:
2148 case OPTION_ROM_CONFIG:
2149 case S_CRTM_VERSION:
2150 case POST_BIOS_ROM:
2151 case ESCD:
2152 case OPTION_ROM_MICROCODE:
2153 case S_CRTM_CONTENTS:
2154 case POST_CONTENTS:
2155 asprintf(&eventname, "%s",
2156 TCPA_pcclient_strings[pc_event->event_id]);
2157 break;
2158
2159 default:
2160 asprintf(&eventname, "<unknown tag 0x%02x>",
2161 pc_event->event_id);
2162 break;
2163 }
2164 break;
2165
2166 default:
2167 asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
2168 break;
2169 }
2170
2171 return eventname;
2172 }
2173
2174 static void
2175 acpi_print_tcpa(struct TCPAevent *event)
2176 {
2177 int i;
2178 char *eventname;
2179
2180 eventname = acpi_tcpa_evname(event);
2181
2182 printf("\t%d", event->pcr_index);
2183 printf(" 0x");
2184 for (i = 0; i < 20; i++)
2185 printf("%02x", event->pcr_value[i]);
2186 printf(" [%s]\n", eventname ? eventname : "<unknown>");
2187
2188 free(eventname);
2189 }
2190
2191 static void
2192 acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
2193 {
2194 struct TCPAbody *tcpa;
2195 struct TCPAevent *event;
2196 uintmax_t len, paddr;
2197 unsigned char *vaddr = NULL;
2198 unsigned char *vend = NULL;
2199
2200 printf(BEGIN_COMMENT);
2201 acpi_print_sdt(sdp);
2202 tcpa = (struct TCPAbody *) sdp;
2203
2204 switch (tcpa->platform_class) {
2205 case ACPI_TCPA_BIOS_CLIENT:
2206 len = tcpa->client.log_max_len;
2207 paddr = tcpa->client.log_start_addr;
2208 break;
2209
2210 case ACPI_TCPA_BIOS_SERVER:
2211 len = tcpa->server.log_max_len;
2212 paddr = tcpa->server.log_start_addr;
2213 break;
2214
2215 default:
2216 printf("XXX");
2217 printf(END_COMMENT);
2218 return;
2219 }
2220 printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
2221 tcpa->platform_class, paddr, len);
2222
2223 if (len == 0) {
2224 printf("\tEmpty TCPA table\n");
2225 printf(END_COMMENT);
2226 return;
2227 }
2228 if(sdp->Revision == 1) {
2229 printf("\tOLD TCPA spec log found. Dumping not supported.\n");
2230 printf(END_COMMENT);
2231 return;
2232 }
2233
2234 vaddr = (unsigned char *)acpi_map_physical(paddr, len);
2235 vend = vaddr + len;
2236
2237 while (vaddr != NULL) {
2238 if ((vaddr + sizeof(struct TCPAevent) >= vend)||
2239 (vaddr + sizeof(struct TCPAevent) < vaddr))
2240 break;
2241 event = (struct TCPAevent *)(void *)vaddr;
2242 if (vaddr + event->event_size >= vend)
2243 break;
2244 if (vaddr + event->event_size < vaddr)
2245 break;
2246 if (event->event_type == 0 && event->event_size == 0)
2247 break;
2248 #if 0
2249 {
2250 unsigned int i, j, k;
2251
2252 printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
2253 for (j = 0, i = 0; i <
2254 sizeof(struct TCPAevent) + event->event_size; i++) {
2255 printf("%02x ", vaddr[i]);
2256 if ((i+1) % 8 == 0) {
2257 for (k = 0; k < 8; k++)
2258 printf("%c", isprint(vaddr[j+k]) ?
2259 vaddr[j+k] : '.');
2260 printf("\n\t\t%p ", &vaddr[i + 1]);
2261 j = i + 1;
2262 }
2263 }
2264 printf("\n"); }
2265 #endif
2266 acpi_print_tcpa(event);
2267
2268 vaddr += sizeof(struct TCPAevent) + event->event_size;
2269 }
2270
2271 printf(END_COMMENT);
2272 }
2273
2274 static const char *
2275 devscope_type2str(int type)
2276 {
2277 static char typebuf[16];
2278
2279 switch (type) {
2280 case 1:
2281 return ("PCI Endpoint Device");
2282 case 2:
2283 return ("PCI Sub-Hierarchy");
2284 case 3:
2285 return ("IOAPIC");
2286 case 4:
2287 return ("HPET");
2288 default:
2289 snprintf(typebuf, sizeof(typebuf), "%d", type);
2290 return (typebuf);
2291 }
2292 }
2293
2294 static int
2295 acpi_handle_dmar_devscope(void *addr, int remaining)
2296 {
2297 char sep;
2298 int pathlen;
2299 ACPI_DMAR_PCI_PATH *path, *pathend;
2300 ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
2301
2302 if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
2303 return (-1);
2304
2305 if (remaining < devscope->Length)
2306 return (-1);
2307
2308 printf("\n");
2309 printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
2310 printf("\t\tLength=%d\n", devscope->Length);
2311 printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
2312 printf("\t\tStartBusNumber=%d\n", devscope->Bus);
2313
2314 path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
2315 pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
2316 pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
2317 if (path < pathend) {
2318 sep = '{';
2319 printf("\t\tPath=");
2320 do {
2321 printf("%c%d:%d", sep, path->Device, path->Function);
2322 sep=',';
2323 path++;
2324 } while (path < pathend);
2325 printf("}\n");
2326 }
2327
2328 return (devscope->Length);
2329 }
2330
2331 static void
2332 acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
2333 {
2334 char *cp;
2335 int remaining, consumed;
2336
2337 printf("\n");
2338 printf("\tType=DRHD\n");
2339 printf("\tLength=%d\n", drhd->Header.Length);
2340
2341 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
2342
2343 printf("\tFlags=");
2344 PRINTFLAG(drhd->Flags, INCLUDE_ALL);
2345 PRINTFLAG_END();
2346
2347 #undef PRINTFLAG
2348
2349 printf("\tSegment=%d\n", drhd->Segment);
2350 printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
2351
2352 remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
2353 if (remaining > 0)
2354 printf("\tDevice Scope:");
2355 while (remaining > 0) {
2356 cp = (char *)drhd + drhd->Header.Length - remaining;
2357 consumed = acpi_handle_dmar_devscope(cp, remaining);
2358 if (consumed <= 0)
2359 break;
2360 else
2361 remaining -= consumed;
2362 }
2363 }
2364
2365 static void
2366 acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
2367 {
2368 char *cp;
2369 int remaining, consumed;
2370
2371 printf("\n");
2372 printf("\tType=RMRR\n");
2373 printf("\tLength=%d\n", rmrr->Header.Length);
2374 printf("\tSegment=%d\n", rmrr->Segment);
2375 printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
2376 printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
2377
2378 remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
2379 if (remaining > 0)
2380 printf("\tDevice Scope:");
2381 while (remaining > 0) {
2382 cp = (char *)rmrr + rmrr->Header.Length - remaining;
2383 consumed = acpi_handle_dmar_devscope(cp, remaining);
2384 if (consumed <= 0)
2385 break;
2386 else
2387 remaining -= consumed;
2388 }
2389 }
2390
2391 static void
2392 acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
2393 {
2394 char *cp;
2395 int remaining, consumed;
2396
2397 printf("\n");
2398 printf("\tType=ATSR\n");
2399 printf("\tLength=%d\n", atsr->Header.Length);
2400
2401 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
2402
2403 printf("\tFlags=");
2404 PRINTFLAG(atsr->Flags, ALL_PORTS);
2405 PRINTFLAG_END();
2406
2407 #undef PRINTFLAG
2408
2409 printf("\tSegment=%d\n", atsr->Segment);
2410
2411 remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
2412 if (remaining > 0)
2413 printf("\tDevice Scope:");
2414 while (remaining > 0) {
2415 cp = (char *)atsr + atsr->Header.Length - remaining;
2416 consumed = acpi_handle_dmar_devscope(cp, remaining);
2417 if (consumed <= 0)
2418 break;
2419 else
2420 remaining -= consumed;
2421 }
2422 }
2423
2424 static void
2425 acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
2426 {
2427
2428 printf("\n");
2429 printf("\tType=RHSA\n");
2430 printf("\tLength=%d\n", rhsa->Header.Length);
2431 printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
2432 printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
2433 }
2434
2435 static int
2436 acpi_handle_dmar_remapping_structure(void *addr, int remaining)
2437 {
2438 ACPI_DMAR_HEADER *hdr = addr;
2439
2440 if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
2441 return (-1);
2442
2443 if (remaining < hdr->Length)
2444 return (-1);
2445
2446 switch (hdr->Type) {
2447 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
2448 acpi_handle_dmar_drhd(addr);
2449 break;
2450 case ACPI_DMAR_TYPE_RESERVED_MEMORY:
2451 acpi_handle_dmar_rmrr(addr);
2452 break;
2453 case ACPI_DMAR_TYPE_ROOT_ATS:
2454 acpi_handle_dmar_atsr(addr);
2455 break;
2456 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
2457 acpi_handle_dmar_rhsa(addr);
2458 break;
2459 default:
2460 printf("\n");
2461 printf("\tType=%d\n", hdr->Type);
2462 printf("\tLength=%d\n", hdr->Length);
2463 break;
2464 }
2465 return (hdr->Length);
2466 }
2467
2468 #ifndef ACPI_DMAR_X2APIC_OPT_OUT
2469 #define ACPI_DMAR_X2APIC_OPT_OUT (0x2)
2470 #endif
2471
2472 static void
2473 acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
2474 {
2475 char *cp;
2476 int remaining, consumed;
2477 ACPI_TABLE_DMAR *dmar;
2478
2479 printf(BEGIN_COMMENT);
2480 acpi_print_sdt(sdp);
2481 dmar = (ACPI_TABLE_DMAR *)sdp;
2482 printf("\tHost Address Width=%d\n", dmar->Width + 1);
2483
2484 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
2485
2486 printf("\tFlags=");
2487 PRINTFLAG(dmar->Flags, INTR_REMAP);
2488 PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
2489 PRINTFLAG_END();
2490
2491 #undef PRINTFLAG
2492
2493 remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
2494 while (remaining > 0) {
2495 cp = (char *)sdp + sdp->Length - remaining;
2496 consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
2497 if (consumed <= 0)
2498 break;
2499 else
2500 remaining -= consumed;
2501 }
2502
2503 printf(END_COMMENT);
2504 }
2505
2506 static void
2507 acpi_handle_waet(ACPI_TABLE_HEADER *sdp)
2508 {
2509 ACPI_TABLE_WAET *waet;
2510
2511 printf(BEGIN_COMMENT);
2512 acpi_print_sdt(sdp);
2513 waet = (ACPI_TABLE_WAET *)sdp;
2514
2515 printf("\tRTC Timer={");
2516 if (waet->Flags & ACPI_WAET_RTC_NO_ACK)
2517 printf("No ACK required");
2518 else
2519 printf("default behaviour");
2520 printf("}\n");
2521 printf("\t ACPI PM Timer={");
2522 if (waet->Flags & ACPI_WAET_TIMER_ONE_READ)
2523 printf("One Read sufficient");
2524 else
2525 printf("default behaviour");
2526 printf("}\n");
2527
2528 printf(END_COMMENT);
2529 }
2530
2531 static void
2532 acpi_print_wdat_action(ACPI_WHEA_HEADER *whea)
2533 {
2534 printf("\tACTION={");
2535 switch (whea->Action) {
2536 case ACPI_WDAT_RESET:
2537 printf("RESET");
2538 break;
2539 case ACPI_WDAT_GET_CURRENT_COUNTDOWN:
2540 printf("GET_CURRENT_COUNTDOWN");
2541 break;
2542 case ACPI_WDAT_GET_COUNTDOWN:
2543 printf("GET_COUNTDOWN");
2544 break;
2545 case ACPI_WDAT_SET_COUNTDOWN:
2546 printf("SET_COUNTDOWN");
2547 break;
2548 case ACPI_WDAT_GET_RUNNING_STATE:
2549 printf("GET_RUNNING_STATE");
2550 break;
2551 case ACPI_WDAT_SET_RUNNING_STATE:
2552 printf("SET_RUNNING_STATE");
2553 break;
2554 case ACPI_WDAT_GET_STOPPED_STATE:
2555 printf("GET_STOPPED_STATE");
2556 break;
2557 case ACPI_WDAT_SET_STOPPED_STATE:
2558 printf("SET_STOPPED_STATE");
2559 break;
2560 case ACPI_WDAT_GET_REBOOT:
2561 printf("GET_REBOOT");
2562 break;
2563 case ACPI_WDAT_SET_REBOOT:
2564 printf("SET_REBOOT");
2565 break;
2566 case ACPI_WDAT_GET_SHUTDOWN:
2567 printf("GET_SHUTDOWN");
2568 break;
2569 case ACPI_WDAT_SET_SHUTDOWN:
2570 printf("SET_SHUTDOWN");
2571 break;
2572 case ACPI_WDAT_GET_STATUS:
2573 printf("GET_STATUS");
2574 break;
2575 case ACPI_WDAT_SET_STATUS:
2576 printf("SET_STATUS");
2577 break;
2578 case ACPI_WDAT_ACTION_RESERVED:
2579 printf("ACTION_RESERVED");
2580 break;
2581 default:
2582 printf("%d", whea->Action);
2583 break;
2584 }
2585 printf("}\n");
2586 }
2587
2588 static void
2589 acpi_print_wdat_instruction(ACPI_WHEA_HEADER *whea)
2590 {
2591 uint32_t ins;
2592
2593 ins = whea->Instruction & ~ACPI_WDAT_PRESERVE_REGISTER;
2594
2595 printf("\tINSTRUCTION={");
2596 switch (ins) {
2597 case ACPI_WDAT_READ_VALUE:
2598 printf("READ_VALUE");
2599 break;
2600 case ACPI_WDAT_READ_COUNTDOWN:
2601 printf("READ_COUNTDOWN");
2602 break;
2603 case ACPI_WDAT_WRITE_VALUE:
2604 printf("WRITE_VALUE");
2605 break;
2606 case ACPI_WDAT_WRITE_COUNTDOWN:
2607 printf("WRITE_COUNTDOWN");
2608 break;
2609 case ACPI_WDAT_INSTRUCTION_RESERVED:
2610 printf("INSTRUCTION_RESERVED");
2611 break;
2612 default:
2613 printf("%d", ins);
2614 break;
2615 }
2616
2617 if (whea->Instruction & ACPI_WDAT_PRESERVE_REGISTER)
2618 printf(", Preserve Register ");
2619
2620 printf("}\n");
2621 }
2622
2623 static void
2624 acpi_handle_wdat(ACPI_TABLE_HEADER *sdp)
2625 {
2626 ACPI_TABLE_WDAT *wdat;
2627 ACPI_WHEA_HEADER *whea;
2628 char *wdat_pos;
2629 u_int i;
2630
2631 printf(BEGIN_COMMENT);
2632 acpi_print_sdt(sdp);
2633 wdat = (ACPI_TABLE_WDAT *)sdp;
2634
2635 printf("\tHeader Length=%d\n", wdat->HeaderLength);
2636
2637 acpi_print_pci_sbfd(wdat->PciSegment, wdat->PciBus, wdat->PciDevice,
2638 wdat->PciFunction);
2639 printf("\n\tTimer Counter Period=%d msec\n", wdat->TimerPeriod);
2640 printf("\tTimer Maximum Counter Value=%d\n", wdat->MaxCount);
2641 printf("\tTimer Minimum Counter Value=%d\n", wdat->MinCount);
2642
2643 printf("\tFlags={");
2644 if (wdat->Flags & ACPI_WDAT_ENABLED)
2645 printf("ENABLED");
2646 if (wdat->Flags & ACPI_WDAT_STOPPED)
2647 printf(", STOPPED");
2648 printf("}\n");
2649
2650 wdat_pos = ((char *)wdat + sizeof(ACPI_TABLE_HEADER)
2651 + wdat->HeaderLength);
2652
2653 for (i = 0; i < wdat->Entries; i++) {
2654 whea = (ACPI_WHEA_HEADER *)wdat_pos;
2655 acpi_print_whea(whea,
2656 acpi_print_wdat_action, acpi_print_wdat_instruction,
2657 NULL);
2658 wdat_pos += sizeof(ACPI_WDAT_ENTRY);
2659 }
2660 printf(END_COMMENT);
2661 }
2662
2663 static void
2664 acpi_handle_wdrt(ACPI_TABLE_HEADER *sdp)
2665 {
2666 ACPI_TABLE_WDRT *wdrt;
2667
2668 printf(BEGIN_COMMENT);
2669 acpi_print_sdt(sdp);
2670 wdrt = (ACPI_TABLE_WDRT *)sdp;
2671
2672 printf("\tControl Register=");
2673 acpi_print_gas(&wdrt->ControlRegister);
2674 printf("\tCount Register=");
2675 acpi_print_gas(&wdrt->CountRegister);
2676 acpi_print_pci(wdrt->PciVendorId, wdrt->PciDeviceId,
2677 wdrt->PciSegment, wdrt->PciBus, wdrt->PciDevice, wdrt->PciFunction);
2678
2679 /* Value must be >= 511 and < 65535 */
2680 printf("\tMaxCount=%d", wdrt->MaxCount);
2681 if (wdrt->MaxCount < 511)
2682 printf(" (Out of Range. Valid range: 511 <= maxcount < 65535)");
2683 printf("\n");
2684
2685 printf("\tUnit={");
2686 switch (wdrt->Units) {
2687 case 0:
2688 printf("1 seconds/count");
2689 break;
2690 case 1:
2691 printf("100 milliseconds/count");
2692 break;
2693 case 2:
2694 printf("10 milliseconds/count");
2695 break;
2696 default:
2697 printf("%d", wdrt->Units);
2698 break;
2699 }
2700 printf("}\n");
2701
2702 printf(END_COMMENT);
2703 }
2704
2705 static void
2706 acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
2707 {
2708 printf(" ");
2709 acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
2710 printf(": Length=%d, Revision=%d, Checksum=%d",
2711 sdp->Length, sdp->Revision, sdp->Checksum);
2712 if (acpi_checksum(sdp, sdp->Length))
2713 printf(" (Incorrect)");
2714 printf(",\n\tOEMID=");
2715 acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
2716 printf(", OEM Table ID=");
2717 acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
2718 printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
2719 printf("\tCreator ID=");
2720 acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
2721 printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
2722 }
2723
2724 static void
2725 acpi_dump_bytes(ACPI_TABLE_HEADER *sdp)
2726 {
2727 unsigned int i;
2728 uint8_t *p;
2729
2730 p = (uint8_t *)sdp;
2731 printf("\n\tData={");
2732 for (i = 0; i < sdp->Length; i++) {
2733 if (cflag) {
2734 if (i % 64 == 0)
2735 printf("\n\t ");
2736 else if (i % 16 == 0)
2737 printf(" ");
2738 printf("%c", (p[i] >= ' ' && p[i] <= '~') ? p[i] : '.');
2739 } else {
2740 if (i % 16 == 0)
2741 printf("\n\t\t");
2742 else if (i % 8 == 0)
2743 printf(" ");
2744 printf(" %02x", p[i]);
2745 }
2746 }
2747 printf("\n\t}\n");
2748 }
2749
2750 static void
2751 acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
2752 {
2753 ACPI_TABLE_RSDT *rsdt;
2754 ACPI_TABLE_XSDT *xsdt;
2755 int i, entries;
2756
2757 rsdt = (ACPI_TABLE_RSDT *)rsdp;
2758 xsdt = (ACPI_TABLE_XSDT *)rsdp;
2759 printf(BEGIN_COMMENT);
2760 acpi_print_sdt(rsdp);
2761 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
2762 printf("\tEntries={ ");
2763 for (i = 0; i < entries; i++) {
2764 if (i > 0)
2765 printf(", ");
2766 if (addr_size == 4)
2767 printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
2768 else
2769 printf("0x%016jx",
2770 (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
2771 }
2772 printf(" }\n");
2773 printf(END_COMMENT);
2774 }
2775
2776 static const char *acpi_pm_profiles[] = {
2777 "Unspecified", "Desktop", "Mobile", "Workstation",
2778 "Enterprise Server", "SOHO Server", "Appliance PC"
2779 };
2780
2781 static void
2782 acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
2783 {
2784 ACPI_TABLE_FADT *fadt;
2785 const char *pm;
2786
2787 fadt = (ACPI_TABLE_FADT *)sdp;
2788 printf(BEGIN_COMMENT);
2789 acpi_print_sdt(sdp);
2790 printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
2791 fadt->Dsdt);
2792 printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
2793 if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
2794 pm = "Reserved";
2795 else
2796 pm = acpi_pm_profiles[fadt->PreferredProfile];
2797 printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
2798 printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
2799 printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
2800 printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
2801 printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
2802 printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
2803 printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
2804 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
2805 fadt->Pm1aEventBlock,
2806 fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
2807 if (fadt->Pm1bEventBlock != 0)
2808 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
2809 fadt->Pm1bEventBlock,
2810 fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
2811 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
2812 fadt->Pm1aControlBlock,
2813 fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
2814 if (fadt->Pm1bControlBlock != 0)
2815 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
2816 fadt->Pm1bControlBlock,
2817 fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
2818 if (fadt->Pm2ControlBlock != 0)
2819 printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
2820 fadt->Pm2ControlBlock,
2821 fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
2822 printf("\tPM_TMR_BLK=0x%x-0x%x\n",
2823 fadt->PmTimerBlock,
2824 fadt->PmTimerBlock + fadt->PmTimerLength - 1);
2825 if (fadt->Gpe0Block != 0)
2826 printf("\tGPE0_BLK=0x%x-0x%x\n",
2827 fadt->Gpe0Block,
2828 fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
2829 if (fadt->Gpe1Block != 0)
2830 printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
2831 fadt->Gpe1Block,
2832 fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
2833 fadt->Gpe1Base);
2834 if (fadt->CstControl != 0)
2835 printf("\tCST_CNT=0x%x\n", fadt->CstControl);
2836 printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
2837 fadt->C2Latency, fadt->C3Latency);
2838 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
2839 fadt->FlushSize, fadt->FlushStride);
2840 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
2841 fadt->DutyOffset, fadt->DutyWidth);
2842 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
2843 fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
2844
2845 #define PRINTFLAG(var, flag) printflag((var), ACPI_FADT_## flag, #flag)
2846
2847 printf("\tIAPC_BOOT_ARCH=");
2848 PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
2849 PRINTFLAG(fadt->BootFlags, 8042);
2850 PRINTFLAG(fadt->BootFlags, NO_VGA);
2851 PRINTFLAG(fadt->BootFlags, NO_MSI);
2852 PRINTFLAG(fadt->BootFlags, NO_ASPM);
2853 PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
2854 PRINTFLAG_END();
2855
2856 printf("\tFlags=");
2857 PRINTFLAG(fadt->Flags, WBINVD);
2858 PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
2859 PRINTFLAG(fadt->Flags, C1_SUPPORTED);
2860 PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
2861 PRINTFLAG(fadt->Flags, POWER_BUTTON);
2862 PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
2863 PRINTFLAG(fadt->Flags, FIXED_RTC);
2864 PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
2865 PRINTFLAG(fadt->Flags, 32BIT_TIMER);
2866 PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
2867 PRINTFLAG(fadt->Flags, RESET_REGISTER);
2868 PRINTFLAG(fadt->Flags, SEALED_CASE);
2869 PRINTFLAG(fadt->Flags, HEADLESS);
2870 PRINTFLAG(fadt->Flags, SLEEP_TYPE);
2871 PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
2872 PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
2873 PRINTFLAG(fadt->Flags, S4_RTC_VALID);
2874 PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
2875 PRINTFLAG(fadt->Flags, APIC_CLUSTER);
2876 PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
2877 PRINTFLAG(fadt->Flags, HW_REDUCED);
2878 PRINTFLAG(fadt->Flags, LOW_POWER_S0);
2879 PRINTFLAG_END();
2880
2881 #undef PRINTFLAG
2882
2883 if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
2884 printf("\tRESET_REG=");
2885 acpi_print_gas(&fadt->ResetRegister);
2886 printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
2887 }
2888 if (acpi_get_fadt_revision(fadt) > 1) {
2889 printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
2890 printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
2891 printf("\tX_PM1a_EVT_BLK=");
2892 acpi_print_gas(&fadt->XPm1aEventBlock);
2893 if (fadt->XPm1bEventBlock.Address != 0) {
2894 printf("\n\tX_PM1b_EVT_BLK=");
2895 acpi_print_gas(&fadt->XPm1bEventBlock);
2896 }
2897 printf("\n\tX_PM1a_CNT_BLK=");
2898 acpi_print_gas(&fadt->XPm1aControlBlock);
2899 if (fadt->XPm1bControlBlock.Address != 0) {
2900 printf("\n\tX_PM1b_CNT_BLK=");
2901 acpi_print_gas(&fadt->XPm1bControlBlock);
2902 }
2903 if (fadt->XPm2ControlBlock.Address != 0) {
2904 printf("\n\tX_PM2_CNT_BLK=");
2905 acpi_print_gas(&fadt->XPm2ControlBlock);
2906 }
2907 printf("\n\tX_PM_TMR_BLK=");
2908 acpi_print_gas(&fadt->XPmTimerBlock);
2909 if (fadt->XGpe0Block.Address != 0) {
2910 printf("\n\tX_GPE0_BLK=");
2911 acpi_print_gas(&fadt->XGpe0Block);
2912 }
2913 if (fadt->XGpe1Block.Address != 0) {
2914 printf("\n\tX_GPE1_BLK=");
2915 acpi_print_gas(&fadt->XGpe1Block);
2916 }
2917 printf("\n");
2918 }
2919
2920 printf(END_COMMENT);
2921 }
2922
2923 static void
2924 acpi_print_facs(ACPI_TABLE_FACS *facs)
2925 {
2926 printf(BEGIN_COMMENT);
2927 printf(" FACS:\tLength=%u, ", facs->Length);
2928 printf("HwSig=0x%08x, ", facs->HardwareSignature);
2929 printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
2930
2931 printf("\tGlobal_Lock=");
2932 if (facs->GlobalLock != 0) {
2933 if (facs->GlobalLock & ACPI_GLOCK_PENDING)
2934 printf("PENDING,");
2935 if (facs->GlobalLock & ACPI_GLOCK_OWNED)
2936 printf("OWNED");
2937 }
2938 printf("\n");
2939
2940 printf("\tFlags=");
2941 if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
2942 printf("S4BIOS");
2943 printf("\n");
2944
2945 if (facs->XFirmwareWakingVector != 0)
2946 printf("\tX_Firm_Wake_Vec=%016jx\n",
2947 (uintmax_t)facs->XFirmwareWakingVector);
2948 printf("\tVersion=%u\n", facs->Version);
2949
2950 printf(END_COMMENT);
2951 }
2952
2953 static void
2954 acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
2955 {
2956 printf(BEGIN_COMMENT);
2957 acpi_print_sdt(dsdp);
2958 printf(END_COMMENT);
2959 }
2960
2961 int
2962 acpi_checksum(void *p, size_t length)
2963 {
2964 uint8_t *bp;
2965 uint8_t sum;
2966
2967 bp = p;
2968 sum = 0;
2969 while (length--)
2970 sum += *bp++;
2971
2972 return (sum);
2973 }
2974
2975 static ACPI_TABLE_HEADER *
2976 acpi_map_sdt(vm_offset_t pa)
2977 {
2978 ACPI_TABLE_HEADER *sp;
2979
2980 sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
2981 sp = acpi_map_physical(pa, sp->Length);
2982 return (sp);
2983 }
2984
2985 static void
2986 acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
2987 {
2988 printf(BEGIN_COMMENT);
2989 printf(" RSD PTR: OEM=");
2990 acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
2991 printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
2992 rp->Revision);
2993 if (rp->Revision < 2) {
2994 printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
2995 rp->Checksum);
2996 } else {
2997 printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
2998 (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
2999 rp->ExtendedChecksum);
3000 }
3001 printf(END_COMMENT);
3002 }
3003
3004 static void
3005 acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
3006 {
3007 ACPI_TABLE_HEADER *sdp;
3008 ACPI_TABLE_RSDT *rsdt;
3009 ACPI_TABLE_XSDT *xsdt;
3010 vm_offset_t addr = 0;
3011 int entries, i;
3012
3013 acpi_print_rsdt(rsdp);
3014 rsdt = (ACPI_TABLE_RSDT *)rsdp;
3015 xsdt = (ACPI_TABLE_XSDT *)rsdp;
3016 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
3017 for (i = 0; i < entries; i++) {
3018 if (addr_size == 4)
3019 addr = le32toh(rsdt->TableOffsetEntry[i]);
3020 else
3021 addr = le64toh(xsdt->TableOffsetEntry[i]);
3022 if (addr == 0)
3023 continue;
3024 sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
3025 if (acpi_checksum(sdp, sdp->Length)) {
3026 warnx("RSDT entry %d (sig %.4s) is corrupt", i,
3027 sdp->Signature);
3028 if (sflag)
3029 continue;
3030 }
3031 if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
3032 acpi_handle_fadt(sdp);
3033 else if (!memcmp(sdp->Signature, ACPI_SIG_BERT, 4))
3034 acpi_handle_bert(sdp);
3035 else if (!memcmp(sdp->Signature, ACPI_SIG_BOOT, 4))
3036 acpi_handle_boot(sdp);
3037 else if (!memcmp(sdp->Signature, ACPI_SIG_CPEP, 4))
3038 acpi_handle_cpep(sdp);
3039 else if (!memcmp(sdp->Signature, ACPI_SIG_DBGP, 4))
3040 acpi_handle_dbgp(sdp);
3041 else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
3042 acpi_handle_dmar(sdp);
3043 else if (!memcmp(sdp->Signature, ACPI_SIG_EINJ, 4))
3044 acpi_handle_einj(sdp);
3045 else if (!memcmp(sdp->Signature, ACPI_SIG_ERST, 4))
3046 acpi_handle_erst(sdp);
3047 else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
3048 acpi_handle_madt(sdp);
3049 else if (!memcmp(sdp->Signature, ACPI_SIG_MSCT, 4))
3050 acpi_handle_msct(sdp);
3051 else if (!memcmp(sdp->Signature, ACPI_SIG_HEST, 4))
3052 acpi_handle_hest(sdp);
3053 else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
3054 acpi_handle_hpet(sdp);
3055 else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
3056 acpi_handle_ecdt(sdp);
3057 else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
3058 acpi_handle_mcfg(sdp);
3059 else if (!memcmp(sdp->Signature, ACPI_SIG_SBST, 4))
3060 acpi_handle_sbst(sdp);
3061 else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
3062 acpi_handle_slit(sdp);
3063 else if (!memcmp(sdp->Signature, ACPI_SIG_SPCR, 4))
3064 acpi_handle_spcr(sdp);
3065 else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
3066 acpi_handle_srat(sdp);
3067 else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
3068 acpi_handle_tcpa(sdp);
3069 else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
3070 acpi_handle_nfit(sdp);
3071 else if (!memcmp(sdp->Signature, ACPI_SIG_WAET, 4))
3072 acpi_handle_waet(sdp);
3073 else if (!memcmp(sdp->Signature, ACPI_SIG_WDAT, 4))
3074 acpi_handle_wdat(sdp);
3075 else if (!memcmp(sdp->Signature, ACPI_SIG_WDRT, 4))
3076 acpi_handle_wdrt(sdp);
3077 else {
3078 printf(BEGIN_COMMENT);
3079 acpi_print_sdt(sdp);
3080 acpi_dump_bytes(sdp);
3081 printf(END_COMMENT);
3082 }
3083 }
3084 }
3085
3086 ACPI_TABLE_HEADER *
3087 sdt_load_devmem(void)
3088 {
3089 ACPI_TABLE_RSDP *rp;
3090 ACPI_TABLE_HEADER *rsdp;
3091
3092 rp = acpi_find_rsd_ptr();
3093 if (!rp)
3094 errx(EXIT_FAILURE, "Can't find ACPI information");
3095
3096 if (tflag)
3097 acpi_print_rsd_ptr(rp);
3098 if (rp->Revision < 2) {
3099 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
3100 if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
3101 acpi_checksum(rsdp, rsdp->Length) != 0)
3102 errx(EXIT_FAILURE, "RSDT is corrupted");
3103 addr_size = sizeof(uint32_t);
3104 } else {
3105 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
3106 if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
3107 acpi_checksum(rsdp, rsdp->Length) != 0)
3108 errx(EXIT_FAILURE, "XSDT is corrupted");
3109 addr_size = sizeof(uint64_t);
3110 }
3111 return (rsdp);
3112 }
3113
3114 /* Write the DSDT to a file, concatenating any SSDTs (if present). */
3115 static int
3116 write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
3117 {
3118 ACPI_TABLE_HEADER sdt;
3119 ACPI_TABLE_HEADER *ssdt;
3120 uint8_t sum;
3121
3122 /* Create a new checksum to account for the DSDT and any SSDTs. */
3123 sdt = *dsdt;
3124 if (rsdt != NULL) {
3125 sdt.Checksum = 0;
3126 sum = acpi_checksum(dsdt + 1, dsdt->Length -
3127 sizeof(ACPI_TABLE_HEADER));
3128 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
3129 while (ssdt != NULL) {
3130 sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
3131 sum += acpi_checksum(ssdt + 1,
3132 ssdt->Length - sizeof(ACPI_TABLE_HEADER));
3133 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
3134 }
3135 sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
3136 sdt.Checksum -= sum;
3137 }
3138
3139 /* Write out the DSDT header and body. */
3140 write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
3141 write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
3142
3143 /* Write out any SSDTs (if present.) */
3144 if (rsdt != NULL) {
3145 ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
3146 while (ssdt != NULL) {
3147 write(fd, ssdt + 1, ssdt->Length -
3148 sizeof(ACPI_TABLE_HEADER));
3149 ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
3150 }
3151 }
3152 return (0);
3153 }
3154
3155 void
3156 dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
3157 {
3158 int fd;
3159 mode_t mode;
3160
3161 assert(outfile != NULL);
3162 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
3163 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
3164 if (fd == -1) {
3165 perror("dsdt_save_file");
3166 return;
3167 }
3168 write_dsdt(fd, rsdt, dsdp);
3169 close(fd);
3170 }
3171
3172 void
3173 aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
3174 {
3175 char buf[MAXPATHLEN], tmpstr[MAXPATHLEN], wrkdir[MAXPATHLEN];
3176 const char *iname = "/acpdump.din";
3177 const char *oname = "/acpdump.dsl";
3178 const char *tmpdir;
3179 FILE *fp;
3180 size_t len;
3181 int fd, status;
3182 pid_t pid;
3183
3184 if (rsdt == NULL)
3185 errx(EXIT_FAILURE, "aml_disassemble: invalid rsdt");
3186 if (dsdp == NULL)
3187 errx(EXIT_FAILURE, "aml_disassemble: invalid dsdp");
3188
3189 tmpdir = getenv("TMPDIR");
3190 if (tmpdir == NULL)
3191 tmpdir = _PATH_TMP;
3192 if (realpath(tmpdir, buf) == NULL) {
3193 perror("realpath tmp dir");
3194 return;
3195 }
3196 len = sizeof(wrkdir) - strlen(iname);
3197 if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
3198 fprintf(stderr, "$TMPDIR too long\n");
3199 return;
3200 }
3201 if (mkdtemp(wrkdir) == NULL) {
3202 perror("mkdtemp tmp working dir");
3203 return;
3204 }
3205 len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
3206 assert(len <= sizeof(tmpstr) - 1);
3207 fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
3208 if (fd < 0) {
3209 perror("iasl tmp file");
3210 return;
3211 }
3212 write_dsdt(fd, rsdt, dsdp);
3213 close(fd);
3214
3215 /* Run iasl -d on the temp file */
3216 if ((pid = fork()) == 0) {
3217 close(STDOUT_FILENO);
3218 if (vflag == 0)
3219 close(STDERR_FILENO);
3220 execl("/usr/bin/iasl", "iasl", "-d", tmpstr, NULL);
3221 err(EXIT_FAILURE, "exec");
3222 }
3223 if (pid > 0)
3224 wait(&status);
3225 if (unlink(tmpstr) < 0) {
3226 perror("unlink");
3227 goto out;
3228 }
3229 if (pid < 0) {
3230 perror("fork");
3231 goto out;
3232 }
3233 if (status != 0) {
3234 fprintf(stderr, "iast exit status = %d\n", status);
3235 }
3236
3237 /* Dump iasl's output to stdout */
3238 len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
3239 assert(len <= sizeof(tmpstr) - 1);
3240 fp = fopen(tmpstr, "r");
3241 if (unlink(tmpstr) < 0) {
3242 perror("unlink");
3243 goto out;
3244 }
3245 if (fp == NULL) {
3246 perror("iasl tmp file (read)");
3247 goto out;
3248 }
3249 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
3250 fwrite(buf, 1, len, stdout);
3251 fclose(fp);
3252
3253 out:
3254 if (rmdir(wrkdir) < 0)
3255 perror("rmdir");
3256 }
3257
3258 void
3259 sdt_print_all(ACPI_TABLE_HEADER *rsdp)
3260 {
3261 acpi_handle_rsdt(rsdp);
3262 }
3263
3264 /* Fetch a table matching the given signature via the RSDT. */
3265 ACPI_TABLE_HEADER *
3266 sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
3267 {
3268 ACPI_TABLE_HEADER *sdt;
3269 ACPI_TABLE_RSDT *rsdt;
3270 ACPI_TABLE_XSDT *xsdt;
3271 vm_offset_t addr = 0;
3272 int entries, i;
3273
3274 rsdt = (ACPI_TABLE_RSDT *)rsdp;
3275 xsdt = (ACPI_TABLE_XSDT *)rsdp;
3276 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
3277 for (i = 0; i < entries; i++) {
3278 if (addr_size == 4)
3279 addr = le32toh(rsdt->TableOffsetEntry[i]);
3280 else
3281 addr = le64toh(xsdt->TableOffsetEntry[i]);
3282 if (addr == 0)
3283 continue;
3284 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
3285 if (last != NULL) {
3286 if (sdt == last)
3287 last = NULL;
3288 continue;
3289 }
3290 if (memcmp(sdt->Signature, sig, strlen(sig)))
3291 continue;
3292 if (acpi_checksum(sdt, sdt->Length))
3293 errx(EXIT_FAILURE, "RSDT entry %d is corrupt", i);
3294 return (sdt);
3295 }
3296
3297 return (NULL);
3298 }
3299
3300 ACPI_TABLE_HEADER *
3301 dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
3302 {
3303 ACPI_TABLE_HEADER *sdt;
3304
3305 /* Use the DSDT address if it is version 1, otherwise use XDSDT. */
3306 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(
3307 acpi_select_address(fadt->Dsdt, fadt->XDsdt));
3308 if (acpi_checksum(sdt, sdt->Length))
3309 errx(EXIT_FAILURE, "DSDT is corrupt");
3310 return (sdt);
3311 }
3312