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