1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1998 Doug Rabson
5 * Copyright (c) 2000 Mitsuru IWASAKI <[email protected]>
6 * Copyright (c) 2020 Alexander Motin <[email protected]>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD$
31 */
32
33 #include <sys/param.h>
34 #include <sys/endian.h>
35 #include <sys/stat.h>
36 #include <sys/wait.h>
37 #include <assert.h>
38 #include <err.h>
39 #include <fcntl.h>
40 #include <paths.h>
41 #include <stdio.h>
42 #include <stdint.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <uuid.h>
47
48 #include "acpidump.h"
49
50 #define BEGIN_COMMENT "/*\n"
51 #define END_COMMENT " */\n"
52
53 static void acpi_print_string(char *s, size_t length);
54 static void acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
55 static int acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
56 static void acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
57 static void acpi_print_cpu(u_char cpu_id);
58 static void acpi_print_cpu_uid(uint32_t uid, char *uid_string);
59 static void acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
60 static void acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
61 uint64_t apic_addr);
62 static void acpi_print_mps_flags(uint16_t flags);
63 static void acpi_print_intr(uint32_t intr, uint16_t mps_flags);
64 static void acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
65 static void acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
66 static void acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
67 static void acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
68 static void acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
69 static void acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
70 static void acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
71 static void acpi_handle_wddt(ACPI_TABLE_HEADER *sdp);
72 static void acpi_handle_lpit(ACPI_TABLE_HEADER *sdp);
73 static void acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
74 uint32_t flags);
75 static void acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
76 static void acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
77 static void acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
78 static void acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
79 static void acpi_print_nfit(ACPI_NFIT_HEADER *nfit);
80 static void acpi_handle_nfit(ACPI_TABLE_HEADER *sdp);
81 static void acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
82 static void acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
83 static void acpi_print_facs(ACPI_TABLE_FACS *facs);
84 static void acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
85 static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
86 static void acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
87 static void acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
88 static void acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
89 void (*action)(ACPI_SUBTABLE_HEADER *));
90 static void acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
91 void (*action)(ACPI_NFIT_HEADER *));
92
93 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
94 static int addr_size;
95
96 /* Strings used in the TCPA table */
97 static const char *tcpa_event_type_strings[] = {
98 "PREBOOT Certificate",
99 "POST Code",
100 "Unused",
101 "No Action",
102 "Separator",
103 "Action",
104 "Event Tag",
105 "S-CRTM Contents",
106 "S-CRTM Version",
107 "CPU Microcode",
108 "Platform Config Flags",
109 "Table of Devices",
110 "Compact Hash",
111 "IPL",
112 "IPL Partition Data",
113 "Non-Host Code",
114 "Non-Host Config",
115 "Non-Host Info"
116 };
117
118 static const char *TCPA_pcclient_strings[] = {
119 "<undefined>",
120 "SMBIOS",
121 "BIS Certificate",
122 "POST BIOS ROM Strings",
123 "ESCD",
124 "CMOS",
125 "NVRAM",
126 "Option ROM Execute",
127 "Option ROM Configurateion",
128 "<undefined>",
129 "Option ROM Microcode Update ",
130 "S-CRTM Version String",
131 "S-CRTM Contents",
132 "POST Contents",
133 "Table of Devices",
134 };
135
136 #define PRINTFLAG_END() printflag_end()
137
138 static char pf_sep = '{';
139
140 static void
printflag_end(void)141 printflag_end(void)
142 {
143
144 if (pf_sep != '{') {
145 printf("}");
146 pf_sep = '{';
147 }
148 printf("\n");
149 }
150
151 static void
printflag(uint64_t var,uint64_t mask,const char * name)152 printflag(uint64_t var, uint64_t mask, const char *name)
153 {
154
155 if (var & mask) {
156 printf("%c%s", pf_sep, name);
157 pf_sep = ',';
158 }
159 }
160
161 static void
acpi_print_string(char * s,size_t length)162 acpi_print_string(char *s, size_t length)
163 {
164 int c;
165
166 /* Trim trailing spaces and NULLs */
167 while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
168 length--;
169
170 while (length--) {
171 c = *s++;
172 putchar(c);
173 }
174 }
175
176 static void
acpi_print_gas(ACPI_GENERIC_ADDRESS * gas)177 acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
178 {
179 switch(gas->SpaceId) {
180 case ACPI_GAS_MEMORY:
181 printf("0x%016jx:%u[%u] (Memory)", (uintmax_t)gas->Address,
182 gas->BitOffset, gas->BitWidth);
183 break;
184 case ACPI_GAS_IO:
185 printf("0x%02jx:%u[%u] (IO)", (uintmax_t)gas->Address,
186 gas->BitOffset, gas->BitWidth);
187 break;
188 case ACPI_GAS_PCI:
189 printf("%x:%x+0x%x:%u[%u] (PCI)", (uint16_t)(gas->Address >> 32),
190 (uint16_t)((gas->Address >> 16) & 0xffff),
191 (uint16_t)gas->Address, gas->BitOffset, gas->BitWidth);
192 break;
193 /* XXX How to handle these below? */
194 case ACPI_GAS_EMBEDDED:
195 printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
196 gas->BitOffset, gas->BitWidth);
197 break;
198 case ACPI_GAS_SMBUS:
199 printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
200 gas->BitOffset, gas->BitWidth);
201 break;
202 case ACPI_GAS_CMOS:
203 case ACPI_GAS_PCIBAR:
204 case ACPI_GAS_DATATABLE:
205 case ACPI_GAS_FIXED:
206 default:
207 printf("0x%016jx (?)", (uintmax_t)gas->Address);
208 break;
209 }
210 }
211
212 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
213 static int
acpi_get_fadt_revision(ACPI_TABLE_FADT * fadt)214 acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
215 {
216 int fadt_revision;
217
218 /* Set the FADT revision separately from the RSDP version. */
219 if (addr_size == 8) {
220 fadt_revision = 2;
221
222 #if defined(__i386__)
223 /*
224 * A few systems (e.g., IBM T23) have an RSDP that claims
225 * revision 2 but the 64 bit addresses are invalid. If
226 * revision 2 and the 32 bit address is non-zero but the
227 * 32 and 64 bit versions don't match, prefer the 32 bit
228 * version for all subsequent tables.
229 *
230 * The only known ACPI systems this affects are early
231 * implementations on 32-bit x86. Because of this limit the
232 * workaround to i386.
233 */
234 if (fadt->Facs != 0 &&
235 (fadt->XFacs & 0xffffffff) != fadt->Facs)
236 fadt_revision = 1;
237 #endif
238 } else
239 fadt_revision = 1;
240 return (fadt_revision);
241 }
242
243 static void
acpi_handle_fadt(ACPI_TABLE_HEADER * sdp)244 acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
245 {
246 ACPI_TABLE_HEADER *dsdp;
247 ACPI_TABLE_FACS *facs;
248 ACPI_TABLE_FADT *fadt;
249 vm_offset_t addr;
250 int fadt_revision;
251
252 fadt = (ACPI_TABLE_FADT *)sdp;
253 acpi_print_fadt(sdp);
254
255 fadt_revision = acpi_get_fadt_revision(fadt);
256 if (fadt_revision == 1)
257 addr = fadt->Facs;
258 else
259 addr = fadt->XFacs;
260 if (addr != 0) {
261 facs = (ACPI_TABLE_FACS *)acpi_map_sdt(addr);
262
263 if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 ||
264 facs->Length < 64)
265 errx(1, "FACS is corrupt");
266 acpi_print_facs(facs);
267 }
268
269 if (fadt_revision == 1)
270 dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
271 else
272 dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
273 if (acpi_checksum(dsdp, dsdp->Length))
274 errx(1, "DSDT is corrupt");
275 acpi_print_dsdt(dsdp);
276 }
277
278 static void
acpi_walk_subtables(ACPI_TABLE_HEADER * table,void * first,void (* action)(ACPI_SUBTABLE_HEADER *))279 acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
280 void (*action)(ACPI_SUBTABLE_HEADER *))
281 {
282 ACPI_SUBTABLE_HEADER *subtable;
283 char *end;
284
285 subtable = first;
286 end = (char *)table + table->Length;
287 while ((char *)subtable < end) {
288 printf("\n");
289 if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
290 warnx("invalid subtable length %u", subtable->Length);
291 return;
292 }
293 action(subtable);
294 subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
295 subtable->Length);
296 }
297 }
298
299 static void
acpi_walk_nfit(ACPI_TABLE_HEADER * table,void * first,void (* action)(ACPI_NFIT_HEADER *))300 acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
301 void (*action)(ACPI_NFIT_HEADER *))
302 {
303 ACPI_NFIT_HEADER *subtable;
304 char *end;
305
306 subtable = first;
307 end = (char *)table + table->Length;
308 while ((char *)subtable < end) {
309 printf("\n");
310 if (subtable->Length < sizeof(ACPI_NFIT_HEADER)) {
311 warnx("invalid subtable length %u", subtable->Length);
312 return;
313 }
314 action(subtable);
315 subtable = (ACPI_NFIT_HEADER *)((char *)subtable +
316 subtable->Length);
317 }
318 }
319
320 static void
acpi_print_cpu(u_char cpu_id)321 acpi_print_cpu(u_char cpu_id)
322 {
323
324 printf("\tACPI CPU=");
325 if (cpu_id == 0xff)
326 printf("ALL\n");
327 else
328 printf("%d\n", (u_int)cpu_id);
329 }
330
331 static void
acpi_print_cpu_uid(uint32_t uid,char * uid_string)332 acpi_print_cpu_uid(uint32_t uid, char *uid_string)
333 {
334
335 printf("\tUID=%d", uid);
336 if (uid_string != NULL)
337 printf(" (%s)", uid_string);
338 printf("\n");
339 }
340
341 static void
acpi_print_local_apic(uint32_t apic_id,uint32_t flags)342 acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
343 {
344
345 printf("\tFlags={");
346 if (flags & ACPI_MADT_ENABLED)
347 printf("ENABLED");
348 else
349 printf("DISABLED");
350 printf("}\n");
351 printf("\tAPIC ID=%d\n", apic_id);
352 }
353
354 static void
acpi_print_io_apic(uint32_t apic_id,uint32_t int_base,uint64_t apic_addr)355 acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
356 {
357
358 printf("\tAPIC ID=%d\n", apic_id);
359 printf("\tINT BASE=%d\n", int_base);
360 printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
361 }
362
363 static void
acpi_print_mps_flags(uint16_t flags)364 acpi_print_mps_flags(uint16_t flags)
365 {
366
367 printf("\tFlags={Polarity=");
368 switch (flags & ACPI_MADT_POLARITY_MASK) {
369 case ACPI_MADT_POLARITY_CONFORMS:
370 printf("conforming");
371 break;
372 case ACPI_MADT_POLARITY_ACTIVE_HIGH:
373 printf("active-hi");
374 break;
375 case ACPI_MADT_POLARITY_ACTIVE_LOW:
376 printf("active-lo");
377 break;
378 default:
379 printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
380 break;
381 }
382 printf(", Trigger=");
383 switch (flags & ACPI_MADT_TRIGGER_MASK) {
384 case ACPI_MADT_TRIGGER_CONFORMS:
385 printf("conforming");
386 break;
387 case ACPI_MADT_TRIGGER_EDGE:
388 printf("edge");
389 break;
390 case ACPI_MADT_TRIGGER_LEVEL:
391 printf("level");
392 break;
393 default:
394 printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
395 }
396 printf("}\n");
397 }
398
399 static void
acpi_print_gicc_flags(uint32_t flags)400 acpi_print_gicc_flags(uint32_t flags)
401 {
402
403 printf("\tFlags={Performance intr=");
404 if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
405 printf("edge");
406 else
407 printf("level");
408 printf(", VGIC intr=");
409 if (flags & ACPI_MADT_VGIC_IRQ_MODE)
410 printf("edge");
411 else
412 printf("level");
413 printf("}\n");
414 }
415
416 static void
acpi_print_intr(uint32_t intr,uint16_t mps_flags)417 acpi_print_intr(uint32_t intr, uint16_t mps_flags)
418 {
419
420 printf("\tINTR=%d\n", intr);
421 acpi_print_mps_flags(mps_flags);
422 }
423
424 static void
acpi_print_local_nmi(u_int lint,uint16_t mps_flags)425 acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
426 {
427
428 printf("\tLINT Pin=%d\n", lint);
429 acpi_print_mps_flags(mps_flags);
430 }
431
432 static const char *apic_types[] = {
433 [ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
434 [ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
435 [ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
436 [ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
437 [ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
438 [ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
439 [ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
440 [ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
441 [ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
442 [ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
443 [ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
444 [ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
445 [ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
446 [ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
447 [ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
448 [ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
449 };
450
451 static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
452 "Corrected Platform Error" };
453
454 static void
acpi_print_madt(ACPI_SUBTABLE_HEADER * mp)455 acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
456 {
457 ACPI_MADT_LOCAL_APIC *lapic;
458 ACPI_MADT_IO_APIC *ioapic;
459 ACPI_MADT_INTERRUPT_OVERRIDE *over;
460 ACPI_MADT_NMI_SOURCE *nmi;
461 ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
462 ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
463 ACPI_MADT_IO_SAPIC *iosapic;
464 ACPI_MADT_LOCAL_SAPIC *lsapic;
465 ACPI_MADT_INTERRUPT_SOURCE *isrc;
466 ACPI_MADT_LOCAL_X2APIC *x2apic;
467 ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
468 ACPI_MADT_GENERIC_INTERRUPT *gicc;
469 ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
470 ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
471 ACPI_MADT_GENERIC_TRANSLATOR *gict;
472
473 if (mp->Type < nitems(apic_types))
474 printf("\tType=%s\n", apic_types[mp->Type]);
475 else
476 printf("\tType=%d (unknown)\n", mp->Type);
477 switch (mp->Type) {
478 case ACPI_MADT_TYPE_LOCAL_APIC:
479 lapic = (ACPI_MADT_LOCAL_APIC *)mp;
480 acpi_print_cpu(lapic->ProcessorId);
481 acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
482 break;
483 case ACPI_MADT_TYPE_IO_APIC:
484 ioapic = (ACPI_MADT_IO_APIC *)mp;
485 acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
486 ioapic->Address);
487 break;
488 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
489 over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
490 printf("\tBUS=%d\n", (u_int)over->Bus);
491 printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
492 acpi_print_intr(over->GlobalIrq, over->IntiFlags);
493 break;
494 case ACPI_MADT_TYPE_NMI_SOURCE:
495 nmi = (ACPI_MADT_NMI_SOURCE *)mp;
496 acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
497 break;
498 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
499 lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
500 acpi_print_cpu(lapic_nmi->ProcessorId);
501 acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
502 break;
503 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
504 lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
505 printf("\tLocal APIC ADDR=0x%016jx\n",
506 (uintmax_t)lapic_over->Address);
507 break;
508 case ACPI_MADT_TYPE_IO_SAPIC:
509 iosapic = (ACPI_MADT_IO_SAPIC *)mp;
510 acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
511 iosapic->Address);
512 break;
513 case ACPI_MADT_TYPE_LOCAL_SAPIC:
514 lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
515 acpi_print_cpu(lsapic->ProcessorId);
516 acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
517 printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
518 if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
519 acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
520 break;
521 case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
522 isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
523 if (isrc->Type < nitems(platform_int_types))
524 printf("\tType=%s\n", platform_int_types[isrc->Type]);
525 else
526 printf("\tType=%d (unknown)\n", isrc->Type);
527 printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
528 printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
529 printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
530 acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
531 break;
532 case ACPI_MADT_TYPE_LOCAL_X2APIC:
533 x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
534 acpi_print_cpu_uid(x2apic->Uid, NULL);
535 acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
536 break;
537 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
538 x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
539 acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
540 acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
541 break;
542 case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
543 gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
544 acpi_print_cpu_uid(gicc->Uid, NULL);
545 printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
546 acpi_print_gicc_flags(gicc->Flags);
547 printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
548 printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
549 printf("\tParked ADDR=%016jx\n",
550 (uintmax_t)gicc->ParkedAddress);
551 printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
552 printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
553 printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
554 printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
555 printf("\tGICR ADDR=%016jx\n",
556 (uintmax_t)gicc->GicrBaseAddress);
557 printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
558 printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass);
559 printf("\tSPE INTR=%d\n", gicc->SpeInterrupt);
560 break;
561 case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
562 gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
563 printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
564 printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
565 printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
566 printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
567 break;
568 case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
569 gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
570 printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
571 printf("\tLength=%08x\n", gicr->Length);
572 break;
573 case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
574 gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
575 printf("\tGIC ITS ID=%d\n", gict->TranslationId);
576 printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
577 break;
578 }
579 }
580
581 static void
acpi_handle_madt(ACPI_TABLE_HEADER * sdp)582 acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
583 {
584 ACPI_TABLE_MADT *madt;
585
586 printf(BEGIN_COMMENT);
587 acpi_print_sdt(sdp);
588 madt = (ACPI_TABLE_MADT *)sdp;
589 printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
590 printf("\tFlags={");
591 if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
592 printf("PC-AT");
593 printf("}\n");
594 acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
595 printf(END_COMMENT);
596 }
597
598 static void
acpi_handle_bert(ACPI_TABLE_HEADER * sdp)599 acpi_handle_bert(ACPI_TABLE_HEADER *sdp)
600 {
601 ACPI_TABLE_BERT *bert;
602
603 printf(BEGIN_COMMENT);
604 acpi_print_sdt(sdp);
605 bert = (ACPI_TABLE_BERT *)sdp;
606 printf("\tRegionLength=%d\n", bert->RegionLength);
607 printf("\tAddress=0x%016jx\n", bert->Address);
608 printf(END_COMMENT);
609 }
610
611 static void
acpi_print_whea(ACPI_WHEA_HEADER * w)612 acpi_print_whea(ACPI_WHEA_HEADER *w)
613 {
614
615 printf("\n\tAction=%d\n", w->Action);
616 printf("\tInstruction=%d\n", w->Instruction);
617 printf("\tFlags=%02x\n", w->Flags);
618 printf("\tRegisterRegion=");
619 acpi_print_gas(&w->RegisterRegion);
620 printf("\n\tValue=0x%016jx\n", w->Value);
621 printf("\tMask=0x%016jx\n", w->Mask);
622 }
623
624 static void
acpi_handle_einj(ACPI_TABLE_HEADER * sdp)625 acpi_handle_einj(ACPI_TABLE_HEADER *sdp)
626 {
627 ACPI_TABLE_EINJ *einj;
628 ACPI_WHEA_HEADER *w;
629 u_int i;
630
631 printf(BEGIN_COMMENT);
632 acpi_print_sdt(sdp);
633 einj = (ACPI_TABLE_EINJ *)sdp;
634 printf("\tHeaderLength=%d\n", einj->HeaderLength);
635 printf("\tFlags=0x%02x\n", einj->Flags);
636 printf("\tEntries=%d\n", einj->Entries);
637 w = (ACPI_WHEA_HEADER *)(einj + 1);
638 for (i = 0; i < MIN(einj->Entries, (sdp->Length -
639 sizeof(ACPI_TABLE_EINJ)) / sizeof(ACPI_WHEA_HEADER)); i++)
640 acpi_print_whea(w + i);
641 printf(END_COMMENT);
642 }
643
644 static void
acpi_handle_erst(ACPI_TABLE_HEADER * sdp)645 acpi_handle_erst(ACPI_TABLE_HEADER *sdp)
646 {
647 ACPI_TABLE_ERST *erst;
648 ACPI_WHEA_HEADER *w;
649 u_int i;
650
651 printf(BEGIN_COMMENT);
652 acpi_print_sdt(sdp);
653 erst = (ACPI_TABLE_ERST *)sdp;
654 printf("\tHeaderLength=%d\n", erst->HeaderLength);
655 printf("\tEntries=%d\n", erst->Entries);
656 w = (ACPI_WHEA_HEADER *)(erst + 1);
657 for (i = 0; i < MIN(erst->Entries, (sdp->Length -
658 sizeof(ACPI_TABLE_ERST)) / sizeof(ACPI_WHEA_HEADER)); i++)
659 acpi_print_whea(w + i);
660 printf(END_COMMENT);
661 }
662
663 static void
acpi_print_hest_bank(ACPI_HEST_IA_ERROR_BANK * b)664 acpi_print_hest_bank(ACPI_HEST_IA_ERROR_BANK *b)
665 {
666
667 printf("\tBank:\n");
668 printf("\t\tBankNumber=%d\n", b->BankNumber);
669 printf("\t\tClearStatusOnInit=%d\n", b->ClearStatusOnInit);
670 printf("\t\tStatusFormat=%d\n", b->StatusFormat);
671 printf("\t\tControlRegister=%x\n", b->ControlRegister);
672 printf("\t\tControlData=%jx\n", b->ControlData);
673 printf("\t\tStatusRegister=%x\n", b->StatusRegister);
674 printf("\t\tAddressRegister=%x\n", b->AddressRegister);
675 printf("\t\tMiscRegister=%x\n", b->MiscRegister);
676 }
677
678 static void
acpi_print_hest_notify(ACPI_HEST_NOTIFY * n)679 acpi_print_hest_notify(ACPI_HEST_NOTIFY *n)
680 {
681
682 printf("\t\tType=%d\n", n->Type);
683 printf("\t\tLength=%d\n", n->Length);
684 printf("\t\tConfigWriteEnable=%04x\n", n->ConfigWriteEnable);
685 printf("\t\tPollInterval=%d\n", n->PollInterval);
686 printf("\t\tVector=%d\n", n->Vector);
687 printf("\t\tPollingThresholdValue=%d\n", n->PollingThresholdValue);
688 printf("\t\tPollingThresholdWindow=%d\n", n->PollingThresholdWindow);
689 printf("\t\tErrorThresholdValue=%d\n", n->ErrorThresholdValue);
690 printf("\t\tErrorThresholdWindow=%d\n", n->ErrorThresholdWindow);
691 }
692
693 static void
acpi_print_hest_aer(ACPI_HEST_AER_COMMON * a)694 acpi_print_hest_aer(ACPI_HEST_AER_COMMON *a)
695 {
696
697 printf("\tFlags=%02x\n", a->Flags);
698 printf("\tEnabled=%d\n", a->Enabled);
699 printf("\tRecordsToPreallocate=%d\n", a->RecordsToPreallocate);
700 printf("\tMaxSectionsPerRecord=%d\n", a->MaxSectionsPerRecord);
701 printf("\tBus=%d\n", a->Bus);
702 printf("\tDevice=%d\n", a->Device);
703 printf("\tFunction=%d\n", a->Function);
704 printf("\tDeviceControl=%d\n", a->DeviceControl);
705 printf("\tUncorrectableMask=%d\n", a->UncorrectableMask);
706 printf("\tUncorrectableSeverity=%d\n", a->UncorrectableSeverity);
707 printf("\tCorrectableMask=%d\n", a->CorrectableMask);
708 printf("\tAdvancedCapabilities=%d\n", a->AdvancedCapabilities);
709 }
710
711 static int
acpi_handle_hest_structure(void * addr,int remaining)712 acpi_handle_hest_structure(void *addr, int remaining)
713 {
714 ACPI_HEST_HEADER *hdr = addr;
715 int i;
716
717 if (remaining < (int)sizeof(ACPI_HEST_HEADER))
718 return (-1);
719
720 printf("\n\tType=%d\n", hdr->Type);
721 printf("\tSourceId=%d\n", hdr->SourceId);
722 switch (hdr->Type) {
723 case ACPI_HEST_TYPE_IA32_CHECK: {
724 ACPI_HEST_IA_MACHINE_CHECK *s = addr;
725 printf("\tFlags=%02x\n", s->Flags);
726 printf("\tEnabled=%d\n", s->Enabled);
727 printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
728 printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
729 printf("\tGlobalCapabilityData=%jd\n", s->GlobalCapabilityData);
730 printf("\tGlobalControlData=%jd\n", s->GlobalControlData);
731 printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
732 for (i = 0; i < s->NumHardwareBanks; i++) {
733 acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
734 (s + 1) + i);
735 }
736 return (sizeof(*s) + s->NumHardwareBanks *
737 sizeof(ACPI_HEST_IA_ERROR_BANK));
738 }
739 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: {
740 ACPI_HEST_IA_CORRECTED *s = addr;
741 printf("\tFlags=%02x\n", s->Flags);
742 printf("\tEnabled=%d\n", s->Enabled);
743 printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
744 printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
745 printf("\tNotify:\n");
746 acpi_print_hest_notify(&s->Notify);
747 printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
748 for (i = 0; i < s->NumHardwareBanks; i++) {
749 acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
750 (s + 1) + i);
751 }
752 return (sizeof(*s) + s->NumHardwareBanks *
753 sizeof(ACPI_HEST_IA_ERROR_BANK));
754 }
755 case ACPI_HEST_TYPE_IA32_NMI: {
756 ACPI_HEST_IA_NMI *s = addr;
757 printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
758 printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
759 printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
760 return (sizeof(*s));
761 }
762 case ACPI_HEST_TYPE_AER_ROOT_PORT: {
763 ACPI_HEST_AER_ROOT *s = addr;
764 acpi_print_hest_aer(&s->Aer);
765 printf("\tRootErrorCommand=%d\n", s->RootErrorCommand);
766 return (sizeof(*s));
767 }
768 case ACPI_HEST_TYPE_AER_ENDPOINT: {
769 ACPI_HEST_AER *s = addr;
770 acpi_print_hest_aer(&s->Aer);
771 return (sizeof(*s));
772 }
773 case ACPI_HEST_TYPE_AER_BRIDGE: {
774 ACPI_HEST_AER_BRIDGE *s = addr;
775 acpi_print_hest_aer(&s->Aer);
776 printf("\tUncorrectableMask2=%d\n", s->UncorrectableMask2);
777 printf("\tUncorrectableSeverity2=%d\n", s->UncorrectableSeverity2);
778 printf("\tAdvancedCapabilities2=%d\n", s->AdvancedCapabilities2);
779 return (sizeof(*s));
780 }
781 case ACPI_HEST_TYPE_GENERIC_ERROR: {
782 ACPI_HEST_GENERIC *s = addr;
783 printf("\tRelatedSourceId=%d\n", s->RelatedSourceId);
784 printf("\tEnabled=%d\n", s->Enabled);
785 printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
786 printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
787 printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
788 printf("\tErrorStatusAddress=");
789 acpi_print_gas(&s->ErrorStatusAddress);
790 printf("\n");
791 printf("\tNotify:\n");
792 acpi_print_hest_notify(&s->Notify);
793 printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength);
794 return (sizeof(*s));
795 }
796 case ACPI_HEST_TYPE_GENERIC_ERROR_V2: {
797 ACPI_HEST_GENERIC_V2 *s = addr;
798 printf("\tRelatedSourceId=%d\n", s->RelatedSourceId);
799 printf("\tEnabled=%d\n", s->Enabled);
800 printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
801 printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
802 printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
803 printf("\tErrorStatusAddress=");
804 acpi_print_gas(&s->ErrorStatusAddress);
805 printf("\n");
806 printf("\tNotify:\n");
807 acpi_print_hest_notify(&s->Notify);
808 printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength);
809 printf("\tReadAckRegister=");
810 acpi_print_gas(&s->ReadAckRegister);
811 printf("\n");
812 printf("\tReadAckPreserve=%jd\n", s->ReadAckPreserve);
813 printf("\tReadAckWrite=%jd\n", s->ReadAckWrite);
814 return (sizeof(*s));
815 }
816 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: {
817 ACPI_HEST_IA_DEFERRED_CHECK *s = addr;
818 printf("\tFlags=%02x\n", s->Flags);
819 printf("\tEnabled=%d\n", s->Enabled);
820 printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
821 printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
822 printf("\tNotify:\n");
823 acpi_print_hest_notify(&s->Notify);
824 printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
825 for (i = 0; i < s->NumHardwareBanks; i++) {
826 acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
827 (s + 1) + i);
828 }
829 return (sizeof(*s) + s->NumHardwareBanks *
830 sizeof(ACPI_HEST_IA_ERROR_BANK));
831 }
832 default:
833 return (-1);
834 }
835 }
836
837 static void
acpi_handle_hest(ACPI_TABLE_HEADER * sdp)838 acpi_handle_hest(ACPI_TABLE_HEADER *sdp)
839 {
840 char *cp;
841 int remaining, consumed;
842 ACPI_TABLE_HEST *hest;
843
844 printf(BEGIN_COMMENT);
845 acpi_print_sdt(sdp);
846 hest = (ACPI_TABLE_HEST *)sdp;
847 printf("\tErrorSourceCount=%d\n", hest->ErrorSourceCount);
848
849 remaining = sdp->Length - sizeof(ACPI_TABLE_HEST);
850 while (remaining > 0) {
851 cp = (char *)sdp + sdp->Length - remaining;
852 consumed = acpi_handle_hest_structure(cp, remaining);
853 if (consumed <= 0)
854 break;
855 else
856 remaining -= consumed;
857 }
858 printf(END_COMMENT);
859 }
860
861 static void
acpi_handle_hpet(ACPI_TABLE_HEADER * sdp)862 acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
863 {
864 ACPI_TABLE_HPET *hpet;
865
866 printf(BEGIN_COMMENT);
867 acpi_print_sdt(sdp);
868 hpet = (ACPI_TABLE_HPET *)sdp;
869 printf("\tHPET Number=%d\n", hpet->Sequence);
870 printf("\tADDR=");
871 acpi_print_gas(&hpet->Address);
872 printf("\n\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
873 printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
874 8);
875 printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
876 1 : 0);
877 printf("\tLegacy IRQ routing capable={");
878 if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
879 printf("TRUE}\n");
880 else
881 printf("FALSE}\n");
882 printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
883 printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
884 printf("\tFlags=0x%02x\n", hpet->Flags);
885 printf(END_COMMENT);
886 }
887
888 static void
acpi_handle_ecdt(ACPI_TABLE_HEADER * sdp)889 acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
890 {
891 ACPI_TABLE_ECDT *ecdt;
892
893 printf(BEGIN_COMMENT);
894 acpi_print_sdt(sdp);
895 ecdt = (ACPI_TABLE_ECDT *)sdp;
896 printf("\tEC_CONTROL=");
897 acpi_print_gas(&ecdt->Control);
898 printf("\n\tEC_DATA=");
899 acpi_print_gas(&ecdt->Data);
900 printf("\n\tUID=%#x, ", ecdt->Uid);
901 printf("GPE_BIT=%#x\n", ecdt->Gpe);
902 printf("\tEC_ID=%s\n", ecdt->Id);
903 printf(END_COMMENT);
904 }
905
906 static void
acpi_handle_mcfg(ACPI_TABLE_HEADER * sdp)907 acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
908 {
909 ACPI_TABLE_MCFG *mcfg;
910 ACPI_MCFG_ALLOCATION *alloc;
911 u_int i, entries;
912
913 printf(BEGIN_COMMENT);
914 acpi_print_sdt(sdp);
915 mcfg = (ACPI_TABLE_MCFG *)sdp;
916 entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
917 sizeof(ACPI_MCFG_ALLOCATION);
918 alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
919 for (i = 0; i < entries; i++, alloc++) {
920 printf("\n");
921 printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
922 printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
923 printf("\tStart Bus=%d\n", alloc->StartBusNumber);
924 printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
925 }
926 printf(END_COMMENT);
927 }
928
929 static void
acpi_handle_slit(ACPI_TABLE_HEADER * sdp)930 acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
931 {
932 ACPI_TABLE_SLIT *slit;
933 UINT64 i, j;
934
935 printf(BEGIN_COMMENT);
936 acpi_print_sdt(sdp);
937 slit = (ACPI_TABLE_SLIT *)sdp;
938 printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
939 printf("\n\t ");
940 for (i = 0; i < slit->LocalityCount; i++)
941 printf(" %3ju", (uintmax_t)i);
942 printf("\n\t +");
943 for (i = 0; i < slit->LocalityCount; i++)
944 printf("----");
945 printf("\n");
946 for (i = 0; i < slit->LocalityCount; i++) {
947 printf("\t %3ju |", (uintmax_t)i);
948 for (j = 0; j < slit->LocalityCount; j++)
949 printf(" %3d",
950 slit->Entry[i * slit->LocalityCount + j]);
951 printf("\n");
952 }
953 printf(END_COMMENT);
954 }
955
956 static void
acpi_handle_wddt(ACPI_TABLE_HEADER * sdp)957 acpi_handle_wddt(ACPI_TABLE_HEADER *sdp)
958 {
959 ACPI_TABLE_WDDT *wddt;
960
961 printf(BEGIN_COMMENT);
962 acpi_print_sdt(sdp);
963 wddt = (ACPI_TABLE_WDDT *)sdp;
964 printf("\tSpecVersion=0x%04x, TableVersion=0x%04x\n",
965 wddt->SpecVersion, wddt->TableVersion);
966 printf("\tPciVendorId=0x%04x, Address=", wddt->PciVendorId);
967 acpi_print_gas(&wddt->Address);
968 printf("\n\tMaxCount=%u, MinCount=%u, Period=%ums\n",
969 wddt->MaxCount, wddt->MinCount, wddt->Period);
970
971 #define PRINTFLAG(var, flag) printflag((var), ACPI_WDDT_## flag, #flag)
972 printf("\tStatus=");
973 PRINTFLAG(wddt->Status, AVAILABLE);
974 PRINTFLAG(wddt->Status, ACTIVE);
975 PRINTFLAG(wddt->Status, TCO_OS_OWNED);
976 PRINTFLAG(wddt->Status, USER_RESET);
977 PRINTFLAG(wddt->Status, WDT_RESET);
978 PRINTFLAG(wddt->Status, POWER_FAIL);
979 PRINTFLAG(wddt->Status, UNKNOWN_RESET);
980 PRINTFLAG_END();
981 printf("\tCapability=");
982 PRINTFLAG(wddt->Capability, AUTO_RESET);
983 PRINTFLAG(wddt->Capability, ALERT_SUPPORT);
984 PRINTFLAG_END();
985 #undef PRINTFLAG
986
987 printf(END_COMMENT);
988 }
989
990 static void
acpi_print_native_lpit(ACPI_LPIT_NATIVE * nl)991 acpi_print_native_lpit(ACPI_LPIT_NATIVE *nl)
992 {
993 printf("\tEntryTrigger=");
994 acpi_print_gas(&nl->EntryTrigger);
995 printf("\n\tResidency=%u\n", nl->Residency);
996 printf("\tLatency=%u\n", nl->Latency);
997 if (nl->Header.Flags & ACPI_LPIT_NO_COUNTER)
998 printf("\tResidencyCounter=Not Present");
999 else {
1000 printf("\tResidencyCounter=");
1001 acpi_print_gas(&nl->ResidencyCounter);
1002 printf("\n");
1003 }
1004 if (nl->CounterFrequency)
1005 printf("\tCounterFrequency=%ju\n", nl->CounterFrequency);
1006 else
1007 printf("\tCounterFrequency=TSC\n");
1008 }
1009
1010 static void
acpi_print_lpit(ACPI_LPIT_HEADER * lpit)1011 acpi_print_lpit(ACPI_LPIT_HEADER *lpit)
1012 {
1013 if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
1014 printf("\tType=ACPI_LPIT_TYPE_NATIVE_CSTATE\n");
1015 else
1016 warnx("unknown LPIT type %u", lpit->Type);
1017
1018 printf("\tLength=%u\n", lpit->Length);
1019 printf("\tUniqueId=0x%04x\n", lpit->UniqueId);
1020 #define PRINTFLAG(var, flag) printflag((var), ACPI_LPIT_## flag, #flag)
1021 printf("\tFlags=");
1022 PRINTFLAG(lpit->Flags, STATE_DISABLED);
1023 PRINTFLAG_END();
1024 #undef PRINTFLAG
1025
1026 if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
1027 return acpi_print_native_lpit((ACPI_LPIT_NATIVE *)lpit);
1028 }
1029
1030 static void
acpi_walk_lpit(ACPI_TABLE_HEADER * table,void * first,void (* action)(ACPI_LPIT_HEADER *))1031 acpi_walk_lpit(ACPI_TABLE_HEADER *table, void *first,
1032 void (*action)(ACPI_LPIT_HEADER *))
1033 {
1034 ACPI_LPIT_HEADER *subtable;
1035 char *end;
1036
1037 subtable = first;
1038 end = (char *)table + table->Length;
1039 while ((char *)subtable < end) {
1040 printf("\n");
1041 if (subtable->Length < sizeof(ACPI_LPIT_HEADER)) {
1042 warnx("invalid subtable length %u", subtable->Length);
1043 return;
1044 }
1045 action(subtable);
1046 subtable = (ACPI_LPIT_HEADER *)((char *)subtable +
1047 subtable->Length);
1048 }
1049 }
1050
1051 static void
acpi_handle_lpit(ACPI_TABLE_HEADER * sdp)1052 acpi_handle_lpit(ACPI_TABLE_HEADER *sdp)
1053 {
1054 ACPI_TABLE_LPIT *lpit;
1055
1056 printf(BEGIN_COMMENT);
1057 acpi_print_sdt(sdp);
1058 lpit = (ACPI_TABLE_LPIT *)sdp;
1059 acpi_walk_lpit(sdp, (lpit + 1), acpi_print_lpit);
1060
1061 printf(END_COMMENT);
1062 }
1063
1064 static void
acpi_print_srat_cpu(uint32_t apic_id,uint32_t proximity_domain,uint32_t flags)1065 acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
1066 uint32_t flags)
1067 {
1068
1069 printf("\tFlags={");
1070 if (flags & ACPI_SRAT_CPU_ENABLED)
1071 printf("ENABLED");
1072 else
1073 printf("DISABLED");
1074 printf("}\n");
1075 printf("\tAPIC ID=%d\n", apic_id);
1076 printf("\tProximity Domain=%d\n", proximity_domain);
1077 }
1078
1079 static char *
acpi_tcpa_evname(struct TCPAevent * event)1080 acpi_tcpa_evname(struct TCPAevent *event)
1081 {
1082 struct TCPApc_event *pc_event;
1083 char *eventname = NULL;
1084
1085 pc_event = (struct TCPApc_event *)(event + 1);
1086
1087 switch(event->event_type) {
1088 case PREBOOT:
1089 case POST_CODE:
1090 case UNUSED:
1091 case NO_ACTION:
1092 case SEPARATOR:
1093 case SCRTM_CONTENTS:
1094 case SCRTM_VERSION:
1095 case CPU_MICROCODE:
1096 case PLATFORM_CONFIG_FLAGS:
1097 case TABLE_OF_DEVICES:
1098 case COMPACT_HASH:
1099 case IPL:
1100 case IPL_PARTITION_DATA:
1101 case NONHOST_CODE:
1102 case NONHOST_CONFIG:
1103 case NONHOST_INFO:
1104 asprintf(&eventname, "%s",
1105 tcpa_event_type_strings[event->event_type]);
1106 break;
1107
1108 case ACTION:
1109 eventname = calloc(event->event_size + 1, sizeof(char));
1110 memcpy(eventname, pc_event, event->event_size);
1111 break;
1112
1113 case EVENT_TAG:
1114 switch (pc_event->event_id) {
1115 case SMBIOS:
1116 case BIS_CERT:
1117 case CMOS:
1118 case NVRAM:
1119 case OPTION_ROM_EXEC:
1120 case OPTION_ROM_CONFIG:
1121 case S_CRTM_VERSION:
1122 case POST_BIOS_ROM:
1123 case ESCD:
1124 case OPTION_ROM_MICROCODE:
1125 case S_CRTM_CONTENTS:
1126 case POST_CONTENTS:
1127 asprintf(&eventname, "%s",
1128 TCPA_pcclient_strings[pc_event->event_id]);
1129 break;
1130
1131 default:
1132 asprintf(&eventname, "<unknown tag 0x%02x>",
1133 pc_event->event_id);
1134 break;
1135 }
1136 break;
1137
1138 default:
1139 asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
1140 break;
1141 }
1142
1143 return eventname;
1144 }
1145
1146 static void
acpi_print_tcpa(struct TCPAevent * event)1147 acpi_print_tcpa(struct TCPAevent *event)
1148 {
1149 int i;
1150 char *eventname;
1151
1152 eventname = acpi_tcpa_evname(event);
1153
1154 printf("\t%d", event->pcr_index);
1155 printf(" 0x");
1156 for (i = 0; i < 20; i++)
1157 printf("%02x", event->pcr_value[i]);
1158 printf(" [%s]\n", eventname ? eventname : "<unknown>");
1159
1160 free(eventname);
1161 }
1162
1163 static void
acpi_handle_tcpa(ACPI_TABLE_HEADER * sdp)1164 acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
1165 {
1166 struct TCPAbody *tcpa;
1167 struct TCPAevent *event;
1168 uintmax_t len, paddr;
1169 unsigned char *vaddr = NULL;
1170 unsigned char *vend = NULL;
1171
1172 printf(BEGIN_COMMENT);
1173 acpi_print_sdt(sdp);
1174 tcpa = (struct TCPAbody *) sdp;
1175
1176 switch (tcpa->platform_class) {
1177 case ACPI_TCPA_BIOS_CLIENT:
1178 len = tcpa->client.log_max_len;
1179 paddr = tcpa->client.log_start_addr;
1180 break;
1181
1182 case ACPI_TCPA_BIOS_SERVER:
1183 len = tcpa->server.log_max_len;
1184 paddr = tcpa->server.log_start_addr;
1185 break;
1186
1187 default:
1188 printf("XXX");
1189 printf(END_COMMENT);
1190 return;
1191 }
1192 printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
1193 tcpa->platform_class, paddr, len);
1194
1195 if (len == 0) {
1196 printf("\tEmpty TCPA table\n");
1197 printf(END_COMMENT);
1198 return;
1199 }
1200 if(sdp->Revision == 1){
1201 printf("\tOLD TCPA spec log found. Dumping not supported.\n");
1202 printf(END_COMMENT);
1203 return;
1204 }
1205
1206 vaddr = (unsigned char *)acpi_map_physical(paddr, len);
1207 vend = vaddr + len;
1208
1209 while (vaddr != NULL) {
1210 if ((vaddr + sizeof(struct TCPAevent) >= vend)||
1211 (vaddr + sizeof(struct TCPAevent) < vaddr))
1212 break;
1213 event = (struct TCPAevent *)(void *)vaddr;
1214 if (vaddr + event->event_size >= vend)
1215 break;
1216 if (vaddr + event->event_size < vaddr)
1217 break;
1218 if (event->event_type == 0 && event->event_size == 0)
1219 break;
1220 #if 0
1221 {
1222 unsigned int i, j, k;
1223
1224 printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
1225 for (j = 0, i = 0; i <
1226 sizeof(struct TCPAevent) + event->event_size; i++) {
1227 printf("%02x ", vaddr[i]);
1228 if ((i+1) % 8 == 0) {
1229 for (k = 0; k < 8; k++)
1230 printf("%c", isprint(vaddr[j+k]) ?
1231 vaddr[j+k] : '.');
1232 printf("\n\t\t%p ", &vaddr[i + 1]);
1233 j = i + 1;
1234 }
1235 }
1236 printf("\n"); }
1237 #endif
1238 acpi_print_tcpa(event);
1239
1240 vaddr += sizeof(struct TCPAevent) + event->event_size;
1241 }
1242
1243 printf(END_COMMENT);
1244 }
acpi_handle_tpm2(ACPI_TABLE_HEADER * sdp)1245 static void acpi_handle_tpm2(ACPI_TABLE_HEADER *sdp)
1246 {
1247 ACPI_TABLE_TPM2 *tpm2;
1248
1249 printf (BEGIN_COMMENT);
1250 acpi_print_sdt(sdp);
1251 tpm2 = (ACPI_TABLE_TPM2 *) sdp;
1252 printf ("\t\tControlArea=%jx\n", tpm2->ControlAddress);
1253 printf ("\t\tStartMethod=%x\n", tpm2->StartMethod);
1254 printf (END_COMMENT);
1255 }
1256
1257 static const char *
devscope_type2str(int type)1258 devscope_type2str(int type)
1259 {
1260 static char typebuf[16];
1261
1262 switch (type) {
1263 case 1:
1264 return ("PCI Endpoint Device");
1265 case 2:
1266 return ("PCI Sub-Hierarchy");
1267 case 3:
1268 return ("IOAPIC");
1269 case 4:
1270 return ("HPET");
1271 default:
1272 snprintf(typebuf, sizeof(typebuf), "%d", type);
1273 return (typebuf);
1274 }
1275 }
1276
1277 static int
acpi_handle_dmar_devscope(void * addr,int remaining)1278 acpi_handle_dmar_devscope(void *addr, int remaining)
1279 {
1280 char sep;
1281 int pathlen;
1282 ACPI_DMAR_PCI_PATH *path, *pathend;
1283 ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
1284
1285 if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
1286 return (-1);
1287
1288 if (remaining < devscope->Length)
1289 return (-1);
1290
1291 printf("\n");
1292 printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
1293 printf("\t\tLength=%d\n", devscope->Length);
1294 printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
1295 printf("\t\tStartBusNumber=%d\n", devscope->Bus);
1296
1297 path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
1298 pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
1299 pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
1300 if (path < pathend) {
1301 sep = '{';
1302 printf("\t\tPath=");
1303 do {
1304 printf("%c%d:%d", sep, path->Device, path->Function);
1305 sep=',';
1306 path++;
1307 } while (path < pathend);
1308 printf("}\n");
1309 }
1310
1311 return (devscope->Length);
1312 }
1313
1314 static void
acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT * drhd)1315 acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
1316 {
1317 char *cp;
1318 int remaining, consumed;
1319
1320 printf("\n");
1321 printf("\tType=DRHD\n");
1322 printf("\tLength=%d\n", drhd->Header.Length);
1323
1324 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
1325
1326 printf("\tFlags=");
1327 PRINTFLAG(drhd->Flags, INCLUDE_ALL);
1328 PRINTFLAG_END();
1329
1330 #undef PRINTFLAG
1331
1332 printf("\tSegment=%d\n", drhd->Segment);
1333 printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
1334
1335 remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
1336 if (remaining > 0)
1337 printf("\tDevice Scope:");
1338 while (remaining > 0) {
1339 cp = (char *)drhd + drhd->Header.Length - remaining;
1340 consumed = acpi_handle_dmar_devscope(cp, remaining);
1341 if (consumed <= 0)
1342 break;
1343 else
1344 remaining -= consumed;
1345 }
1346 }
1347
1348 static void
acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY * rmrr)1349 acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
1350 {
1351 char *cp;
1352 int remaining, consumed;
1353
1354 printf("\n");
1355 printf("\tType=RMRR\n");
1356 printf("\tLength=%d\n", rmrr->Header.Length);
1357 printf("\tSegment=%d\n", rmrr->Segment);
1358 printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
1359 printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
1360
1361 remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
1362 if (remaining > 0)
1363 printf("\tDevice Scope:");
1364 while (remaining > 0) {
1365 cp = (char *)rmrr + rmrr->Header.Length - remaining;
1366 consumed = acpi_handle_dmar_devscope(cp, remaining);
1367 if (consumed <= 0)
1368 break;
1369 else
1370 remaining -= consumed;
1371 }
1372 }
1373
1374 static void
acpi_handle_dmar_atsr(ACPI_DMAR_ATSR * atsr)1375 acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
1376 {
1377 char *cp;
1378 int remaining, consumed;
1379
1380 printf("\n");
1381 printf("\tType=ATSR\n");
1382 printf("\tLength=%d\n", atsr->Header.Length);
1383
1384 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
1385
1386 printf("\tFlags=");
1387 PRINTFLAG(atsr->Flags, ALL_PORTS);
1388 PRINTFLAG_END();
1389
1390 #undef PRINTFLAG
1391
1392 printf("\tSegment=%d\n", atsr->Segment);
1393
1394 remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
1395 if (remaining > 0)
1396 printf("\tDevice Scope:");
1397 while (remaining > 0) {
1398 cp = (char *)atsr + atsr->Header.Length - remaining;
1399 consumed = acpi_handle_dmar_devscope(cp, remaining);
1400 if (consumed <= 0)
1401 break;
1402 else
1403 remaining -= consumed;
1404 }
1405 }
1406
1407 static void
acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA * rhsa)1408 acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
1409 {
1410
1411 printf("\n");
1412 printf("\tType=RHSA\n");
1413 printf("\tLength=%d\n", rhsa->Header.Length);
1414 printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
1415 printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
1416 }
1417
1418 static int
acpi_handle_dmar_remapping_structure(void * addr,int remaining)1419 acpi_handle_dmar_remapping_structure(void *addr, int remaining)
1420 {
1421 ACPI_DMAR_HEADER *hdr = addr;
1422
1423 if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
1424 return (-1);
1425
1426 if (remaining < hdr->Length)
1427 return (-1);
1428
1429 switch (hdr->Type) {
1430 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1431 acpi_handle_dmar_drhd(addr);
1432 break;
1433 case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1434 acpi_handle_dmar_rmrr(addr);
1435 break;
1436 case ACPI_DMAR_TYPE_ROOT_ATS:
1437 acpi_handle_dmar_atsr(addr);
1438 break;
1439 case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1440 acpi_handle_dmar_rhsa(addr);
1441 break;
1442 default:
1443 printf("\n");
1444 printf("\tType=%d\n", hdr->Type);
1445 printf("\tLength=%d\n", hdr->Length);
1446 break;
1447 }
1448 return (hdr->Length);
1449 }
1450
1451 #ifndef ACPI_DMAR_X2APIC_OPT_OUT
1452 #define ACPI_DMAR_X2APIC_OPT_OUT (0x2)
1453 #endif
1454
1455 static void
acpi_handle_dmar(ACPI_TABLE_HEADER * sdp)1456 acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1457 {
1458 char *cp;
1459 int remaining, consumed;
1460 ACPI_TABLE_DMAR *dmar;
1461
1462 printf(BEGIN_COMMENT);
1463 acpi_print_sdt(sdp);
1464 dmar = (ACPI_TABLE_DMAR *)sdp;
1465 printf("\tHost Address Width=%d\n", dmar->Width + 1);
1466
1467 #define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
1468
1469 printf("\tFlags=");
1470 PRINTFLAG(dmar->Flags, INTR_REMAP);
1471 PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1472 PRINTFLAG_END();
1473
1474 #undef PRINTFLAG
1475
1476 remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1477 while (remaining > 0) {
1478 cp = (char *)sdp + sdp->Length - remaining;
1479 consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1480 if (consumed <= 0)
1481 break;
1482 else
1483 remaining -= consumed;
1484 }
1485
1486 printf(END_COMMENT);
1487 }
1488
1489 static void
acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY * mp)1490 acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
1491 {
1492
1493 printf("\tFlags={");
1494 if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
1495 printf("ENABLED");
1496 else
1497 printf("DISABLED");
1498 if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
1499 printf(",HOT_PLUGGABLE");
1500 if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
1501 printf(",NON_VOLATILE");
1502 printf("}\n");
1503 printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
1504 printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
1505 printf("\tProximity Domain=%d\n", mp->ProximityDomain);
1506 }
1507
1508 static const char *srat_types[] = {
1509 [ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
1510 [ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
1511 [ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
1512 [ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
1513 [ACPI_SRAT_TYPE_GIC_ITS_AFFINITY] = "GIC ITS",
1514 };
1515
1516 static void
acpi_print_srat(ACPI_SUBTABLE_HEADER * srat)1517 acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
1518 {
1519 ACPI_SRAT_CPU_AFFINITY *cpu;
1520 ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
1521 ACPI_SRAT_GICC_AFFINITY *gic;
1522
1523 if (srat->Type < nitems(srat_types))
1524 printf("\tType=%s\n", srat_types[srat->Type]);
1525 else
1526 printf("\tType=%d (unknown)\n", srat->Type);
1527 switch (srat->Type) {
1528 case ACPI_SRAT_TYPE_CPU_AFFINITY:
1529 cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
1530 acpi_print_srat_cpu(cpu->ApicId,
1531 cpu->ProximityDomainHi[2] << 24 |
1532 cpu->ProximityDomainHi[1] << 16 |
1533 cpu->ProximityDomainHi[0] << 0 |
1534 cpu->ProximityDomainLo, cpu->Flags);
1535 break;
1536 case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
1537 acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
1538 break;
1539 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
1540 x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
1541 acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
1542 x2apic->Flags);
1543 break;
1544 case ACPI_SRAT_TYPE_GICC_AFFINITY:
1545 gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
1546 acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
1547 gic->Flags);
1548 break;
1549 }
1550 }
1551
1552 static void
acpi_handle_srat(ACPI_TABLE_HEADER * sdp)1553 acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
1554 {
1555 ACPI_TABLE_SRAT *srat;
1556
1557 printf(BEGIN_COMMENT);
1558 acpi_print_sdt(sdp);
1559 srat = (ACPI_TABLE_SRAT *)sdp;
1560 printf("\tTable Revision=%d\n", srat->TableRevision);
1561 acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
1562 printf(END_COMMENT);
1563 }
1564
1565 static const char *nfit_types[] = {
1566 [ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
1567 [ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
1568 [ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
1569 [ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
1570 [ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
1571 [ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
1572 [ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address",
1573 [ACPI_NFIT_TYPE_CAPABILITIES] = "Platform Capabilities"
1574 };
1575
1576
1577 static void
acpi_print_nfit(ACPI_NFIT_HEADER * nfit)1578 acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
1579 {
1580 char *uuidstr;
1581 uint32_t status;
1582
1583 ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
1584 ACPI_NFIT_MEMORY_MAP *mmap;
1585 ACPI_NFIT_INTERLEAVE *ileave;
1586 ACPI_NFIT_SMBIOS *smbios;
1587 ACPI_NFIT_CONTROL_REGION *ctlreg;
1588 ACPI_NFIT_DATA_REGION *datareg;
1589 ACPI_NFIT_FLUSH_ADDRESS *fladdr;
1590 ACPI_NFIT_CAPABILITIES *caps;
1591
1592 if (nfit->Type < nitems(nfit_types))
1593 printf("\tType=%s\n", nfit_types[nfit->Type]);
1594 else
1595 printf("\tType=%u (unknown)\n", nfit->Type);
1596 switch (nfit->Type) {
1597 case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
1598 sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
1599 printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
1600 printf("\tProximityDomain=%u\n",
1601 (u_int)sysaddr->ProximityDomain);
1602 uuid_to_string((uuid_t *)(sysaddr->RangeGuid),
1603 &uuidstr, &status);
1604 if (status != uuid_s_ok)
1605 errx(1, "uuid_to_string: status=%u", status);
1606 printf("\tRangeGuid=%s\n", uuidstr);
1607 free(uuidstr);
1608 printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
1609 printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
1610 printf("\tMemoryMapping=0x%016jx\n",
1611 (uintmax_t)sysaddr->MemoryMapping);
1612
1613 #define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_## flag, #flag)
1614
1615 printf("\tFlags=");
1616 PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
1617 PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
1618 PRINTFLAG_END();
1619
1620 #undef PRINTFLAG
1621
1622 break;
1623 case ACPI_NFIT_TYPE_MEMORY_MAP:
1624 mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
1625 printf("\tDeviceHandle=0x%x\n", (u_int)mmap->DeviceHandle);
1626 printf("\tPhysicalId=0x%04x\n", (u_int)mmap->PhysicalId);
1627 printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
1628 printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
1629 printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
1630 printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
1631 printf("\tRegionOffset=0x%016jx\n",
1632 (uintmax_t)mmap->RegionOffset);
1633 printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
1634 printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
1635 printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
1636
1637 #define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_MEM_## flag, #flag)
1638
1639 printf("\tFlags=");
1640 PRINTFLAG(mmap->Flags, SAVE_FAILED);
1641 PRINTFLAG(mmap->Flags, RESTORE_FAILED);
1642 PRINTFLAG(mmap->Flags, FLUSH_FAILED);
1643 PRINTFLAG(mmap->Flags, NOT_ARMED);
1644 PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
1645 PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
1646 PRINTFLAG(mmap->Flags, MAP_FAILED);
1647 PRINTFLAG_END();
1648
1649 #undef PRINTFLAG
1650
1651 break;
1652 case ACPI_NFIT_TYPE_INTERLEAVE:
1653 ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
1654 printf("\tInterleaveIndex=%u\n",
1655 (u_int)ileave->InterleaveIndex);
1656 printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
1657 printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
1658 /* XXX ileave->LineOffset[i] output is not supported */
1659 break;
1660 case ACPI_NFIT_TYPE_SMBIOS:
1661 smbios = (ACPI_NFIT_SMBIOS *)nfit;
1662 /* XXX smbios->Data[x] output is not supported */
1663 break;
1664 case ACPI_NFIT_TYPE_CONTROL_REGION:
1665 ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
1666 printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
1667 printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
1668 printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
1669 printf("\tRevisionId=0x%02x\n", (u_int)ctlreg->RevisionId);
1670 printf("\tSubsystemVendorId=0x%04x\n",
1671 (u_int)ctlreg->SubsystemVendorId);
1672 printf("\tSubsystemDeviceId=0x%04x\n",
1673 (u_int)ctlreg->SubsystemDeviceId);
1674 printf("\tSubsystemRevisionId=0x%02x\n",
1675 (u_int)ctlreg->SubsystemRevisionId);
1676 printf("\tValidFields=0x%02x\n", (u_int)ctlreg->ValidFields);
1677 printf("\tManufacturingLocation=0x%02x\n",
1678 (u_int)ctlreg->ManufacturingLocation);
1679 printf("\tManufacturingDate=%04x\n",
1680 (u_int)be16toh(ctlreg->ManufacturingDate));
1681 printf("\tSerialNumber=%08X\n",
1682 (u_int)be32toh(ctlreg->SerialNumber));
1683 printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
1684 printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
1685 printf("\tWindowSize=0x%016jx\n",
1686 (uintmax_t)ctlreg->WindowSize);
1687 printf("\tCommandOffset=0x%016jx\n",
1688 (uintmax_t)ctlreg->CommandOffset);
1689 printf("\tCommandSize=0x%016jx\n",
1690 (uintmax_t)ctlreg->CommandSize);
1691 printf("\tStatusOffset=0x%016jx\n",
1692 (uintmax_t)ctlreg->StatusOffset);
1693 printf("\tStatusSize=0x%016jx\n",
1694 (uintmax_t)ctlreg->StatusSize);
1695
1696 #define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_## flag, #flag)
1697
1698 printf("\tFlags=");
1699 PRINTFLAG(ctlreg->Flags, CONTROL_BUFFERED);
1700 PRINTFLAG_END();
1701
1702 #undef PRINTFLAG
1703
1704 break;
1705 case ACPI_NFIT_TYPE_DATA_REGION:
1706 datareg = (ACPI_NFIT_DATA_REGION *)nfit;
1707 printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
1708 printf("\tWindows=%u\n", (u_int)datareg->Windows);
1709 printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
1710 printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
1711 printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
1712 printf("\tStartAddress=0x%016jx\n",
1713 (uintmax_t)datareg->StartAddress);
1714 break;
1715 case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
1716 fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
1717 printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
1718 printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
1719 /* XXX fladdr->HintAddress[i] output is not supported */
1720 break;
1721 case ACPI_NFIT_TYPE_CAPABILITIES:
1722 caps = (ACPI_NFIT_CAPABILITIES *)nfit;
1723 printf("\tHighestCapability=%u\n", (u_int)caps->HighestCapability);
1724
1725 #define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_CAPABILITY_## flag, #flag)
1726
1727 printf("\tCapabilities=");
1728 PRINTFLAG(caps->Capabilities, CACHE_FLUSH);
1729 PRINTFLAG(caps->Capabilities, MEM_FLUSH);
1730 PRINTFLAG(caps->Capabilities, MEM_MIRRORING);
1731 PRINTFLAG_END();
1732
1733 #undef PRINTFLAG
1734 break;
1735 }
1736 }
1737
1738 static void
acpi_handle_nfit(ACPI_TABLE_HEADER * sdp)1739 acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
1740 {
1741 ACPI_TABLE_NFIT *nfit;
1742
1743 printf(BEGIN_COMMENT);
1744 acpi_print_sdt(sdp);
1745 nfit = (ACPI_TABLE_NFIT *)sdp;
1746 acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
1747 printf(END_COMMENT);
1748 }
1749
1750 static void
acpi_print_sdt(ACPI_TABLE_HEADER * sdp)1751 acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
1752 {
1753 printf(" ");
1754 acpi_print_string(sdp->Signature, ACPI_NAMESEG_SIZE);
1755 printf(": Length=%d, Revision=%d, Checksum=%d,\n",
1756 sdp->Length, sdp->Revision, sdp->Checksum);
1757 printf("\tOEMID=");
1758 acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
1759 printf(", OEM Table ID=");
1760 acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
1761 printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
1762 printf("\tCreator ID=");
1763 acpi_print_string(sdp->AslCompilerId, ACPI_NAMESEG_SIZE);
1764 printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
1765 }
1766
1767 static void
acpi_print_rsdt(ACPI_TABLE_HEADER * rsdp)1768 acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
1769 {
1770 ACPI_TABLE_RSDT *rsdt;
1771 ACPI_TABLE_XSDT *xsdt;
1772 int i, entries;
1773
1774 rsdt = (ACPI_TABLE_RSDT *)rsdp;
1775 xsdt = (ACPI_TABLE_XSDT *)rsdp;
1776 printf(BEGIN_COMMENT);
1777 acpi_print_sdt(rsdp);
1778 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
1779 printf("\tEntries={ ");
1780 for (i = 0; i < entries; i++) {
1781 if (i > 0)
1782 printf(", ");
1783 if (addr_size == 4)
1784 printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
1785 else
1786 printf("0x%016jx",
1787 (uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
1788 }
1789 printf(" }\n");
1790 printf(END_COMMENT);
1791 }
1792
1793 static const char *acpi_pm_profiles[] = {
1794 "Unspecified", "Desktop", "Mobile", "Workstation",
1795 "Enterprise Server", "SOHO Server", "Appliance PC"
1796 };
1797
1798 static void
acpi_print_fadt(ACPI_TABLE_HEADER * sdp)1799 acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
1800 {
1801 ACPI_TABLE_FADT *fadt;
1802 const char *pm;
1803
1804 fadt = (ACPI_TABLE_FADT *)sdp;
1805 printf(BEGIN_COMMENT);
1806 acpi_print_sdt(sdp);
1807 printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
1808 fadt->Dsdt);
1809 printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
1810 if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
1811 pm = "Reserved";
1812 else
1813 pm = acpi_pm_profiles[fadt->PreferredProfile];
1814 printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
1815 printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
1816 printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
1817 printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
1818 printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
1819 printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
1820 printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
1821 printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
1822 fadt->Pm1aEventBlock,
1823 fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
1824 if (fadt->Pm1bEventBlock != 0)
1825 printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
1826 fadt->Pm1bEventBlock,
1827 fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
1828 printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
1829 fadt->Pm1aControlBlock,
1830 fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
1831 if (fadt->Pm1bControlBlock != 0)
1832 printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
1833 fadt->Pm1bControlBlock,
1834 fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
1835 if (fadt->Pm2ControlBlock != 0)
1836 printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
1837 fadt->Pm2ControlBlock,
1838 fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
1839 printf("\tPM_TMR_BLK=0x%x-0x%x\n",
1840 fadt->PmTimerBlock,
1841 fadt->PmTimerBlock + fadt->PmTimerLength - 1);
1842 if (fadt->Gpe0Block != 0)
1843 printf("\tGPE0_BLK=0x%x-0x%x\n",
1844 fadt->Gpe0Block,
1845 fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
1846 if (fadt->Gpe1Block != 0)
1847 printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
1848 fadt->Gpe1Block,
1849 fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
1850 fadt->Gpe1Base);
1851 if (fadt->CstControl != 0)
1852 printf("\tCST_CNT=0x%x\n", fadt->CstControl);
1853 printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
1854 fadt->C2Latency, fadt->C3Latency);
1855 printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
1856 fadt->FlushSize, fadt->FlushStride);
1857 printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
1858 fadt->DutyOffset, fadt->DutyWidth);
1859 printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
1860 fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
1861
1862 #define PRINTFLAG(var, flag) printflag((var), ACPI_FADT_## flag, #flag)
1863
1864 printf("\tIAPC_BOOT_ARCH=");
1865 PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
1866 PRINTFLAG(fadt->BootFlags, 8042);
1867 PRINTFLAG(fadt->BootFlags, NO_VGA);
1868 PRINTFLAG(fadt->BootFlags, NO_MSI);
1869 PRINTFLAG(fadt->BootFlags, NO_ASPM);
1870 PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
1871 PRINTFLAG_END();
1872
1873 printf("\tFlags=");
1874 PRINTFLAG(fadt->Flags, WBINVD);
1875 PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
1876 PRINTFLAG(fadt->Flags, C1_SUPPORTED);
1877 PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
1878 PRINTFLAG(fadt->Flags, POWER_BUTTON);
1879 PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
1880 PRINTFLAG(fadt->Flags, FIXED_RTC);
1881 PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
1882 PRINTFLAG(fadt->Flags, 32BIT_TIMER);
1883 PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
1884 PRINTFLAG(fadt->Flags, RESET_REGISTER);
1885 PRINTFLAG(fadt->Flags, SEALED_CASE);
1886 PRINTFLAG(fadt->Flags, HEADLESS);
1887 PRINTFLAG(fadt->Flags, SLEEP_TYPE);
1888 PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
1889 PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
1890 PRINTFLAG(fadt->Flags, S4_RTC_VALID);
1891 PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
1892 PRINTFLAG(fadt->Flags, APIC_CLUSTER);
1893 PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
1894 PRINTFLAG(fadt->Flags, HW_REDUCED);
1895 PRINTFLAG(fadt->Flags, LOW_POWER_S0);
1896 PRINTFLAG_END();
1897
1898 #undef PRINTFLAG
1899
1900 if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
1901 printf("\tRESET_REG=");
1902 acpi_print_gas(&fadt->ResetRegister);
1903 printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
1904 }
1905 if (acpi_get_fadt_revision(fadt) > 1) {
1906 printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
1907 printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
1908 printf("\tX_PM1a_EVT_BLK=");
1909 acpi_print_gas(&fadt->XPm1aEventBlock);
1910 if (fadt->XPm1bEventBlock.Address != 0) {
1911 printf("\n\tX_PM1b_EVT_BLK=");
1912 acpi_print_gas(&fadt->XPm1bEventBlock);
1913 }
1914 printf("\n\tX_PM1a_CNT_BLK=");
1915 acpi_print_gas(&fadt->XPm1aControlBlock);
1916 if (fadt->XPm1bControlBlock.Address != 0) {
1917 printf("\n\tX_PM1b_CNT_BLK=");
1918 acpi_print_gas(&fadt->XPm1bControlBlock);
1919 }
1920 if (fadt->XPm2ControlBlock.Address != 0) {
1921 printf("\n\tX_PM2_CNT_BLK=");
1922 acpi_print_gas(&fadt->XPm2ControlBlock);
1923 }
1924 printf("\n\tX_PM_TMR_BLK=");
1925 acpi_print_gas(&fadt->XPmTimerBlock);
1926 if (fadt->XGpe0Block.Address != 0) {
1927 printf("\n\tX_GPE0_BLK=");
1928 acpi_print_gas(&fadt->XGpe0Block);
1929 }
1930 if (fadt->XGpe1Block.Address != 0) {
1931 printf("\n\tX_GPE1_BLK=");
1932 acpi_print_gas(&fadt->XGpe1Block);
1933 }
1934 printf("\n");
1935 }
1936
1937 printf(END_COMMENT);
1938 }
1939
1940 static void
acpi_print_facs(ACPI_TABLE_FACS * facs)1941 acpi_print_facs(ACPI_TABLE_FACS *facs)
1942 {
1943 printf(BEGIN_COMMENT);
1944 printf(" FACS:\tLength=%u, ", facs->Length);
1945 printf("HwSig=0x%08x, ", facs->HardwareSignature);
1946 printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
1947
1948 printf("\tGlobal_Lock=");
1949 if (facs->GlobalLock != 0) {
1950 if (facs->GlobalLock & ACPI_GLOCK_PENDING)
1951 printf("PENDING,");
1952 if (facs->GlobalLock & ACPI_GLOCK_OWNED)
1953 printf("OWNED");
1954 }
1955 printf("\n");
1956
1957 printf("\tFlags=");
1958 if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
1959 printf("S4BIOS");
1960 printf("\n");
1961
1962 if (facs->XFirmwareWakingVector != 0)
1963 printf("\tX_Firm_Wake_Vec=%016jx\n",
1964 (uintmax_t)facs->XFirmwareWakingVector);
1965 printf("\tVersion=%u\n", facs->Version);
1966
1967 printf(END_COMMENT);
1968 }
1969
1970 static void
acpi_print_dsdt(ACPI_TABLE_HEADER * dsdp)1971 acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
1972 {
1973 printf(BEGIN_COMMENT);
1974 acpi_print_sdt(dsdp);
1975 printf(END_COMMENT);
1976 }
1977
1978 int
acpi_checksum(void * p,size_t length)1979 acpi_checksum(void *p, size_t length)
1980 {
1981 uint8_t *bp;
1982 uint8_t sum;
1983
1984 bp = p;
1985 sum = 0;
1986 while (length--)
1987 sum += *bp++;
1988
1989 return (sum);
1990 }
1991
1992 static ACPI_TABLE_HEADER *
acpi_map_sdt(vm_offset_t pa)1993 acpi_map_sdt(vm_offset_t pa)
1994 {
1995 ACPI_TABLE_HEADER *sp;
1996
1997 sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
1998 sp = acpi_map_physical(pa, sp->Length);
1999 return (sp);
2000 }
2001
2002 static void
acpi_print_rsd_ptr(ACPI_TABLE_RSDP * rp)2003 acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
2004 {
2005 printf(BEGIN_COMMENT);
2006 printf(" RSD PTR: OEM=");
2007 acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
2008 printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
2009 rp->Revision);
2010 if (rp->Revision < 2) {
2011 printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
2012 rp->Checksum);
2013 } else {
2014 printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
2015 (uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
2016 rp->ExtendedChecksum);
2017 }
2018 printf(END_COMMENT);
2019 }
2020
2021 static void
acpi_handle_rsdt(ACPI_TABLE_HEADER * rsdp)2022 acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
2023 {
2024 ACPI_TABLE_HEADER *sdp;
2025 ACPI_TABLE_RSDT *rsdt;
2026 ACPI_TABLE_XSDT *xsdt;
2027 vm_offset_t addr;
2028 int entries, i;
2029
2030 acpi_print_rsdt(rsdp);
2031 rsdt = (ACPI_TABLE_RSDT *)rsdp;
2032 xsdt = (ACPI_TABLE_XSDT *)rsdp;
2033 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
2034 for (i = 0; i < entries; i++) {
2035 if (addr_size == 4)
2036 addr = le32toh(rsdt->TableOffsetEntry[i]);
2037 else
2038 addr = le64toh(xsdt->TableOffsetEntry[i]);
2039 if (addr == 0)
2040 continue;
2041 sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
2042 if (acpi_checksum(sdp, sdp->Length)) {
2043 warnx("RSDT entry %d (sig %.4s) is corrupt", i,
2044 sdp->Signature);
2045 continue;
2046 }
2047 if (!memcmp(sdp->Signature, ACPI_SIG_BERT, 4))
2048 acpi_handle_bert(sdp);
2049 else if (!memcmp(sdp->Signature, ACPI_SIG_EINJ, 4))
2050 acpi_handle_einj(sdp);
2051 else if (!memcmp(sdp->Signature, ACPI_SIG_ERST, 4))
2052 acpi_handle_erst(sdp);
2053 else if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
2054 acpi_handle_fadt(sdp);
2055 else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
2056 acpi_handle_madt(sdp);
2057 else if (!memcmp(sdp->Signature, ACPI_SIG_HEST, 4))
2058 acpi_handle_hest(sdp);
2059 else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
2060 acpi_handle_hpet(sdp);
2061 else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
2062 acpi_handle_ecdt(sdp);
2063 else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
2064 acpi_handle_mcfg(sdp);
2065 else if (!memcmp(sdp->Signature, ACPI_SIG_SLIT, 4))
2066 acpi_handle_slit(sdp);
2067 else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
2068 acpi_handle_srat(sdp);
2069 else if (!memcmp(sdp->Signature, ACPI_SIG_TCPA, 4))
2070 acpi_handle_tcpa(sdp);
2071 else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
2072 acpi_handle_dmar(sdp);
2073 else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
2074 acpi_handle_nfit(sdp);
2075 else if (!memcmp(sdp->Signature, ACPI_SIG_WDDT, 4))
2076 acpi_handle_wddt(sdp);
2077 else if (!memcmp(sdp->Signature, ACPI_SIG_LPIT, 4))
2078 acpi_handle_lpit(sdp);
2079 else if (!memcmp(sdp->Signature, ACPI_SIG_TPM2, 4))
2080 acpi_handle_tpm2(sdp);
2081 else {
2082 printf(BEGIN_COMMENT);
2083 acpi_print_sdt(sdp);
2084 printf(END_COMMENT);
2085 }
2086 }
2087 }
2088
2089 ACPI_TABLE_HEADER *
sdt_load_devmem(void)2090 sdt_load_devmem(void)
2091 {
2092 ACPI_TABLE_RSDP *rp;
2093 ACPI_TABLE_HEADER *rsdp;
2094
2095 rp = acpi_find_rsd_ptr();
2096 if (!rp)
2097 errx(1, "Can't find ACPI information");
2098
2099 if (tflag)
2100 acpi_print_rsd_ptr(rp);
2101 if (rp->Revision < 2) {
2102 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
2103 if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
2104 acpi_checksum(rsdp, rsdp->Length) != 0)
2105 errx(1, "RSDT is corrupted");
2106 addr_size = sizeof(uint32_t);
2107 } else {
2108 rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
2109 if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
2110 acpi_checksum(rsdp, rsdp->Length) != 0)
2111 errx(1, "XSDT is corrupted");
2112 addr_size = sizeof(uint64_t);
2113 }
2114 return (rsdp);
2115 }
2116
2117 /* Write the DSDT to a file, concatenating any SSDTs (if present). */
2118 static int
write_dsdt(int fd,ACPI_TABLE_HEADER * rsdt,ACPI_TABLE_HEADER * dsdt)2119 write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
2120 {
2121 ACPI_TABLE_HEADER sdt;
2122 ACPI_TABLE_HEADER *ssdt;
2123 uint8_t sum;
2124
2125 /* Create a new checksum to account for the DSDT and any SSDTs. */
2126 sdt = *dsdt;
2127 if (rsdt != NULL) {
2128 sdt.Checksum = 0;
2129 sum = acpi_checksum(dsdt + 1, dsdt->Length -
2130 sizeof(ACPI_TABLE_HEADER));
2131 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
2132 while (ssdt != NULL) {
2133 sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
2134 sum += acpi_checksum(ssdt + 1,
2135 ssdt->Length - sizeof(ACPI_TABLE_HEADER));
2136 ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
2137 }
2138 sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
2139 sdt.Checksum -= sum;
2140 }
2141
2142 /* Write out the DSDT header and body. */
2143 write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
2144 write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
2145
2146 /* Write out any SSDTs (if present.) */
2147 if (rsdt != NULL) {
2148 ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
2149 while (ssdt != NULL) {
2150 write(fd, ssdt + 1, ssdt->Length -
2151 sizeof(ACPI_TABLE_HEADER));
2152 ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
2153 }
2154 }
2155 return (0);
2156 }
2157
2158 void
dsdt_save_file(char * outfile,ACPI_TABLE_HEADER * rsdt,ACPI_TABLE_HEADER * dsdp)2159 dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
2160 {
2161 int fd;
2162 mode_t mode;
2163
2164 assert(outfile != NULL);
2165 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
2166 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
2167 if (fd == -1) {
2168 perror("dsdt_save_file");
2169 return;
2170 }
2171 write_dsdt(fd, rsdt, dsdp);
2172 close(fd);
2173 }
2174
2175 void
aml_disassemble(ACPI_TABLE_HEADER * rsdt,ACPI_TABLE_HEADER * dsdp)2176 aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
2177 {
2178 char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
2179 const char *iname = "/acpdump.din";
2180 const char *oname = "/acpdump.dsl";
2181 const char *tmpdir;
2182 FILE *fp;
2183 size_t len;
2184 int fd, status;
2185 pid_t pid;
2186
2187 tmpdir = getenv("TMPDIR");
2188 if (tmpdir == NULL)
2189 tmpdir = _PATH_TMP;
2190 if (realpath(tmpdir, buf) == NULL) {
2191 perror("realpath tmp dir");
2192 return;
2193 }
2194 len = sizeof(wrkdir) - strlen(iname);
2195 if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
2196 fprintf(stderr, "$TMPDIR too long\n");
2197 return;
2198 }
2199 if (mkdtemp(wrkdir) == NULL) {
2200 perror("mkdtemp tmp working dir");
2201 return;
2202 }
2203 len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
2204 assert(len <= sizeof(tmpstr) - 1);
2205 fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
2206 if (fd < 0) {
2207 perror("iasl tmp file");
2208 return;
2209 }
2210 write_dsdt(fd, rsdt, dsdp);
2211 close(fd);
2212
2213 /* Run iasl -d on the temp file */
2214 if ((pid = fork()) == 0) {
2215 close(STDOUT_FILENO);
2216 if (vflag == 0)
2217 close(STDERR_FILENO);
2218 execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
2219 err(1, "exec");
2220 }
2221 if (pid > 0)
2222 wait(&status);
2223 if (unlink(tmpstr) < 0) {
2224 perror("unlink");
2225 goto out;
2226 }
2227 if (pid < 0) {
2228 perror("fork");
2229 goto out;
2230 }
2231 if (status != 0) {
2232 fprintf(stderr, "iast exit status = %d\n", status);
2233 }
2234
2235 /* Dump iasl's output to stdout */
2236 len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
2237 assert(len <= sizeof(tmpstr) - 1);
2238 fp = fopen(tmpstr, "r");
2239 if (unlink(tmpstr) < 0) {
2240 perror("unlink");
2241 goto out;
2242 }
2243 if (fp == NULL) {
2244 perror("iasl tmp file (read)");
2245 goto out;
2246 }
2247 while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
2248 fwrite(buf, 1, len, stdout);
2249 fclose(fp);
2250
2251 out:
2252 if (rmdir(wrkdir) < 0)
2253 perror("rmdir");
2254 }
2255
2256 void
sdt_print_all(ACPI_TABLE_HEADER * rsdp)2257 sdt_print_all(ACPI_TABLE_HEADER *rsdp)
2258 {
2259 acpi_handle_rsdt(rsdp);
2260 }
2261
2262 /* Fetch a table matching the given signature via the RSDT. */
2263 ACPI_TABLE_HEADER *
sdt_from_rsdt(ACPI_TABLE_HEADER * rsdp,const char * sig,ACPI_TABLE_HEADER * last)2264 sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
2265 {
2266 ACPI_TABLE_HEADER *sdt;
2267 ACPI_TABLE_RSDT *rsdt;
2268 ACPI_TABLE_XSDT *xsdt;
2269 vm_offset_t addr;
2270 int entries, i;
2271
2272 rsdt = (ACPI_TABLE_RSDT *)rsdp;
2273 xsdt = (ACPI_TABLE_XSDT *)rsdp;
2274 entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
2275 for (i = 0; i < entries; i++) {
2276 if (addr_size == 4)
2277 addr = le32toh(rsdt->TableOffsetEntry[i]);
2278 else
2279 addr = le64toh(xsdt->TableOffsetEntry[i]);
2280 if (addr == 0)
2281 continue;
2282 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
2283 if (last != NULL) {
2284 if (sdt == last)
2285 last = NULL;
2286 continue;
2287 }
2288 if (memcmp(sdt->Signature, sig, strlen(sig)))
2289 continue;
2290 if (acpi_checksum(sdt, sdt->Length))
2291 errx(1, "RSDT entry %d is corrupt", i);
2292 return (sdt);
2293 }
2294
2295 return (NULL);
2296 }
2297
2298 ACPI_TABLE_HEADER *
dsdt_from_fadt(ACPI_TABLE_FADT * fadt)2299 dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
2300 {
2301 ACPI_TABLE_HEADER *sdt;
2302
2303 /* Use the DSDT address if it is version 1, otherwise use XDSDT. */
2304 if (acpi_get_fadt_revision(fadt) == 1)
2305 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
2306 else
2307 sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
2308 if (acpi_checksum(sdt, sdt->Length))
2309 errx(1, "DSDT is corrupt\n");
2310 return (sdt);
2311 }
2312