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