Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/acpi/acpidump/acpi.c
107108 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 1998 Doug Rabson
5
* Copyright (c) 2000 Mitsuru IWASAKI <[email protected]>
6
* Copyright (c) 2020 Alexander Motin <[email protected]>
7
* Copyright (c) 2024 The FreeBSD Foundation
8
* All rights reserved.
9
*
10
* Portions of this software were developed by Konstantin Belousov
11
* under sponsorship from the FreeBSD Foundation.
12
*
13
* Redistribution and use in source and binary forms, with or without
14
* modification, are permitted provided that the following conditions
15
* are met:
16
* 1. Redistributions of source code must retain the above copyright
17
* notice, this list of conditions and the following disclaimer.
18
* 2. Redistributions in binary form must reproduce the above copyright
19
* notice, this list of conditions and the following disclaimer in the
20
* documentation and/or other materials provided with the distribution.
21
*
22
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
* SUCH DAMAGE.
33
*/
34
35
#include <sys/param.h>
36
#include <sys/endian.h>
37
#include <sys/stat.h>
38
#include <sys/wait.h>
39
#include <assert.h>
40
#include <err.h>
41
#include <fcntl.h>
42
#include <paths.h>
43
#include <stdbool.h>
44
#include <stdio.h>
45
#include <stdint.h>
46
#include <stdlib.h>
47
#include <string.h>
48
#include <unistd.h>
49
#include <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 int acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
59
static void acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
60
static void acpi_print_cpu(u_char cpu_id);
61
static void acpi_print_cpu_uid(uint32_t uid, char *uid_string);
62
static void acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
63
static void acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
64
uint64_t apic_addr);
65
static void acpi_print_mps_flags(uint16_t flags);
66
static void acpi_print_intr(uint32_t intr, uint16_t mps_flags);
67
static void acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
68
static void acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
69
static void acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
70
static void acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
71
static void acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
72
static void acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
73
static void acpi_handle_slit(ACPI_TABLE_HEADER *sdp);
74
static void acpi_handle_wddt(ACPI_TABLE_HEADER *sdp);
75
static void acpi_handle_lpit(ACPI_TABLE_HEADER *sdp);
76
static void acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
77
uint32_t flags);
78
static void acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
79
static void acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
80
static void acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
81
static void acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp);
82
static void acpi_print_nfit(ACPI_NFIT_HEADER *nfit);
83
static void acpi_handle_nfit(ACPI_TABLE_HEADER *sdp);
84
static void acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
85
static void acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
86
static void acpi_print_facs(ACPI_TABLE_FACS *facs);
87
static void acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
88
static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
89
static void acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
90
static void acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp, const char *elm);
91
static void acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
92
void (*action)(ACPI_SUBTABLE_HEADER *));
93
static void acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
94
void (*action)(ACPI_NFIT_HEADER *));
95
96
/* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
97
static int addr_size;
98
99
/* Strings used in the TCPA table */
100
static const char *tcpa_event_type_strings[] = {
101
"PREBOOT Certificate",
102
"POST Code",
103
"Unused",
104
"No Action",
105
"Separator",
106
"Action",
107
"Event Tag",
108
"S-CRTM Contents",
109
"S-CRTM Version",
110
"CPU Microcode",
111
"Platform Config Flags",
112
"Table of Devices",
113
"Compact Hash",
114
"IPL",
115
"IPL Partition Data",
116
"Non-Host Code",
117
"Non-Host Config",
118
"Non-Host Info"
119
};
120
121
static const char *TCPA_pcclient_strings[] = {
122
"<undefined>",
123
"SMBIOS",
124
"BIS Certificate",
125
"POST BIOS ROM Strings",
126
"ESCD",
127
"CMOS",
128
"NVRAM",
129
"Option ROM Execute",
130
"Option ROM Configurateion",
131
"<undefined>",
132
"Option ROM Microcode Update ",
133
"S-CRTM Version String",
134
"S-CRTM Contents",
135
"POST Contents",
136
"Table of Devices",
137
};
138
139
#define PRINTFLAG_END() printflag_end()
140
141
static char pf_sep = '{';
142
143
static void
144
printflag_end(void)
145
{
146
147
if (pf_sep != '{') {
148
printf("}");
149
pf_sep = '{';
150
}
151
printf("\n");
152
}
153
154
static void
155
printflag(uint64_t var, uint64_t mask, const char *name)
156
{
157
158
if (var & mask) {
159
printf("%c%s", pf_sep, name);
160
pf_sep = ',';
161
}
162
}
163
164
static void
165
printfield(uint64_t var, int lbit, int hbit, const char *name)
166
{
167
uint64_t mask;
168
int len;
169
170
len = hbit - lbit + 1;
171
mask = ((1 << (len + 1)) - 1) << lbit;
172
printf("%c%s=%#jx", pf_sep, name, (uintmax_t)((var & mask) >> lbit));
173
pf_sep = ',';
174
}
175
176
static void
177
acpi_print_string(char *s, size_t length)
178
{
179
int c;
180
181
/* Trim trailing spaces and NULLs */
182
while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
183
length--;
184
185
while (length--) {
186
c = *s++;
187
putchar(c);
188
}
189
}
190
191
static void
192
acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
193
{
194
switch(gas->SpaceId) {
195
case ACPI_GAS_MEMORY:
196
printf("0x%016jx:%u[%u] (Memory)", (uintmax_t)gas->Address,
197
gas->BitOffset, gas->BitWidth);
198
break;
199
case ACPI_GAS_IO:
200
printf("0x%02jx:%u[%u] (IO)", (uintmax_t)gas->Address,
201
gas->BitOffset, gas->BitWidth);
202
break;
203
case ACPI_GAS_PCI:
204
printf("%x:%x+0x%x:%u[%u] (PCI)", (uint16_t)(gas->Address >> 32),
205
(uint16_t)((gas->Address >> 16) & 0xffff),
206
(uint16_t)gas->Address, gas->BitOffset, gas->BitWidth);
207
break;
208
/* XXX How to handle these below? */
209
case ACPI_GAS_EMBEDDED:
210
printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
211
gas->BitOffset, gas->BitWidth);
212
break;
213
case ACPI_GAS_SMBUS:
214
printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
215
gas->BitOffset, gas->BitWidth);
216
break;
217
case ACPI_GAS_CMOS:
218
case ACPI_GAS_PCIBAR:
219
case ACPI_GAS_DATATABLE:
220
case ACPI_GAS_FIXED:
221
default:
222
printf("0x%016jx (?)", (uintmax_t)gas->Address);
223
break;
224
}
225
}
226
227
/* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
228
static int
229
acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt __unused)
230
{
231
int fadt_revision;
232
233
/* Set the FADT revision separately from the RSDP version. */
234
if (addr_size == 8) {
235
fadt_revision = 2;
236
237
#if defined(__i386__)
238
/*
239
* A few systems (e.g., IBM T23) have an RSDP that claims
240
* revision 2 but the 64 bit addresses are invalid. If
241
* revision 2 and the 32 bit address is non-zero but the
242
* 32 and 64 bit versions don't match, prefer the 32 bit
243
* version for all subsequent tables.
244
*
245
* The only known ACPI systems this affects are early
246
* implementations on 32-bit x86. Because of this limit the
247
* workaround to i386.
248
*/
249
if (fadt->Facs != 0 &&
250
(fadt->XFacs & 0xffffffff) != fadt->Facs)
251
fadt_revision = 1;
252
#endif
253
} else
254
fadt_revision = 1;
255
return (fadt_revision);
256
}
257
258
static void
259
acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
260
{
261
ACPI_TABLE_HEADER *dsdp;
262
ACPI_TABLE_FACS *facs;
263
ACPI_TABLE_FADT *fadt;
264
vm_offset_t addr;
265
int fadt_revision;
266
267
fadt = (ACPI_TABLE_FADT *)sdp;
268
acpi_print_fadt(sdp);
269
270
fadt_revision = acpi_get_fadt_revision(fadt);
271
if (fadt_revision == 1)
272
addr = fadt->Facs;
273
else
274
addr = fadt->XFacs;
275
if (addr != 0) {
276
facs = (ACPI_TABLE_FACS *)acpi_map_sdt(addr);
277
278
if (memcmp(facs->Signature, ACPI_SIG_FACS, ACPI_NAMESEG_SIZE) != 0 ||
279
facs->Length < 64)
280
errx(1, "FACS is corrupt");
281
acpi_print_facs(facs);
282
}
283
284
if (fadt_revision == 1)
285
dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
286
else
287
dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
288
if (acpi_checksum(dsdp, dsdp->Length))
289
errx(1, "DSDT is corrupt");
290
acpi_print_dsdt(dsdp);
291
}
292
293
static void
294
acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
295
void (*action)(ACPI_SUBTABLE_HEADER *))
296
{
297
ACPI_SUBTABLE_HEADER *subtable;
298
char *end;
299
300
subtable = first;
301
end = (char *)table + table->Length;
302
while ((char *)subtable < end) {
303
printf("\n");
304
if (subtable->Length < sizeof(ACPI_SUBTABLE_HEADER)) {
305
warnx("invalid subtable length %u", subtable->Length);
306
return;
307
}
308
action(subtable);
309
subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
310
subtable->Length);
311
}
312
}
313
314
static void
315
acpi_walk_nfit(ACPI_TABLE_HEADER *table, void *first,
316
void (*action)(ACPI_NFIT_HEADER *))
317
{
318
ACPI_NFIT_HEADER *subtable;
319
char *end;
320
321
subtable = first;
322
end = (char *)table + table->Length;
323
while ((char *)subtable < end) {
324
printf("\n");
325
if (subtable->Length < sizeof(ACPI_NFIT_HEADER)) {
326
warnx("invalid subtable length %u", subtable->Length);
327
return;
328
}
329
action(subtable);
330
subtable = (ACPI_NFIT_HEADER *)((char *)subtable +
331
subtable->Length);
332
}
333
}
334
335
static void
336
acpi_print_cpu(u_char cpu_id)
337
{
338
339
printf("\tACPI CPU=");
340
if (cpu_id == 0xff)
341
printf("ALL\n");
342
else
343
printf("%d\n", (u_int)cpu_id);
344
}
345
346
static void
347
acpi_print_cpu_uid(uint32_t uid, char *uid_string)
348
{
349
350
printf("\tUID=%d", uid);
351
if (uid_string != NULL)
352
printf(" (%s)", uid_string);
353
printf("\n");
354
}
355
356
static void
357
acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
358
{
359
360
printf("\tFlags={");
361
if (flags & ACPI_MADT_ENABLED)
362
printf("ENABLED");
363
else
364
printf("DISABLED");
365
printf("}\n");
366
printf("\tAPIC ID=%d\n", apic_id);
367
}
368
369
static void
370
acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
371
{
372
373
printf("\tAPIC ID=%d\n", apic_id);
374
printf("\tINT BASE=%d\n", int_base);
375
printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
376
}
377
378
static void
379
acpi_print_mps_flags(uint16_t flags)
380
{
381
382
printf("\tFlags={Polarity=");
383
switch (flags & ACPI_MADT_POLARITY_MASK) {
384
case ACPI_MADT_POLARITY_CONFORMS:
385
printf("conforming");
386
break;
387
case ACPI_MADT_POLARITY_ACTIVE_HIGH:
388
printf("active-hi");
389
break;
390
case ACPI_MADT_POLARITY_ACTIVE_LOW:
391
printf("active-lo");
392
break;
393
default:
394
printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
395
break;
396
}
397
printf(", Trigger=");
398
switch (flags & ACPI_MADT_TRIGGER_MASK) {
399
case ACPI_MADT_TRIGGER_CONFORMS:
400
printf("conforming");
401
break;
402
case ACPI_MADT_TRIGGER_EDGE:
403
printf("edge");
404
break;
405
case ACPI_MADT_TRIGGER_LEVEL:
406
printf("level");
407
break;
408
default:
409
printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
410
}
411
printf("}\n");
412
}
413
414
static void
415
acpi_print_gicc_flags(uint32_t flags)
416
{
417
418
printf("\tFlags={Performance intr=");
419
if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
420
printf("edge");
421
else
422
printf("level");
423
printf(", VGIC intr=");
424
if (flags & ACPI_MADT_VGIC_IRQ_MODE)
425
printf("edge");
426
else
427
printf("level");
428
printf("}\n");
429
}
430
431
static void
432
acpi_print_intr(uint32_t intr, uint16_t mps_flags)
433
{
434
435
printf("\tINTR=%d\n", intr);
436
acpi_print_mps_flags(mps_flags);
437
}
438
439
static void
440
acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
441
{
442
443
printf("\tLINT Pin=%d\n", lint);
444
acpi_print_mps_flags(mps_flags);
445
}
446
447
static const char *apic_types[] = {
448
[ACPI_MADT_TYPE_LOCAL_APIC] = "Local APIC",
449
[ACPI_MADT_TYPE_IO_APIC] = "IO APIC",
450
[ACPI_MADT_TYPE_INTERRUPT_OVERRIDE] = "INT Override",
451
[ACPI_MADT_TYPE_NMI_SOURCE] = "NMI",
452
[ACPI_MADT_TYPE_LOCAL_APIC_NMI] = "Local APIC NMI",
453
[ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE] = "Local APIC Override",
454
[ACPI_MADT_TYPE_IO_SAPIC] = "IO SAPIC",
455
[ACPI_MADT_TYPE_LOCAL_SAPIC] = "Local SAPIC",
456
[ACPI_MADT_TYPE_INTERRUPT_SOURCE] = "Platform Interrupt",
457
[ACPI_MADT_TYPE_LOCAL_X2APIC] = "Local X2APIC",
458
[ACPI_MADT_TYPE_LOCAL_X2APIC_NMI] = "Local X2APIC NMI",
459
[ACPI_MADT_TYPE_GENERIC_INTERRUPT] = "GIC CPU Interface Structure",
460
[ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR] = "GIC Distributor Structure",
461
[ACPI_MADT_TYPE_GENERIC_MSI_FRAME] = "GICv2m MSI Frame",
462
[ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR] = "GIC Redistributor Structure",
463
[ACPI_MADT_TYPE_GENERIC_TRANSLATOR] = "GIC ITS Structure"
464
};
465
466
static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
467
"Corrected Platform Error" };
468
469
static void
470
acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
471
{
472
ACPI_MADT_LOCAL_APIC *lapic;
473
ACPI_MADT_IO_APIC *ioapic;
474
ACPI_MADT_INTERRUPT_OVERRIDE *over;
475
ACPI_MADT_NMI_SOURCE *nmi;
476
ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
477
ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
478
ACPI_MADT_IO_SAPIC *iosapic;
479
ACPI_MADT_LOCAL_SAPIC *lsapic;
480
ACPI_MADT_INTERRUPT_SOURCE *isrc;
481
ACPI_MADT_LOCAL_X2APIC *x2apic;
482
ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
483
ACPI_MADT_GENERIC_INTERRUPT *gicc;
484
ACPI_MADT_GENERIC_DISTRIBUTOR *gicd;
485
ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr;
486
ACPI_MADT_GENERIC_TRANSLATOR *gict;
487
488
if (mp->Type < nitems(apic_types))
489
printf("\tType=%s\n", apic_types[mp->Type]);
490
else
491
printf("\tType=%d (unknown)\n", mp->Type);
492
switch (mp->Type) {
493
case ACPI_MADT_TYPE_LOCAL_APIC:
494
lapic = (ACPI_MADT_LOCAL_APIC *)mp;
495
acpi_print_cpu(lapic->ProcessorId);
496
acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
497
break;
498
case ACPI_MADT_TYPE_IO_APIC:
499
ioapic = (ACPI_MADT_IO_APIC *)mp;
500
acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
501
ioapic->Address);
502
break;
503
case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
504
over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
505
printf("\tBUS=%d\n", (u_int)over->Bus);
506
printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
507
acpi_print_intr(over->GlobalIrq, over->IntiFlags);
508
break;
509
case ACPI_MADT_TYPE_NMI_SOURCE:
510
nmi = (ACPI_MADT_NMI_SOURCE *)mp;
511
acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
512
break;
513
case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
514
lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
515
acpi_print_cpu(lapic_nmi->ProcessorId);
516
acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
517
break;
518
case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
519
lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
520
printf("\tLocal APIC ADDR=0x%016jx\n",
521
(uintmax_t)lapic_over->Address);
522
break;
523
case ACPI_MADT_TYPE_IO_SAPIC:
524
iosapic = (ACPI_MADT_IO_SAPIC *)mp;
525
acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
526
iosapic->Address);
527
break;
528
case ACPI_MADT_TYPE_LOCAL_SAPIC:
529
lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
530
acpi_print_cpu(lsapic->ProcessorId);
531
acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
532
printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
533
if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
534
acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
535
break;
536
case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
537
isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
538
if (isrc->Type < nitems(platform_int_types))
539
printf("\tType=%s\n", platform_int_types[isrc->Type]);
540
else
541
printf("\tType=%d (unknown)\n", isrc->Type);
542
printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
543
printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
544
printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
545
acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
546
break;
547
case ACPI_MADT_TYPE_LOCAL_X2APIC:
548
x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
549
acpi_print_cpu_uid(x2apic->Uid, NULL);
550
acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
551
break;
552
case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
553
x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
554
acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
555
acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
556
break;
557
case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
558
gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp;
559
acpi_print_cpu_uid(gicc->Uid, NULL);
560
printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber);
561
acpi_print_gicc_flags(gicc->Flags);
562
printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion);
563
printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt);
564
printf("\tParked ADDR=%016jx\n",
565
(uintmax_t)gicc->ParkedAddress);
566
printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress);
567
printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress);
568
printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress);
569
printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt);
570
printf("\tGICR ADDR=%016jx\n",
571
(uintmax_t)gicc->GicrBaseAddress);
572
printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr);
573
printf("\tEfficiency Class=%d\n", (u_int)gicc->EfficiencyClass);
574
printf("\tSPE INTR=%d\n", gicc->SpeInterrupt);
575
break;
576
case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
577
gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp;
578
printf("\tGIC ID=%d\n", (u_int)gicd->GicId);
579
printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress);
580
printf("\tVector Base=%d\n", gicd->GlobalIrqBase);
581
printf("\tGIC VERSION=%d\n", (u_int)gicd->Version);
582
break;
583
case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR:
584
gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp;
585
printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress);
586
printf("\tLength=%08x\n", gicr->Length);
587
break;
588
case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
589
gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp;
590
printf("\tGIC ITS ID=%d\n", gict->TranslationId);
591
printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress);
592
break;
593
}
594
}
595
596
static void
597
acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
598
{
599
ACPI_TABLE_MADT *madt;
600
601
printf(BEGIN_COMMENT);
602
acpi_print_sdt(sdp);
603
madt = (ACPI_TABLE_MADT *)sdp;
604
printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
605
printf("\tFlags={");
606
if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
607
printf("PC-AT");
608
printf("}\n");
609
acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
610
printf(END_COMMENT);
611
}
612
613
static void
614
acpi_handle_bert(ACPI_TABLE_HEADER *sdp)
615
{
616
ACPI_TABLE_BERT *bert;
617
618
printf(BEGIN_COMMENT);
619
acpi_print_sdt(sdp);
620
bert = (ACPI_TABLE_BERT *)sdp;
621
printf("\tRegionLength=%d\n", bert->RegionLength);
622
printf("\tAddress=0x%016jx\n", bert->Address);
623
printf(END_COMMENT);
624
}
625
626
static const char *
627
einj_action(UINT8 Action)
628
{
629
static char buf[32];
630
631
#define ACTION(name) \
632
case __CONCAT(ACPI_EINJ_, name): \
633
return (__STRING(name))
634
#define ACTIONV2(name) \
635
case __CONCAT(ACPI_EINJV2_, name): \
636
return (__XSTRING(__CONCAT(V2_, name)))
637
638
switch (Action) {
639
ACTION(BEGIN_OPERATION);
640
ACTION(GET_TRIGGER_TABLE);
641
ACTION(SET_ERROR_TYPE);
642
ACTION(GET_ERROR_TYPE);
643
ACTION(END_OPERATION);
644
ACTION(EXECUTE_OPERATION);
645
ACTION(CHECK_BUSY_STATUS);
646
ACTION(GET_COMMAND_STATUS);
647
ACTION(SET_ERROR_TYPE_WITH_ADDRESS);
648
ACTION(GET_EXECUTE_TIMINGS);
649
ACTIONV2(GET_ERROR_TYPE);
650
ACTION(TRIGGER_ERROR);
651
default:
652
snprintf(buf, sizeof(buf), "UNKNOWN (%#x)", Action);
653
return (buf);
654
}
655
656
#undef ACTION
657
#undef ACTIONV2
658
}
659
660
static const char *
661
einj_instruction(UINT8 Instruction)
662
{
663
static char buf[32];
664
665
#define INSTRUCTION(name) \
666
case __CONCAT(ACPI_EINJ_, name): \
667
return (__STRING(name))
668
669
switch (Instruction) {
670
INSTRUCTION(READ_REGISTER);
671
INSTRUCTION(READ_REGISTER_VALUE);
672
INSTRUCTION(WRITE_REGISTER);
673
INSTRUCTION(WRITE_REGISTER_VALUE);
674
INSTRUCTION(NOOP);
675
INSTRUCTION(FLUSH_CACHELINE);
676
default:
677
snprintf(buf, sizeof(buf), "UNKNOWN (%#x)", Instruction);
678
return (buf);
679
}
680
681
#undef INSTRUCTION
682
}
683
684
static void
685
acpi_print_einj_entry(ACPI_EINJ_ENTRY *entry)
686
{
687
ACPI_WHEA_HEADER *w = &entry->WheaHeader;
688
689
printf("\n\tAction=%s\n", einj_action(w->Action));
690
printf("\tInstruction=%s\n", einj_instruction(w->Instruction));
691
if (w->Flags != 0) {
692
printf("\tFlags=%02x", w->Flags);
693
if (w->Flags & 0x1)
694
printf("<PRESERVE_REGISTER>");
695
printf("\n");
696
}
697
printf("\tRegisterRegion=");
698
acpi_print_gas(&w->RegisterRegion);
699
printf("\n");
700
switch (w->Instruction) {
701
case ACPI_EINJ_READ_REGISTER:
702
case ACPI_EINJ_WRITE_REGISTER:
703
case ACPI_EINJ_NOOP:
704
case ACPI_EINJ_FLUSH_CACHELINE:
705
break;
706
default:
707
printf("\tValue=0x%016jx\n", w->Value);
708
}
709
printf("\tMask=0x%016jx\n", w->Mask);
710
}
711
712
static void
713
acpi_handle_einj(ACPI_TABLE_HEADER *sdp)
714
{
715
ACPI_TABLE_EINJ *einj;
716
ACPI_EINJ_ENTRY *w;
717
u_int i;
718
719
printf(BEGIN_COMMENT);
720
acpi_print_sdt(sdp);
721
einj = (ACPI_TABLE_EINJ *)sdp;
722
printf("\tHeaderLength=%d\n", einj->HeaderLength);
723
printf("\tFlags=0x%02x\n", einj->Flags);
724
printf("\tEntries=%d\n", einj->Entries);
725
w = (ACPI_EINJ_ENTRY *)(einj + 1);
726
for (i = 0; i < MIN(einj->Entries, (sdp->Length -
727
sizeof(ACPI_TABLE_EINJ)) / sizeof(ACPI_EINJ_ENTRY)); i++)
728
acpi_print_einj_entry(w + i);
729
printf(END_COMMENT);
730
}
731
732
static const char *
733
erst_action(UINT8 Action)
734
{
735
static char buf[32];
736
737
#define ACTION(name) \
738
case __CONCAT(ACPI_ERST_, name): \
739
return (__STRING(name))
740
741
switch (Action) {
742
ACTION(BEGIN_WRITE);
743
ACTION(BEGIN_READ);
744
ACTION(BEGIN_CLEAR);
745
ACTION(END);
746
ACTION(SET_RECORD_OFFSET);
747
ACTION(EXECUTE_OPERATION);
748
ACTION(CHECK_BUSY_STATUS);
749
ACTION(GET_COMMAND_STATUS);
750
ACTION(GET_RECORD_ID);
751
ACTION(SET_RECORD_ID);
752
ACTION(GET_RECORD_COUNT);
753
ACTION(BEGIN_DUMMY_WRIITE);
754
ACTION(GET_ERROR_RANGE);
755
ACTION(GET_ERROR_LENGTH);
756
ACTION(GET_ERROR_ATTRIBUTES);
757
ACTION(EXECUTE_TIMINGS);
758
default:
759
snprintf(buf, sizeof(buf), "UNKNOWN (%#x)", Action);
760
return (buf);
761
}
762
763
#undef ACTION
764
}
765
766
static const char *
767
erst_instruction(UINT8 Instruction)
768
{
769
static char buf[32];
770
771
#define INSTRUCTION(name) \
772
case __CONCAT(ACPI_ERST_, name): \
773
return (__STRING(name))
774
775
switch (Instruction) {
776
INSTRUCTION(READ_REGISTER);
777
INSTRUCTION(READ_REGISTER_VALUE);
778
INSTRUCTION(WRITE_REGISTER);
779
INSTRUCTION(WRITE_REGISTER_VALUE);
780
INSTRUCTION(NOOP);
781
INSTRUCTION(LOAD_VAR1);
782
INSTRUCTION(LOAD_VAR2);
783
INSTRUCTION(STORE_VAR1);
784
INSTRUCTION(ADD);
785
INSTRUCTION(SUBTRACT);
786
INSTRUCTION(ADD_VALUE);
787
INSTRUCTION(SUBTRACT_VALUE);
788
INSTRUCTION(STALL);
789
INSTRUCTION(STALL_WHILE_TRUE);
790
INSTRUCTION(SKIP_NEXT_IF_TRUE);
791
INSTRUCTION(GOTO);
792
INSTRUCTION(SET_SRC_ADDRESS_BASE);
793
INSTRUCTION(SET_DST_ADDRESS_BASE);
794
INSTRUCTION(MOVE_DATA);
795
default:
796
snprintf(buf, sizeof(buf), "UNKNOWN (%#x)", Instruction);
797
return (buf);
798
}
799
800
#undef INSTRUCTION
801
}
802
803
static void
804
acpi_print_erst_entry(ACPI_ERST_ENTRY *entry)
805
{
806
ACPI_WHEA_HEADER *w = &entry->WheaHeader;
807
808
printf("\n\tAction=%s\n", erst_action(w->Action));
809
printf("\tInstruction=%s\n", erst_instruction(w->Instruction));
810
if (w->Flags != 0) {
811
printf("\tFlags=%02x", w->Flags);
812
if (w->Flags & 0x1)
813
printf("<PRESERVE_REGISTER>");
814
printf("\n");
815
}
816
printf("\tRegisterRegion=");
817
acpi_print_gas(&w->RegisterRegion);
818
printf("\n");
819
switch (w->Instruction) {
820
case ACPI_ERST_READ_REGISTER:
821
case ACPI_ERST_WRITE_REGISTER:
822
case ACPI_ERST_NOOP:
823
case ACPI_ERST_LOAD_VAR1:
824
case ACPI_ERST_LOAD_VAR2:
825
case ACPI_ERST_STORE_VAR1:
826
case ACPI_ERST_ADD:
827
case ACPI_ERST_SUBTRACT:
828
case ACPI_ERST_SET_SRC_ADDRESS_BASE:
829
case ACPI_ERST_SET_DST_ADDRESS_BASE:
830
case ACPI_ERST_MOVE_DATA:
831
break;
832
default:
833
printf("\tValue=0x%016jx\n", w->Value);
834
break;
835
}
836
printf("\tMask=0x%016jx\n", w->Mask);
837
}
838
839
static void
840
acpi_handle_erst(ACPI_TABLE_HEADER *sdp)
841
{
842
ACPI_TABLE_ERST *erst;
843
ACPI_ERST_ENTRY *w;
844
u_int i;
845
846
printf(BEGIN_COMMENT);
847
acpi_print_sdt(sdp);
848
erst = (ACPI_TABLE_ERST *)sdp;
849
printf("\tHeaderLength=%d\n", erst->HeaderLength);
850
printf("\tEntries=%d\n", erst->Entries);
851
w = (ACPI_ERST_ENTRY *)(erst + 1);
852
for (i = 0; i < MIN(erst->Entries, (sdp->Length -
853
sizeof(ACPI_TABLE_ERST)) / sizeof(ACPI_ERST_ENTRY)); i++)
854
acpi_print_erst_entry(w + i);
855
printf(END_COMMENT);
856
}
857
858
static void
859
acpi_print_hest_bank(ACPI_HEST_IA_ERROR_BANK *b)
860
{
861
862
printf("\tBank:\n");
863
printf("\t\tBankNumber=%d\n", b->BankNumber);
864
printf("\t\tClearStatusOnInit=%d\n", b->ClearStatusOnInit);
865
printf("\t\tStatusFormat=%d\n", b->StatusFormat);
866
printf("\t\tControlRegister=%x\n", b->ControlRegister);
867
printf("\t\tControlData=%jx\n", b->ControlData);
868
printf("\t\tStatusRegister=%x\n", b->StatusRegister);
869
printf("\t\tAddressRegister=%x\n", b->AddressRegister);
870
printf("\t\tMiscRegister=%x\n", b->MiscRegister);
871
}
872
873
static void
874
acpi_print_hest_notify(ACPI_HEST_NOTIFY *n)
875
{
876
877
printf("\t\tType=%d\n", n->Type);
878
printf("\t\tLength=%d\n", n->Length);
879
printf("\t\tConfigWriteEnable=%04x\n", n->ConfigWriteEnable);
880
printf("\t\tPollInterval=%d\n", n->PollInterval);
881
printf("\t\tVector=%d\n", n->Vector);
882
printf("\t\tPollingThresholdValue=%d\n", n->PollingThresholdValue);
883
printf("\t\tPollingThresholdWindow=%d\n", n->PollingThresholdWindow);
884
printf("\t\tErrorThresholdValue=%d\n", n->ErrorThresholdValue);
885
printf("\t\tErrorThresholdWindow=%d\n", n->ErrorThresholdWindow);
886
}
887
888
static void
889
acpi_print_hest_aer(ACPI_HEST_AER_COMMON *a)
890
{
891
892
printf("\tFlags=%02x\n", a->Flags);
893
printf("\tEnabled=%d\n", a->Enabled);
894
printf("\tRecordsToPreallocate=%d\n", a->RecordsToPreallocate);
895
printf("\tMaxSectionsPerRecord=%d\n", a->MaxSectionsPerRecord);
896
printf("\tBus=%d\n", a->Bus);
897
printf("\tDevice=%d\n", a->Device);
898
printf("\tFunction=%d\n", a->Function);
899
printf("\tDeviceControl=%d\n", a->DeviceControl);
900
printf("\tUncorrectableMask=%d\n", a->UncorrectableMask);
901
printf("\tUncorrectableSeverity=%d\n", a->UncorrectableSeverity);
902
printf("\tCorrectableMask=%d\n", a->CorrectableMask);
903
printf("\tAdvancedCapabilities=%d\n", a->AdvancedCapabilities);
904
}
905
906
static int
907
acpi_handle_hest_structure(void *addr, int remaining)
908
{
909
ACPI_HEST_HEADER *hdr = addr;
910
int i;
911
912
if (remaining < (int)sizeof(ACPI_HEST_HEADER))
913
return (-1);
914
915
printf("\n\tType=%d\n", hdr->Type);
916
printf("\tSourceId=%d\n", hdr->SourceId);
917
switch (hdr->Type) {
918
case ACPI_HEST_TYPE_IA32_CHECK: {
919
ACPI_HEST_IA_MACHINE_CHECK *s = addr;
920
printf("\tFlags=%02x\n", s->Flags);
921
printf("\tEnabled=%d\n", s->Enabled);
922
printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
923
printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
924
printf("\tGlobalCapabilityData=%jd\n", s->GlobalCapabilityData);
925
printf("\tGlobalControlData=%jd\n", s->GlobalControlData);
926
printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
927
for (i = 0; i < s->NumHardwareBanks; i++) {
928
acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
929
(s + 1) + i);
930
}
931
return (sizeof(*s) + s->NumHardwareBanks *
932
sizeof(ACPI_HEST_IA_ERROR_BANK));
933
}
934
case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: {
935
ACPI_HEST_IA_CORRECTED *s = addr;
936
printf("\tFlags=%02x\n", s->Flags);
937
printf("\tEnabled=%d\n", s->Enabled);
938
printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
939
printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
940
printf("\tNotify:\n");
941
acpi_print_hest_notify(&s->Notify);
942
printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
943
for (i = 0; i < s->NumHardwareBanks; i++) {
944
acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
945
(s + 1) + i);
946
}
947
return (sizeof(*s) + s->NumHardwareBanks *
948
sizeof(ACPI_HEST_IA_ERROR_BANK));
949
}
950
case ACPI_HEST_TYPE_IA32_NMI: {
951
ACPI_HEST_IA_NMI *s = addr;
952
printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
953
printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
954
printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
955
return (sizeof(*s));
956
}
957
case ACPI_HEST_TYPE_AER_ROOT_PORT: {
958
ACPI_HEST_AER_ROOT *s = addr;
959
acpi_print_hest_aer(&s->Aer);
960
printf("\tRootErrorCommand=%d\n", s->RootErrorCommand);
961
return (sizeof(*s));
962
}
963
case ACPI_HEST_TYPE_AER_ENDPOINT: {
964
ACPI_HEST_AER *s = addr;
965
acpi_print_hest_aer(&s->Aer);
966
return (sizeof(*s));
967
}
968
case ACPI_HEST_TYPE_AER_BRIDGE: {
969
ACPI_HEST_AER_BRIDGE *s = addr;
970
acpi_print_hest_aer(&s->Aer);
971
printf("\tUncorrectableMask2=%d\n", s->UncorrectableMask2);
972
printf("\tUncorrectableSeverity2=%d\n", s->UncorrectableSeverity2);
973
printf("\tAdvancedCapabilities2=%d\n", s->AdvancedCapabilities2);
974
return (sizeof(*s));
975
}
976
case ACPI_HEST_TYPE_GENERIC_ERROR: {
977
ACPI_HEST_GENERIC *s = addr;
978
printf("\tRelatedSourceId=%d\n", s->RelatedSourceId);
979
printf("\tEnabled=%d\n", s->Enabled);
980
printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
981
printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
982
printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
983
printf("\tErrorStatusAddress=");
984
acpi_print_gas(&s->ErrorStatusAddress);
985
printf("\n");
986
printf("\tNotify:\n");
987
acpi_print_hest_notify(&s->Notify);
988
printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength);
989
return (sizeof(*s));
990
}
991
case ACPI_HEST_TYPE_GENERIC_ERROR_V2: {
992
ACPI_HEST_GENERIC_V2 *s = addr;
993
printf("\tRelatedSourceId=%d\n", s->RelatedSourceId);
994
printf("\tEnabled=%d\n", s->Enabled);
995
printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
996
printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
997
printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength);
998
printf("\tErrorStatusAddress=");
999
acpi_print_gas(&s->ErrorStatusAddress);
1000
printf("\n");
1001
printf("\tNotify:\n");
1002
acpi_print_hest_notify(&s->Notify);
1003
printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength);
1004
printf("\tReadAckRegister=");
1005
acpi_print_gas(&s->ReadAckRegister);
1006
printf("\n");
1007
printf("\tReadAckPreserve=%jd\n", s->ReadAckPreserve);
1008
printf("\tReadAckWrite=%jd\n", s->ReadAckWrite);
1009
return (sizeof(*s));
1010
}
1011
case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: {
1012
ACPI_HEST_IA_DEFERRED_CHECK *s = addr;
1013
printf("\tFlags=%02x\n", s->Flags);
1014
printf("\tEnabled=%d\n", s->Enabled);
1015
printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate);
1016
printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord);
1017
printf("\tNotify:\n");
1018
acpi_print_hest_notify(&s->Notify);
1019
printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks);
1020
for (i = 0; i < s->NumHardwareBanks; i++) {
1021
acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *)
1022
(s + 1) + i);
1023
}
1024
return (sizeof(*s) + s->NumHardwareBanks *
1025
sizeof(ACPI_HEST_IA_ERROR_BANK));
1026
}
1027
default:
1028
return (-1);
1029
}
1030
}
1031
1032
static void
1033
acpi_handle_hest(ACPI_TABLE_HEADER *sdp)
1034
{
1035
char *cp;
1036
int remaining, consumed;
1037
ACPI_TABLE_HEST *hest;
1038
1039
printf(BEGIN_COMMENT);
1040
acpi_print_sdt(sdp);
1041
hest = (ACPI_TABLE_HEST *)sdp;
1042
printf("\tErrorSourceCount=%d\n", hest->ErrorSourceCount);
1043
1044
remaining = sdp->Length - sizeof(ACPI_TABLE_HEST);
1045
while (remaining > 0) {
1046
cp = (char *)sdp + sdp->Length - remaining;
1047
consumed = acpi_handle_hest_structure(cp, remaining);
1048
if (consumed <= 0)
1049
break;
1050
else
1051
remaining -= consumed;
1052
}
1053
printf(END_COMMENT);
1054
}
1055
1056
static void
1057
acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
1058
{
1059
ACPI_TABLE_HPET *hpet;
1060
1061
printf(BEGIN_COMMENT);
1062
acpi_print_sdt(sdp);
1063
hpet = (ACPI_TABLE_HPET *)sdp;
1064
printf("\tHPET Number=%d\n", hpet->Sequence);
1065
printf("\tADDR=");
1066
acpi_print_gas(&hpet->Address);
1067
printf("\n\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
1068
printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
1069
8);
1070
printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
1071
1 : 0);
1072
printf("\tLegacy IRQ routing capable={");
1073
if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
1074
printf("TRUE}\n");
1075
else
1076
printf("FALSE}\n");
1077
printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
1078
printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
1079
printf("\tFlags=0x%02x\n", hpet->Flags);
1080
printf(END_COMMENT);
1081
}
1082
1083
static void
1084
acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
1085
{
1086
ACPI_TABLE_ECDT *ecdt;
1087
1088
printf(BEGIN_COMMENT);
1089
acpi_print_sdt(sdp);
1090
ecdt = (ACPI_TABLE_ECDT *)sdp;
1091
printf("\tEC_CONTROL=");
1092
acpi_print_gas(&ecdt->Control);
1093
printf("\n\tEC_DATA=");
1094
acpi_print_gas(&ecdt->Data);
1095
printf("\n\tUID=%#x, ", ecdt->Uid);
1096
printf("GPE_BIT=%#x\n", ecdt->Gpe);
1097
printf("\tEC_ID=%s\n", ecdt->Id);
1098
printf(END_COMMENT);
1099
}
1100
1101
static void
1102
acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
1103
{
1104
ACPI_TABLE_MCFG *mcfg;
1105
ACPI_MCFG_ALLOCATION *alloc;
1106
u_int i, entries;
1107
1108
printf(BEGIN_COMMENT);
1109
acpi_print_sdt(sdp);
1110
mcfg = (ACPI_TABLE_MCFG *)sdp;
1111
entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
1112
sizeof(ACPI_MCFG_ALLOCATION);
1113
alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
1114
for (i = 0; i < entries; i++, alloc++) {
1115
printf("\n");
1116
printf("\tBase Address=0x%016jx\n", (uintmax_t)alloc->Address);
1117
printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
1118
printf("\tStart Bus=%d\n", alloc->StartBusNumber);
1119
printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
1120
}
1121
printf(END_COMMENT);
1122
}
1123
1124
static void
1125
acpi_handle_slit(ACPI_TABLE_HEADER *sdp)
1126
{
1127
ACPI_TABLE_SLIT *slit;
1128
UINT64 i, j;
1129
1130
printf(BEGIN_COMMENT);
1131
acpi_print_sdt(sdp);
1132
slit = (ACPI_TABLE_SLIT *)sdp;
1133
printf("\tLocality Count=%ju\n", (uintmax_t)slit->LocalityCount);
1134
printf("\n\t ");
1135
for (i = 0; i < slit->LocalityCount; i++)
1136
printf(" %3ju", (uintmax_t)i);
1137
printf("\n\t +");
1138
for (i = 0; i < slit->LocalityCount; i++)
1139
printf("----");
1140
printf("\n");
1141
for (i = 0; i < slit->LocalityCount; i++) {
1142
printf("\t %3ju |", (uintmax_t)i);
1143
for (j = 0; j < slit->LocalityCount; j++)
1144
printf(" %3d",
1145
slit->Entry[i * slit->LocalityCount + j]);
1146
printf("\n");
1147
}
1148
printf(END_COMMENT);
1149
}
1150
1151
static void
1152
acpi_handle_wddt(ACPI_TABLE_HEADER *sdp)
1153
{
1154
ACPI_TABLE_WDDT *wddt;
1155
1156
printf(BEGIN_COMMENT);
1157
acpi_print_sdt(sdp);
1158
wddt = (ACPI_TABLE_WDDT *)sdp;
1159
printf("\tSpecVersion=0x%04x, TableVersion=0x%04x\n",
1160
wddt->SpecVersion, wddt->TableVersion);
1161
printf("\tPciVendorId=0x%04x, Address=", wddt->PciVendorId);
1162
acpi_print_gas(&wddt->Address);
1163
printf("\n\tMaxCount=%u, MinCount=%u, Period=%ums\n",
1164
wddt->MaxCount, wddt->MinCount, wddt->Period);
1165
1166
#define PRINTFLAG(var, flag) printflag((var), ACPI_WDDT_## flag, #flag)
1167
printf("\tStatus=");
1168
PRINTFLAG(wddt->Status, AVAILABLE);
1169
PRINTFLAG(wddt->Status, ACTIVE);
1170
PRINTFLAG(wddt->Status, TCO_OS_OWNED);
1171
PRINTFLAG(wddt->Status, USER_RESET);
1172
PRINTFLAG(wddt->Status, WDT_RESET);
1173
PRINTFLAG(wddt->Status, POWER_FAIL);
1174
PRINTFLAG(wddt->Status, UNKNOWN_RESET);
1175
PRINTFLAG_END();
1176
printf("\tCapability=");
1177
PRINTFLAG(wddt->Capability, AUTO_RESET);
1178
PRINTFLAG(wddt->Capability, ALERT_SUPPORT);
1179
PRINTFLAG_END();
1180
#undef PRINTFLAG
1181
1182
printf(END_COMMENT);
1183
}
1184
1185
static void
1186
acpi_print_native_lpit(ACPI_LPIT_NATIVE *nl)
1187
{
1188
printf("\tEntryTrigger=");
1189
acpi_print_gas(&nl->EntryTrigger);
1190
printf("\n\tResidency=%u\n", nl->Residency);
1191
printf("\tLatency=%u\n", nl->Latency);
1192
if (nl->Header.Flags & ACPI_LPIT_NO_COUNTER)
1193
printf("\tResidencyCounter=Not Present");
1194
else {
1195
printf("\tResidencyCounter=");
1196
acpi_print_gas(&nl->ResidencyCounter);
1197
printf("\n");
1198
}
1199
if (nl->CounterFrequency)
1200
printf("\tCounterFrequency=%ju\n", nl->CounterFrequency);
1201
else
1202
printf("\tCounterFrequency=TSC\n");
1203
}
1204
1205
static void
1206
acpi_print_lpit(ACPI_LPIT_HEADER *lpit)
1207
{
1208
if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
1209
printf("\tType=ACPI_LPIT_TYPE_NATIVE_CSTATE\n");
1210
else
1211
warnx("unknown LPIT type %u", lpit->Type);
1212
1213
printf("\tLength=%u\n", lpit->Length);
1214
printf("\tUniqueId=0x%04x\n", lpit->UniqueId);
1215
#define PRINTFLAG(var, flag) printflag((var), ACPI_LPIT_## flag, #flag)
1216
printf("\tFlags=");
1217
PRINTFLAG(lpit->Flags, STATE_DISABLED);
1218
PRINTFLAG_END();
1219
#undef PRINTFLAG
1220
1221
if (lpit->Type == ACPI_LPIT_TYPE_NATIVE_CSTATE)
1222
return acpi_print_native_lpit((ACPI_LPIT_NATIVE *)lpit);
1223
}
1224
1225
static void
1226
acpi_walk_lpit(ACPI_TABLE_HEADER *table, void *first,
1227
void (*action)(ACPI_LPIT_HEADER *))
1228
{
1229
ACPI_LPIT_HEADER *subtable;
1230
char *end;
1231
1232
subtable = first;
1233
end = (char *)table + table->Length;
1234
while ((char *)subtable < end) {
1235
printf("\n");
1236
if (subtable->Length < sizeof(ACPI_LPIT_HEADER)) {
1237
warnx("invalid subtable length %u", subtable->Length);
1238
return;
1239
}
1240
action(subtable);
1241
subtable = (ACPI_LPIT_HEADER *)((char *)subtable +
1242
subtable->Length);
1243
}
1244
}
1245
1246
static void
1247
acpi_handle_lpit(ACPI_TABLE_HEADER *sdp)
1248
{
1249
ACPI_TABLE_LPIT *lpit;
1250
1251
printf(BEGIN_COMMENT);
1252
acpi_print_sdt(sdp);
1253
lpit = (ACPI_TABLE_LPIT *)sdp;
1254
acpi_walk_lpit(sdp, (lpit + 1), acpi_print_lpit);
1255
1256
printf(END_COMMENT);
1257
}
1258
1259
static void
1260
acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
1261
uint32_t flags)
1262
{
1263
1264
printf("\tFlags={");
1265
if (flags & ACPI_SRAT_CPU_ENABLED)
1266
printf("ENABLED");
1267
else
1268
printf("DISABLED");
1269
printf("}\n");
1270
printf("\tAPIC ID=%d\n", apic_id);
1271
printf("\tProximity Domain=%d\n", proximity_domain);
1272
}
1273
1274
static char *
1275
acpi_tcpa_evname(struct TCPAevent *event)
1276
{
1277
struct TCPApc_event *pc_event;
1278
char *eventname = NULL;
1279
1280
pc_event = (struct TCPApc_event *)(event + 1);
1281
1282
switch(event->event_type) {
1283
case PREBOOT:
1284
case POST_CODE:
1285
case UNUSED:
1286
case NO_ACTION:
1287
case SEPARATOR:
1288
case SCRTM_CONTENTS:
1289
case SCRTM_VERSION:
1290
case CPU_MICROCODE:
1291
case PLATFORM_CONFIG_FLAGS:
1292
case TABLE_OF_DEVICES:
1293
case COMPACT_HASH:
1294
case IPL:
1295
case IPL_PARTITION_DATA:
1296
case NONHOST_CODE:
1297
case NONHOST_CONFIG:
1298
case NONHOST_INFO:
1299
asprintf(&eventname, "%s",
1300
tcpa_event_type_strings[event->event_type]);
1301
break;
1302
1303
case ACTION:
1304
eventname = calloc(event->event_size + 1, sizeof(char));
1305
memcpy(eventname, pc_event, event->event_size);
1306
break;
1307
1308
case EVENT_TAG:
1309
switch (pc_event->event_id) {
1310
case SMBIOS:
1311
case BIS_CERT:
1312
case CMOS:
1313
case NVRAM:
1314
case OPTION_ROM_EXEC:
1315
case OPTION_ROM_CONFIG:
1316
case S_CRTM_VERSION:
1317
case POST_BIOS_ROM:
1318
case ESCD:
1319
case OPTION_ROM_MICROCODE:
1320
case S_CRTM_CONTENTS:
1321
case POST_CONTENTS:
1322
asprintf(&eventname, "%s",
1323
TCPA_pcclient_strings[pc_event->event_id]);
1324
break;
1325
1326
default:
1327
asprintf(&eventname, "<unknown tag 0x%02x>",
1328
pc_event->event_id);
1329
break;
1330
}
1331
break;
1332
1333
default:
1334
asprintf(&eventname, "<unknown 0x%02x>", event->event_type);
1335
break;
1336
}
1337
1338
return eventname;
1339
}
1340
1341
static void
1342
acpi_print_tcpa(struct TCPAevent *event)
1343
{
1344
int i;
1345
char *eventname;
1346
1347
eventname = acpi_tcpa_evname(event);
1348
1349
printf("\t%d", event->pcr_index);
1350
printf(" 0x");
1351
for (i = 0; i < 20; i++)
1352
printf("%02x", event->pcr_value[i]);
1353
printf(" [%s]\n", eventname ? eventname : "<unknown>");
1354
1355
free(eventname);
1356
}
1357
1358
static void
1359
acpi_handle_tcpa(ACPI_TABLE_HEADER *sdp)
1360
{
1361
struct TCPAbody *tcpa;
1362
struct TCPAevent *event;
1363
uintmax_t len, paddr;
1364
unsigned char *vaddr = NULL;
1365
unsigned char *vend = NULL;
1366
1367
printf(BEGIN_COMMENT);
1368
acpi_print_sdt(sdp);
1369
tcpa = (struct TCPAbody *) sdp;
1370
1371
switch (tcpa->platform_class) {
1372
case ACPI_TCPA_BIOS_CLIENT:
1373
len = tcpa->client.log_max_len;
1374
paddr = tcpa->client.log_start_addr;
1375
break;
1376
1377
case ACPI_TCPA_BIOS_SERVER:
1378
len = tcpa->server.log_max_len;
1379
paddr = tcpa->server.log_start_addr;
1380
break;
1381
1382
default:
1383
printf("XXX");
1384
printf(END_COMMENT);
1385
return;
1386
}
1387
printf("\tClass %u Base Address 0x%jx Length %ju\n\n",
1388
tcpa->platform_class, paddr, len);
1389
1390
if (len == 0) {
1391
printf("\tEmpty TCPA table\n");
1392
printf(END_COMMENT);
1393
return;
1394
}
1395
if(sdp->Revision == 1){
1396
printf("\tOLD TCPA spec log found. Dumping not supported.\n");
1397
printf(END_COMMENT);
1398
return;
1399
}
1400
1401
vaddr = (unsigned char *)acpi_map_physical(paddr, len);
1402
vend = vaddr + len;
1403
1404
while (vaddr != NULL) {
1405
if ((uintptr_t)vaddr + sizeof(struct TCPAevent) >=
1406
(uintptr_t)vend || (uintptr_t)vaddr + sizeof(
1407
struct TCPAevent) < (uintptr_t)vaddr)
1408
break;
1409
event = (struct TCPAevent *)(void *)vaddr;
1410
if ((uintptr_t)vaddr + event->event_size >= (uintptr_t)vend)
1411
break;
1412
if ((uintptr_t)vaddr + event->event_size < (uintptr_t)vaddr)
1413
break;
1414
if (event->event_type == 0 && event->event_size == 0)
1415
break;
1416
#if 0
1417
{
1418
unsigned int i, j, k;
1419
1420
printf("\n\tsize %d\n\t\t%p ", event->event_size, vaddr);
1421
for (j = 0, i = 0; i <
1422
sizeof(struct TCPAevent) + event->event_size; i++) {
1423
printf("%02x ", vaddr[i]);
1424
if ((i+1) % 8 == 0) {
1425
for (k = 0; k < 8; k++)
1426
printf("%c", isprint(vaddr[j+k]) ?
1427
vaddr[j+k] : '.');
1428
printf("\n\t\t%p ", &vaddr[i + 1]);
1429
j = i + 1;
1430
}
1431
}
1432
printf("\n"); }
1433
#endif
1434
acpi_print_tcpa(event);
1435
1436
vaddr += sizeof(struct TCPAevent) + event->event_size;
1437
}
1438
1439
printf(END_COMMENT);
1440
}
1441
1442
static void acpi_handle_tpm2(ACPI_TABLE_HEADER *sdp)
1443
{
1444
ACPI_TABLE_TPM2 *tpm2;
1445
1446
printf (BEGIN_COMMENT);
1447
acpi_print_sdt(sdp);
1448
tpm2 = (ACPI_TABLE_TPM2 *) sdp;
1449
printf ("\t\tControlArea=%jx\n", tpm2->ControlAddress);
1450
printf ("\t\tStartMethod=%x\n", tpm2->StartMethod);
1451
printf (END_COMMENT);
1452
}
1453
1454
static int spcr_xlate_baud(uint8_t r)
1455
{
1456
static int rates[] = { 9600, 19200, -1, 57600, 115200 };
1457
_Static_assert(nitems(rates) == 7 - 3 + 1, "rates array size incorrect");
1458
1459
if (r == 0)
1460
return (0);
1461
1462
if (r < 3 || r > 7)
1463
return (-1);
1464
1465
return (rates[r - 3]);
1466
}
1467
1468
static const char *spcr_interface_type(int ift)
1469
{
1470
static const char *if_names[] = {
1471
[0x00] = "Fully 16550-compatible",
1472
[0x01] = "16550 subset compatible with DBGP Revision 1",
1473
[0x02] = "MAX311xE SPI UART",
1474
[0x03] = "Arm PL011 UART",
1475
[0x04] = "MSM8x60 (e.g. 8960)",
1476
[0x05] = "Nvidia 16550",
1477
[0x06] = "TI OMAP",
1478
[0x07] = "Reserved (Do Not Use)",
1479
[0x08] = "APM88xxxx",
1480
[0x09] = "MSM8974",
1481
[0x0a] = "SAM5250",
1482
[0x0b] = "Intel USIF",
1483
[0x0c] = "i.MX 6",
1484
[0x0d] = "(deprecated) Arm SBSA (2.x only) Generic UART supporting only 32-bit accesses",
1485
[0x0e] = "Arm SBSA Generic UART",
1486
[0x0f] = "Arm DCC",
1487
[0x10] = "BCM2835",
1488
[0x11] = "SDM845 with clock rate of 1.8432 MHz",
1489
[0x12] = "16550-compatible with parameters defined in Generic Address Structure",
1490
[0x13] = "SDM845 with clock rate of 7.372 MHz",
1491
[0x14] = "Intel LPSS",
1492
[0x15] = "RISC-V SBI console (any supported SBI mechanism)",
1493
};
1494
1495
if (ift >= (int)nitems(if_names) || if_names[ift] == NULL)
1496
return ("Reserved");
1497
return (if_names[ift]);
1498
}
1499
1500
static const char *spcr_interrupt_type(int ift)
1501
{
1502
static char buf[100];
1503
1504
#define APPEND(b,s) \
1505
if ((ift & (b)) != 0) { \
1506
if (strlen(buf) > 0) \
1507
strlcat(buf, ",", sizeof(buf)); \
1508
strlcat(buf, s, sizeof(buf)); \
1509
}
1510
1511
*buf = '\0';
1512
APPEND(0x01, "PC/AT IRQ");
1513
APPEND(0x02, "I/O APIC");
1514
APPEND(0x04, "I/O SAPIC");
1515
APPEND(0x08, "ARMH GIC");
1516
APPEND(0x10, "RISC-V PLIC/APLIC");
1517
1518
#undef APPEND
1519
1520
return (buf);
1521
}
1522
1523
static const char *spcr_terminal_type(int type)
1524
{
1525
static const char *term_names[] = {
1526
[0] = "VT100",
1527
[1] = "Extended VT100",
1528
[2] = "VT-UTF8",
1529
[3] = "ANSI",
1530
};
1531
1532
if (type >= (int)nitems(term_names) || term_names[type] == NULL)
1533
return ("Reserved");
1534
return (term_names[type]);
1535
}
1536
1537
static void acpi_handle_spcr(ACPI_TABLE_HEADER *sdp)
1538
{
1539
ACPI_TABLE_SPCR *spcr;
1540
1541
printf (BEGIN_COMMENT);
1542
acpi_print_sdt(sdp);
1543
1544
/* Rev 1 and 2 are the same size */
1545
spcr = (ACPI_TABLE_SPCR *) sdp;
1546
printf ("\tInterfaceType=%d (%s)\n", spcr->InterfaceType,
1547
spcr_interface_type(spcr->InterfaceType));
1548
printf ("\tSerialPort=");
1549
acpi_print_gas(&spcr->SerialPort);
1550
printf ("\n\tInterruptType=%#x (%s)\n", spcr->InterruptType,
1551
spcr_interrupt_type(spcr->InterruptType));
1552
printf ("\tPcInterrupt=%d (%s)\n", spcr->PcInterrupt,
1553
(spcr->InterruptType & 0x1) ? "Valid" : "Invalid");
1554
printf ("\tInterrupt=%d\n", spcr->Interrupt);
1555
printf ("\tBaudRate=%d (%d)\n", spcr_xlate_baud(spcr->BaudRate), spcr->BaudRate);
1556
printf ("\tParity=%d\n", spcr->Parity);
1557
printf ("\tStopBits=%d\n", spcr->StopBits);
1558
printf ("\tFlowControl=%d\n", spcr->FlowControl);
1559
printf ("\tTerminalType=%d (%s)\n", spcr->TerminalType,
1560
spcr_terminal_type(spcr->TerminalType));
1561
printf ("\tPciDeviceId=%#04x\n", spcr->PciDeviceId);
1562
printf ("\tPciVendorId=%#04x\n", spcr->PciVendorId);
1563
printf ("\tPciBus=%d\n", spcr->PciBus);
1564
printf ("\tPciDevice=%d\n", spcr->PciDevice);
1565
printf ("\tPciFunction=%d\n", spcr->PciFunction);
1566
printf ("\tPciFlags=%d\n", spcr->PciFlags);
1567
printf ("\tPciSegment=%d\n", spcr->PciSegment);
1568
1569
/* Rev 3 added UartClkFrequency */
1570
if (sdp->Revision >= 3) {
1571
printf("\tLanguage=%d\n", spcr->Language);
1572
printf("\tUartClkFreq=%jd",
1573
(uintmax_t)spcr->UartClkFreq);
1574
}
1575
1576
/* Rev 4 added PreciseBaudrate and NameSpace* */
1577
if (sdp->Revision >= 4) {
1578
printf("\tPreciseBaudrate=%jd",
1579
(uintmax_t)spcr->PreciseBaudrate);
1580
if (spcr->NameSpaceStringLength > 0 &&
1581
spcr->NameSpaceStringOffset >= sizeof(*spcr) &&
1582
sdp->Length >= spcr->NameSpaceStringOffset +
1583
spcr->NameSpaceStringLength) {
1584
printf ("\tNameSpaceString='%s'\n",
1585
(char *)sdp + spcr->NameSpaceStringOffset);
1586
}
1587
}
1588
1589
printf (END_COMMENT);
1590
}
1591
1592
static const char *
1593
devscope_type2str(int type)
1594
{
1595
static char typebuf[16];
1596
1597
switch (type) {
1598
case ACPI_DMAR_SCOPE_TYPE_ENDPOINT:
1599
return ("PCI Endpoint Device");
1600
case ACPI_DMAR_SCOPE_TYPE_BRIDGE:
1601
return ("PCI Sub-Hierarchy");
1602
case ACPI_DMAR_SCOPE_TYPE_IOAPIC:
1603
return ("IOAPIC");
1604
case ACPI_DMAR_SCOPE_TYPE_HPET:
1605
return ("HPET");
1606
case ACPI_DMAR_SCOPE_TYPE_NAMESPACE:
1607
return ("ACPI NS DEV");
1608
default:
1609
snprintf(typebuf, sizeof(typebuf), "%d", type);
1610
return (typebuf);
1611
}
1612
}
1613
1614
static int
1615
acpi_handle_dmar_devscope(void *addr, int remaining)
1616
{
1617
char sep;
1618
int pathlen;
1619
ACPI_DMAR_PCI_PATH *path, *pathend;
1620
ACPI_DMAR_DEVICE_SCOPE *devscope = addr;
1621
1622
if (remaining < (int)sizeof(ACPI_DMAR_DEVICE_SCOPE))
1623
return (-1);
1624
1625
if (remaining < devscope->Length)
1626
return (-1);
1627
1628
printf("\n");
1629
printf("\t\tType=%s\n", devscope_type2str(devscope->EntryType));
1630
printf("\t\tLength=%d\n", devscope->Length);
1631
printf("\t\tEnumerationId=%d\n", devscope->EnumerationId);
1632
printf("\t\tStartBusNumber=%d\n", devscope->Bus);
1633
1634
path = (ACPI_DMAR_PCI_PATH *)(devscope + 1);
1635
pathlen = devscope->Length - sizeof(ACPI_DMAR_DEVICE_SCOPE);
1636
pathend = path + pathlen / sizeof(ACPI_DMAR_PCI_PATH);
1637
if (path < pathend) {
1638
sep = '{';
1639
printf("\t\tPath=");
1640
do {
1641
printf("%c%d:%d", sep, path->Device, path->Function);
1642
sep=',';
1643
path++;
1644
} while (path < pathend);
1645
printf("}\n");
1646
}
1647
1648
return (devscope->Length);
1649
}
1650
1651
static void
1652
acpi_handle_dmar_drhd(ACPI_DMAR_HARDWARE_UNIT *drhd)
1653
{
1654
char *cp;
1655
int remaining, consumed;
1656
1657
printf("\n");
1658
printf("\tType=DRHD\n");
1659
printf("\tLength=%d\n", drhd->Header.Length);
1660
1661
#define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
1662
1663
printf("\tFlags=");
1664
PRINTFLAG(drhd->Flags, INCLUDE_ALL);
1665
PRINTFLAG_END();
1666
1667
#undef PRINTFLAG
1668
1669
printf("\tSegment=%d\n", drhd->Segment);
1670
printf("\tAddress=0x%016jx\n", (uintmax_t)drhd->Address);
1671
1672
remaining = drhd->Header.Length - sizeof(ACPI_DMAR_HARDWARE_UNIT);
1673
if (remaining > 0)
1674
printf("\tDevice Scope:");
1675
while (remaining > 0) {
1676
cp = (char *)drhd + drhd->Header.Length - remaining;
1677
consumed = acpi_handle_dmar_devscope(cp, remaining);
1678
if (consumed <= 0)
1679
break;
1680
else
1681
remaining -= consumed;
1682
}
1683
}
1684
1685
static void
1686
acpi_handle_dmar_rmrr(ACPI_DMAR_RESERVED_MEMORY *rmrr)
1687
{
1688
char *cp;
1689
int remaining, consumed;
1690
1691
printf("\n");
1692
printf("\tType=RMRR\n");
1693
printf("\tLength=%d\n", rmrr->Header.Length);
1694
printf("\tSegment=%d\n", rmrr->Segment);
1695
printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rmrr->BaseAddress);
1696
printf("\tLimitAddress=0x%016jx\n", (uintmax_t)rmrr->EndAddress);
1697
1698
remaining = rmrr->Header.Length - sizeof(ACPI_DMAR_RESERVED_MEMORY);
1699
if (remaining > 0)
1700
printf("\tDevice Scope:");
1701
while (remaining > 0) {
1702
cp = (char *)rmrr + rmrr->Header.Length - remaining;
1703
consumed = acpi_handle_dmar_devscope(cp, remaining);
1704
if (consumed <= 0)
1705
break;
1706
else
1707
remaining -= consumed;
1708
}
1709
}
1710
1711
static void
1712
acpi_handle_dmar_atsr(ACPI_DMAR_ATSR *atsr)
1713
{
1714
char *cp;
1715
int remaining, consumed;
1716
1717
printf("\n");
1718
printf("\tType=ATSR\n");
1719
printf("\tLength=%d\n", atsr->Header.Length);
1720
1721
#define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
1722
1723
printf("\tFlags=");
1724
PRINTFLAG(atsr->Flags, ALL_PORTS);
1725
PRINTFLAG_END();
1726
1727
#undef PRINTFLAG
1728
1729
printf("\tSegment=%d\n", atsr->Segment);
1730
1731
remaining = atsr->Header.Length - sizeof(ACPI_DMAR_ATSR);
1732
if (remaining > 0)
1733
printf("\tDevice Scope:");
1734
while (remaining > 0) {
1735
cp = (char *)atsr + atsr->Header.Length - remaining;
1736
consumed = acpi_handle_dmar_devscope(cp, remaining);
1737
if (consumed <= 0)
1738
break;
1739
else
1740
remaining -= consumed;
1741
}
1742
}
1743
1744
static void
1745
acpi_handle_dmar_rhsa(ACPI_DMAR_RHSA *rhsa)
1746
{
1747
1748
printf("\n");
1749
printf("\tType=RHSA\n");
1750
printf("\tLength=%d\n", rhsa->Header.Length);
1751
printf("\tBaseAddress=0x%016jx\n", (uintmax_t)rhsa->BaseAddress);
1752
printf("\tProximityDomain=0x%08x\n", rhsa->ProximityDomain);
1753
}
1754
1755
static int
1756
acpi_handle_dmar_remapping_structure(void *addr, int remaining)
1757
{
1758
ACPI_DMAR_HEADER *hdr = addr;
1759
1760
if (remaining < (int)sizeof(ACPI_DMAR_HEADER))
1761
return (-1);
1762
1763
if (remaining < hdr->Length)
1764
return (-1);
1765
1766
switch (hdr->Type) {
1767
case ACPI_DMAR_TYPE_HARDWARE_UNIT:
1768
acpi_handle_dmar_drhd(addr);
1769
break;
1770
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
1771
acpi_handle_dmar_rmrr(addr);
1772
break;
1773
case ACPI_DMAR_TYPE_ROOT_ATS:
1774
acpi_handle_dmar_atsr(addr);
1775
break;
1776
case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
1777
acpi_handle_dmar_rhsa(addr);
1778
break;
1779
default:
1780
printf("\n");
1781
printf("\tType=%d\n", hdr->Type);
1782
printf("\tLength=%d\n", hdr->Length);
1783
break;
1784
}
1785
return (hdr->Length);
1786
}
1787
1788
#ifndef ACPI_DMAR_X2APIC_OPT_OUT
1789
#define ACPI_DMAR_X2APIC_OPT_OUT (0x2)
1790
#endif
1791
1792
static void
1793
acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
1794
{
1795
char *cp;
1796
int remaining, consumed;
1797
ACPI_TABLE_DMAR *dmar;
1798
1799
printf(BEGIN_COMMENT);
1800
acpi_print_sdt(sdp);
1801
dmar = (ACPI_TABLE_DMAR *)sdp;
1802
printf("\tHost Address Width=%d\n", dmar->Width + 1);
1803
1804
#define PRINTFLAG(var, flag) printflag((var), ACPI_DMAR_## flag, #flag)
1805
1806
printf("\tFlags=");
1807
PRINTFLAG(dmar->Flags, INTR_REMAP);
1808
PRINTFLAG(dmar->Flags, X2APIC_OPT_OUT);
1809
PRINTFLAG_END();
1810
1811
#undef PRINTFLAG
1812
1813
remaining = sdp->Length - sizeof(ACPI_TABLE_DMAR);
1814
while (remaining > 0) {
1815
cp = (char *)sdp + sdp->Length - remaining;
1816
consumed = acpi_handle_dmar_remapping_structure(cp, remaining);
1817
if (consumed <= 0)
1818
break;
1819
else
1820
remaining -= consumed;
1821
}
1822
1823
printf(END_COMMENT);
1824
}
1825
1826
static void
1827
acpi_handle_ivrs_ivhd_header(ACPI_IVRS_HEADER *addr)
1828
{
1829
printf("\n\tIVHD Type=%#x IOMMU DeviceId=%#06x\n\tFlags=",
1830
addr->Type, addr->DeviceId);
1831
#define PRINTFLAG(flag, name) printflag(addr->Flags, flag, #name)
1832
PRINTFLAG(ACPI_IVHD_TT_ENABLE, HtTunEn);
1833
PRINTFLAG(ACPI_IVHD_ISOC, PassPW);
1834
PRINTFLAG(ACPI_IVHD_RES_PASS_PW, ResPassPW);
1835
PRINTFLAG(ACPI_IVHD_ISOC, Isoc);
1836
PRINTFLAG(ACPI_IVHD_TT_ENABLE, IotlbSup);
1837
PRINTFLAG((1 << 5), Coherent);
1838
PRINTFLAG((1 << 6), PreFSup);
1839
PRINTFLAG((1 << 7), PPRSup);
1840
#undef PRINTFLAG
1841
PRINTFLAG_END();
1842
}
1843
1844
static void
1845
acpi_handle_ivrs_ivhd_dte(UINT8 dte)
1846
{
1847
if (dte == 0) {
1848
printf("\n");
1849
return;
1850
}
1851
printf(" DTE=");
1852
#define PRINTFLAG(flag, name) printflag(dte, flag, #name)
1853
PRINTFLAG(ACPI_IVHD_INIT_PASS, INITPass);
1854
PRINTFLAG(ACPI_IVHD_EINT_PASS, EIntPass);
1855
PRINTFLAG(ACPI_IVHD_NMI_PASS, NMIPass);
1856
PRINTFLAG(ACPI_IVHD_SYSTEM_MGMT, SysMgtPass);
1857
PRINTFLAG(ACPI_IVHD_LINT0_PASS, Lint0Pass);
1858
PRINTFLAG(ACPI_IVHD_LINT1_PASS, Lint1Pass);
1859
#undef PRINTFLAG
1860
PRINTFLAG_END();
1861
}
1862
1863
static void
1864
acpi_handle_ivrs_ivhd_edte(UINT32 edte)
1865
{
1866
if (edte == 0)
1867
return;
1868
printf("\t\t ExtDTE=");
1869
#define PRINTFLAG(flag, name) printflag(edte, flag, #name)
1870
PRINTFLAG(ACPI_IVHD_ATS_DISABLED, AtsDisabled);
1871
#undef PRINTFLAG
1872
PRINTFLAG_END();
1873
}
1874
1875
static const char *
1876
acpi_handle_ivrs_ivhd_variety(UINT8 v)
1877
{
1878
switch (v) {
1879
case ACPI_IVHD_IOAPIC:
1880
return ("IOAPIC");
1881
case ACPI_IVHD_HPET:
1882
return ("HPET");
1883
default:
1884
return ("UNKNOWN");
1885
}
1886
}
1887
1888
static void
1889
acpi_handle_ivrs_ivhd_devs(ACPI_IVRS_DE_HEADER *d, char *de)
1890
{
1891
char *db;
1892
ACPI_IVRS_DEVICE4 *d4;
1893
ACPI_IVRS_DEVICE8A *d8a;
1894
ACPI_IVRS_DEVICE8B *d8b;
1895
ACPI_IVRS_DEVICE8C *d8c;
1896
ACPI_IVRS_DEVICE_HID *dh;
1897
size_t len;
1898
UINT32 x32;
1899
1900
for (; (char *)d < de; d = (ACPI_IVRS_DE_HEADER *)(db + len)) {
1901
db = (char *)d;
1902
if (d->Type == ACPI_IVRS_TYPE_PAD4) {
1903
len = sizeof(*d4);
1904
} else if (d->Type == ACPI_IVRS_TYPE_ALL) {
1905
d4 = (ACPI_IVRS_DEVICE4 *)db;
1906
len = sizeof(*d4);
1907
printf("\t\tDev Type=%#x Id=ALL", d4->Header.Type);
1908
acpi_handle_ivrs_ivhd_dte(d4->Header.DataSetting);
1909
} else if (d->Type == ACPI_IVRS_TYPE_SELECT) {
1910
d4 = (ACPI_IVRS_DEVICE4 *)db;
1911
len = sizeof(*d4);
1912
printf("\t\tDev Type=%#x Id=%#06x", d4->Header.Type,
1913
d4->Header.Id);
1914
acpi_handle_ivrs_ivhd_dte(d4->Header.DataSetting);
1915
} else if (d->Type == ACPI_IVRS_TYPE_START) {
1916
d4 = (ACPI_IVRS_DEVICE4 *)db;
1917
len = 2 * sizeof(*d4);
1918
printf("\t\tDev Type=%#x Id=%#06x-%#06x",
1919
d4->Header.Type,
1920
d4->Header.Id, (d4 + 1)->Header.Id);
1921
acpi_handle_ivrs_ivhd_dte(d4->Header.DataSetting);
1922
} else if (d->Type == ACPI_IVRS_TYPE_END) {
1923
d4 = (ACPI_IVRS_DEVICE4 *)db;
1924
len = 2 * sizeof(*d4);
1925
printf("\t\tDev Type=%#x Id=%#06x BIOS BUG\n",
1926
d4->Header.Type, d4->Header.Id);
1927
} else if (d->Type == ACPI_IVRS_TYPE_PAD8) {
1928
len = sizeof(*d8a);
1929
} else if (d->Type == ACPI_IVRS_TYPE_ALIAS_SELECT) {
1930
d8a = (ACPI_IVRS_DEVICE8A *)db;
1931
len = sizeof(*d8a);
1932
printf("\t\tDev Type=%#x Id=%#06x AliasId=%#06x",
1933
d8a->Header.Type, d8a->Header.Id, d8a->UsedId);
1934
acpi_handle_ivrs_ivhd_dte(d8a->Header.DataSetting);
1935
} else if (d->Type == ACPI_IVRS_TYPE_ALIAS_START) {
1936
d8a = (ACPI_IVRS_DEVICE8A *)db;
1937
d4 = (ACPI_IVRS_DEVICE4 *)(db + sizeof(*d8a));
1938
len = sizeof(*d8a) + sizeof(*d4);
1939
printf("\t\tDev Type=%#x Id=%#06x-%#06x AliasId=%#06x",
1940
d8a->Header.Type, d8a->Header.Id, d4->Header.Id,
1941
d8a->UsedId);
1942
acpi_handle_ivrs_ivhd_dte(d8a->Header.DataSetting);
1943
} else if (d->Type == ACPI_IVRS_TYPE_EXT_SELECT) {
1944
d8b = (ACPI_IVRS_DEVICE8B *)db;
1945
len = sizeof(*d8b);
1946
printf("\t\tDev Type=%#x Id=%#06x",
1947
d8b->Header.Type, d8b->Header.Id);
1948
acpi_handle_ivrs_ivhd_dte(d8b->Header.DataSetting);
1949
printf("\t\t");
1950
acpi_handle_ivrs_ivhd_edte(d8b->ExtendedData);
1951
} else if (d->Type == ACPI_IVRS_TYPE_EXT_START) {
1952
d8b = (ACPI_IVRS_DEVICE8B *)db;
1953
len = sizeof(*d8b);
1954
d4 = (ACPI_IVRS_DEVICE4 *)(db + sizeof(*d8b));
1955
len = sizeof(*d8b) + sizeof(*d4);
1956
printf("\t\tDev Type=%#x Id=%#06x-%#06x",
1957
d8b->Header.Type, d8b->Header.Id, d4->Header.Id);
1958
acpi_handle_ivrs_ivhd_dte(d8b->Header.DataSetting);
1959
acpi_handle_ivrs_ivhd_edte(d8b->ExtendedData);
1960
} else if (d->Type == ACPI_IVRS_TYPE_SPECIAL) {
1961
d8c = (ACPI_IVRS_DEVICE8C *)db;
1962
len = sizeof(*d8c);
1963
printf("\t\tDev Type=%#x Id=%#06x Handle=%#x "
1964
"Variety=%d(%s)",
1965
d8c->Header.Type, d8c->UsedId, d8c->Handle,
1966
d8c->Variety,
1967
acpi_handle_ivrs_ivhd_variety(d8c->Variety));
1968
acpi_handle_ivrs_ivhd_dte(d8c->Header.DataSetting);
1969
} else if (d->Type == ACPI_IVRS_TYPE_HID) {
1970
dh = (ACPI_IVRS_DEVICE_HID *)db;
1971
len = sizeof(*dh) + dh->UidLength;
1972
printf("\t\tDev Type=%#x Id=%#06x HID=",
1973
dh->Header.Type, dh->Header.Id);
1974
acpi_print_string((char *)&dh->AcpiHid,
1975
sizeof(dh->AcpiHid));
1976
printf(" CID=");
1977
acpi_print_string((char *)&dh->AcpiCid,
1978
sizeof(dh->AcpiCid));
1979
printf(" UID=");
1980
switch (dh->UidType) {
1981
case ACPI_IVRS_UID_NOT_PRESENT:
1982
default:
1983
printf("none");
1984
break;
1985
case ACPI_IVRS_UID_IS_INTEGER:
1986
memcpy(&x32, dh + 1, sizeof(x32));
1987
printf("%#x", x32);
1988
break;
1989
case ACPI_IVRS_UID_IS_STRING:
1990
acpi_print_string((char *)(dh + 1),
1991
dh->UidLength);
1992
break;
1993
}
1994
acpi_handle_ivrs_ivhd_dte(dh->Header.DataSetting);
1995
} else {
1996
printf("\t\tDev Type=%#x Unknown\n", d->Type);
1997
if (d->Type <= 63)
1998
len = sizeof(*d4);
1999
else if (d->Type <= 127)
2000
len = sizeof(*d8a);
2001
else {
2002
printf("Abort, cannot advance iterator.\n");
2003
return;
2004
}
2005
}
2006
}
2007
}
2008
2009
static void
2010
acpi_handle_ivrs_ivhd_10(ACPI_IVRS_HARDWARE1 *addr, bool efrsup)
2011
{
2012
acpi_handle_ivrs_ivhd_header(&addr->Header);
2013
printf("\tCapOffset=%#x Base=%#jx PCISeg=%#x Unit=%#x MSIlog=%d\n",
2014
addr->CapabilityOffset, (uintmax_t)addr->BaseAddress,
2015
addr->PciSegmentGroup, (addr->Info & ACPI_IVHD_UNIT_ID_MASK) >> 8,
2016
addr->Info & ACPI_IVHD_MSI_NUMBER_MASK);
2017
if (efrsup) {
2018
#define PRINTFLAG(flag, name) printflag(addr->FeatureReporting, flag, #name)
2019
#define PRINTFIELD(lbit, hbit, name) \
2020
printfield(addr->FeatureReporting, lbit, hbit, #name)
2021
PRINTFIELD(30, 31, HATS);
2022
PRINTFIELD(28, 29, GATS);
2023
PRINTFIELD(23, 27, MsiNumPPR);
2024
PRINTFIELD(17, 22, PNBanks);
2025
PRINTFIELD(13, 16, PNCounters);
2026
PRINTFIELD(8, 12, PASmax);
2027
PRINTFLAG(1 << 7, HESup);
2028
PRINTFLAG(1 << 6, GASup);
2029
PRINTFLAG(1 << 5, UASup);
2030
PRINTFIELD(3, 2, GLXSup);
2031
PRINTFLAG(1 << 1, NXSup);
2032
PRINTFLAG(1 << 0, XTSup);
2033
#undef PRINTFLAG
2034
#undef PRINTFIELD
2035
PRINTFLAG_END();
2036
}
2037
acpi_handle_ivrs_ivhd_devs((ACPI_IVRS_DE_HEADER *)(addr + 1),
2038
(char *)addr + addr->Header.Length);
2039
}
2040
2041
static void
2042
acpi_handle_ivrs_ivhd_info_11(ACPI_IVRS_HARDWARE2 *addr)
2043
{
2044
acpi_handle_ivrs_ivhd_header(&addr->Header);
2045
printf("\tCapOffset=%#x Base=%#jx PCISeg=%#x Unit=%#x MSIlog=%d\n",
2046
addr->CapabilityOffset, (uintmax_t)addr->BaseAddress,
2047
addr->PciSegmentGroup, (addr->Info >> 8) & 0x1f,
2048
addr->Info & 0x5);
2049
printf("\tAttr=");
2050
#define PRINTFIELD(lbit, hbit, name) \
2051
printfield(addr->Attributes, lbit, hbit, #name)
2052
PRINTFIELD(23, 27, MsiNumPPR);
2053
PRINTFIELD(17, 22, PNBanks);
2054
PRINTFIELD(13, 16, PNCounters);
2055
#undef PRINTFIELD
2056
PRINTFLAG_END();
2057
}
2058
2059
static void
2060
acpi_handle_ivrs_ivhd_11(ACPI_IVRS_HARDWARE2 *addr)
2061
{
2062
acpi_handle_ivrs_ivhd_info_11(addr);
2063
printf("\tEFRreg=%#018jx\n", (uintmax_t)addr->EfrRegisterImage);
2064
acpi_handle_ivrs_ivhd_devs((ACPI_IVRS_DE_HEADER *)(addr + 1),
2065
(char *)addr + addr->Header.Length);
2066
}
2067
2068
static void
2069
acpi_handle_ivrs_ivhd_40(ACPI_IVRS_HARDWARE2 *addr)
2070
{
2071
acpi_handle_ivrs_ivhd_info_11(addr);
2072
printf("\tEFRreg=%#018jx EFR2reg=%#018jx\n",
2073
(uintmax_t)addr->EfrRegisterImage, (uintmax_t)addr->Reserved);
2074
acpi_handle_ivrs_ivhd_devs((ACPI_IVRS_DE_HEADER *)(addr + 1),
2075
(char *)addr + addr->Header.Length);
2076
}
2077
2078
static const char *
2079
acpi_handle_ivrs_ivmd_type(ACPI_IVRS_MEMORY *addr)
2080
{
2081
switch (addr->Header.Type) {
2082
case ACPI_IVRS_TYPE_MEMORY1:
2083
return ("ALL");
2084
case ACPI_IVRS_TYPE_MEMORY2:
2085
return ("specified");
2086
case ACPI_IVRS_TYPE_MEMORY3:
2087
return ("range");
2088
default:
2089
return ("unknown");
2090
}
2091
}
2092
2093
static void
2094
acpi_handle_ivrs_ivmd(ACPI_IVRS_MEMORY *addr)
2095
{
2096
UINT16 x16;
2097
2098
printf("\tMem Type=%#x(%s) ",
2099
addr->Header.Type, acpi_handle_ivrs_ivmd_type(addr));
2100
switch (addr->Header.Type) {
2101
case ACPI_IVRS_TYPE_MEMORY2:
2102
memcpy(&x16, &addr->Reserved, sizeof(x16));
2103
printf("Id=%#06x PCISeg=%#x ", addr->Header.DeviceId, x16);
2104
break;
2105
case ACPI_IVRS_TYPE_MEMORY3:
2106
memcpy(&x16, &addr->Reserved, sizeof(x16));
2107
printf("Id=%#06x-%#06x PCISeg=%#x", addr->Header.DeviceId,
2108
addr->AuxData, x16);
2109
break;
2110
}
2111
printf("Start=%#18jx Length=%#jx Flags=",
2112
(uintmax_t)addr->StartAddress, (uintmax_t)addr->MemoryLength);
2113
#define PRINTFLAG(flag, name) printflag(addr->Header.Flags, flag, #name)
2114
PRINTFLAG(ACPI_IVMD_EXCLUSION_RANGE, ExclusionRange);
2115
PRINTFLAG(ACPI_IVMD_WRITE, IW);
2116
PRINTFLAG(ACPI_IVMD_READ, IR);
2117
PRINTFLAG(ACPI_IVMD_UNITY, Unity);
2118
#undef PRINTFLAG
2119
PRINTFLAG_END();
2120
}
2121
2122
static int
2123
acpi_handle_ivrs_blocks(void *addr, int remaining, bool efrsup)
2124
{
2125
ACPI_IVRS_HEADER *hdr = addr;
2126
2127
if (remaining < (int)sizeof(ACPI_IVRS_HEADER))
2128
return (-1);
2129
2130
if (remaining < hdr->Length)
2131
return (-1);
2132
2133
switch (hdr->Type) {
2134
case ACPI_IVRS_TYPE_HARDWARE1:
2135
acpi_handle_ivrs_ivhd_10(addr, efrsup);
2136
break;
2137
case ACPI_IVRS_TYPE_HARDWARE2:
2138
if (!efrsup)
2139
printf("\t!! Found IVHD block 0x11 but !EFRsup\n");
2140
acpi_handle_ivrs_ivhd_11(addr);
2141
break;
2142
case ACPI_IVRS_TYPE_HARDWARE3:
2143
if (!efrsup)
2144
printf("\t!! Found IVHD block 0x40 but !EFRsup\n");
2145
acpi_handle_ivrs_ivhd_40(addr);
2146
break;
2147
case ACPI_IVRS_TYPE_MEMORY1:
2148
case ACPI_IVRS_TYPE_MEMORY2:
2149
case ACPI_IVRS_TYPE_MEMORY3:
2150
acpi_handle_ivrs_ivmd(addr);
2151
break;
2152
default:
2153
printf("\n");
2154
printf("\tType=%d\n", hdr->Type);
2155
printf("\tLength=%d\n", hdr->Length);
2156
break;
2157
}
2158
return (hdr->Length);
2159
}
2160
2161
#define ACPI_IVRS_DMAREMAP 0x00000002
2162
#define ACPI_IVRS_EFRSUP 0x00000001
2163
#define ACPI_IVRS_GVA_SIZE 0x000000e0
2164
2165
static void
2166
acpi_handle_ivrs(ACPI_TABLE_HEADER *sdp)
2167
{
2168
ACPI_TABLE_IVRS *ivrs;
2169
char *cp;
2170
int remaining, consumed;
2171
bool efrsup;
2172
2173
printf(BEGIN_COMMENT);
2174
acpi_print_sdt(sdp);
2175
ivrs = (ACPI_TABLE_IVRS *)sdp;
2176
efrsup = (ivrs->Info & ACPI_IVRS_EFRSUP) != 0;
2177
printf("\tVAsize=%d PAsize=%d GVAsize=%d\n",
2178
(ivrs->Info & ACPI_IVRS_VIRTUAL_SIZE) >> 15,
2179
(ivrs->Info & ACPI_IVRS_PHYSICAL_SIZE) >> 8,
2180
(ivrs->Info & ACPI_IVRS_GVA_SIZE) >> 5);
2181
printf("\tATS_resp_res=%d DMA_preboot_remap=%d EFRsup=%d\n",
2182
(ivrs->Info & ACPI_IVRS_ATS_RESERVED) != 0,
2183
(ivrs->Info & ACPI_IVRS_DMAREMAP) != 0, efrsup);
2184
2185
remaining = sdp->Length - sizeof(ACPI_TABLE_IVRS);
2186
while (remaining > 0) {
2187
cp = (char *)sdp + sdp->Length - remaining;
2188
consumed = acpi_handle_ivrs_blocks(cp, remaining, efrsup);
2189
if (consumed <= 0)
2190
break;
2191
else
2192
remaining -= consumed;
2193
}
2194
2195
printf(END_COMMENT);
2196
}
2197
2198
static void
2199
acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
2200
{
2201
2202
printf("\tFlags={");
2203
if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
2204
printf("ENABLED");
2205
else
2206
printf("DISABLED");
2207
if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
2208
printf(",HOT_PLUGGABLE");
2209
if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
2210
printf(",NON_VOLATILE");
2211
printf("}\n");
2212
printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
2213
printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
2214
printf("\tProximity Domain=%d\n", mp->ProximityDomain);
2215
}
2216
2217
static const char *srat_types[] = {
2218
[ACPI_SRAT_TYPE_CPU_AFFINITY] = "CPU",
2219
[ACPI_SRAT_TYPE_MEMORY_AFFINITY] = "Memory",
2220
[ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY] = "X2APIC",
2221
[ACPI_SRAT_TYPE_GICC_AFFINITY] = "GICC",
2222
[ACPI_SRAT_TYPE_GIC_ITS_AFFINITY] = "GIC ITS",
2223
};
2224
2225
static void
2226
acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
2227
{
2228
ACPI_SRAT_CPU_AFFINITY *cpu;
2229
ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
2230
ACPI_SRAT_GICC_AFFINITY *gic;
2231
2232
if (srat->Type < nitems(srat_types))
2233
printf("\tType=%s\n", srat_types[srat->Type]);
2234
else
2235
printf("\tType=%d (unknown)\n", srat->Type);
2236
switch (srat->Type) {
2237
case ACPI_SRAT_TYPE_CPU_AFFINITY:
2238
cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
2239
acpi_print_srat_cpu(cpu->ApicId,
2240
cpu->ProximityDomainHi[2] << 24 |
2241
cpu->ProximityDomainHi[1] << 16 |
2242
cpu->ProximityDomainHi[0] << 0 |
2243
cpu->ProximityDomainLo, cpu->Flags);
2244
break;
2245
case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
2246
acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
2247
break;
2248
case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
2249
x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
2250
acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
2251
x2apic->Flags);
2252
break;
2253
case ACPI_SRAT_TYPE_GICC_AFFINITY:
2254
gic = (ACPI_SRAT_GICC_AFFINITY *)srat;
2255
acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain,
2256
gic->Flags);
2257
break;
2258
}
2259
}
2260
2261
static void
2262
acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
2263
{
2264
ACPI_TABLE_SRAT *srat;
2265
2266
printf(BEGIN_COMMENT);
2267
acpi_print_sdt(sdp);
2268
srat = (ACPI_TABLE_SRAT *)sdp;
2269
printf("\tTable Revision=%d\n", srat->TableRevision);
2270
acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
2271
printf(END_COMMENT);
2272
}
2273
2274
static const char *nfit_types[] = {
2275
[ACPI_NFIT_TYPE_SYSTEM_ADDRESS] = "System Address",
2276
[ACPI_NFIT_TYPE_MEMORY_MAP] = "Memory Map",
2277
[ACPI_NFIT_TYPE_INTERLEAVE] = "Interleave",
2278
[ACPI_NFIT_TYPE_SMBIOS] = "SMBIOS",
2279
[ACPI_NFIT_TYPE_CONTROL_REGION] = "Control Region",
2280
[ACPI_NFIT_TYPE_DATA_REGION] = "Data Region",
2281
[ACPI_NFIT_TYPE_FLUSH_ADDRESS] = "Flush Address",
2282
[ACPI_NFIT_TYPE_CAPABILITIES] = "Platform Capabilities"
2283
};
2284
2285
2286
static void
2287
acpi_print_nfit(ACPI_NFIT_HEADER *nfit)
2288
{
2289
char *uuidstr;
2290
uint32_t m, status;
2291
2292
ACPI_NFIT_SYSTEM_ADDRESS *sysaddr;
2293
ACPI_NFIT_MEMORY_MAP *mmap;
2294
ACPI_NFIT_INTERLEAVE *ileave;
2295
ACPI_NFIT_CONTROL_REGION *ctlreg;
2296
ACPI_NFIT_DATA_REGION *datareg;
2297
ACPI_NFIT_FLUSH_ADDRESS *fladdr;
2298
ACPI_NFIT_CAPABILITIES *caps;
2299
2300
if (nfit->Type < nitems(nfit_types))
2301
printf("\tType=%s\n", nfit_types[nfit->Type]);
2302
else
2303
printf("\tType=%u (unknown)\n", nfit->Type);
2304
switch (nfit->Type) {
2305
case ACPI_NFIT_TYPE_SYSTEM_ADDRESS:
2306
sysaddr = (ACPI_NFIT_SYSTEM_ADDRESS *)nfit;
2307
printf("\tRangeIndex=%u\n", (u_int)sysaddr->RangeIndex);
2308
printf("\tProximityDomain=%u\n",
2309
(u_int)sysaddr->ProximityDomain);
2310
uuid_to_string((uuid_t *)(uintptr_t)(sysaddr->RangeGuid),
2311
&uuidstr, &status);
2312
if (status != uuid_s_ok)
2313
errx(1, "uuid_to_string: status=%u", status);
2314
printf("\tRangeGuid=%s\n", uuidstr);
2315
free(uuidstr);
2316
printf("\tAddress=0x%016jx\n", (uintmax_t)sysaddr->Address);
2317
printf("\tLength=0x%016jx\n", (uintmax_t)sysaddr->Length);
2318
printf("\tMemoryMapping=0x%016jx\n",
2319
(uintmax_t)sysaddr->MemoryMapping);
2320
2321
#define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_## flag, #flag)
2322
2323
printf("\tFlags=");
2324
PRINTFLAG(sysaddr->Flags, ADD_ONLINE_ONLY);
2325
PRINTFLAG(sysaddr->Flags, PROXIMITY_VALID);
2326
PRINTFLAG_END();
2327
2328
#undef PRINTFLAG
2329
2330
break;
2331
case ACPI_NFIT_TYPE_MEMORY_MAP:
2332
mmap = (ACPI_NFIT_MEMORY_MAP *)nfit;
2333
printf("\tDeviceHandle=0x%x\n", (u_int)mmap->DeviceHandle);
2334
printf("\tPhysicalId=0x%04x\n", (u_int)mmap->PhysicalId);
2335
printf("\tRegionId=%u\n", (u_int)mmap->RegionId);
2336
printf("\tRangeIndex=%u\n", (u_int)mmap->RangeIndex);
2337
printf("\tRegionIndex=%u\n", (u_int)mmap->RegionIndex);
2338
printf("\tRegionSize=0x%016jx\n", (uintmax_t)mmap->RegionSize);
2339
printf("\tRegionOffset=0x%016jx\n",
2340
(uintmax_t)mmap->RegionOffset);
2341
printf("\tAddress=0x%016jx\n", (uintmax_t)mmap->Address);
2342
printf("\tInterleaveIndex=%u\n", (u_int)mmap->InterleaveIndex);
2343
printf("\tInterleaveWays=%u\n", (u_int)mmap->InterleaveWays);
2344
2345
#define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_MEM_## flag, #flag)
2346
2347
printf("\tFlags=");
2348
PRINTFLAG(mmap->Flags, SAVE_FAILED);
2349
PRINTFLAG(mmap->Flags, RESTORE_FAILED);
2350
PRINTFLAG(mmap->Flags, FLUSH_FAILED);
2351
PRINTFLAG(mmap->Flags, NOT_ARMED);
2352
PRINTFLAG(mmap->Flags, HEALTH_OBSERVED);
2353
PRINTFLAG(mmap->Flags, HEALTH_ENABLED);
2354
PRINTFLAG(mmap->Flags, MAP_FAILED);
2355
PRINTFLAG_END();
2356
2357
#undef PRINTFLAG
2358
2359
break;
2360
case ACPI_NFIT_TYPE_INTERLEAVE:
2361
ileave = (ACPI_NFIT_INTERLEAVE *)nfit;
2362
printf("\tInterleaveIndex=%u\n",
2363
(u_int)ileave->InterleaveIndex);
2364
printf("\tLineCount=%u\n", (u_int)ileave->LineCount);
2365
printf("\tLineSize=%u\n", (u_int)ileave->LineSize);
2366
for (m = 0; m < ileave->LineCount; m++) {
2367
printf("\tLine%uOffset=0x%08x\n", (u_int)m + 1,
2368
(u_int)ileave->LineOffset[m]);
2369
}
2370
break;
2371
case ACPI_NFIT_TYPE_SMBIOS:
2372
/* XXX smbios->Data[x] output is not supported */
2373
break;
2374
case ACPI_NFIT_TYPE_CONTROL_REGION:
2375
ctlreg = (ACPI_NFIT_CONTROL_REGION *)nfit;
2376
printf("\tRegionIndex=%u\n", (u_int)ctlreg->RegionIndex);
2377
printf("\tVendorId=0x%04x\n", (u_int)ctlreg->VendorId);
2378
printf("\tDeviceId=0x%04x\n", (u_int)ctlreg->DeviceId);
2379
printf("\tRevisionId=0x%02x\n", (u_int)ctlreg->RevisionId);
2380
printf("\tSubsystemVendorId=0x%04x\n",
2381
(u_int)ctlreg->SubsystemVendorId);
2382
printf("\tSubsystemDeviceId=0x%04x\n",
2383
(u_int)ctlreg->SubsystemDeviceId);
2384
printf("\tSubsystemRevisionId=0x%02x\n",
2385
(u_int)ctlreg->SubsystemRevisionId);
2386
printf("\tValidFields=0x%02x\n", (u_int)ctlreg->ValidFields);
2387
printf("\tManufacturingLocation=0x%02x\n",
2388
(u_int)ctlreg->ManufacturingLocation);
2389
printf("\tManufacturingDate=%04x\n",
2390
(u_int)be16toh(ctlreg->ManufacturingDate));
2391
printf("\tSerialNumber=%08X\n",
2392
(u_int)be32toh(ctlreg->SerialNumber));
2393
printf("\tCode=0x%04x\n", (u_int)ctlreg->Code);
2394
printf("\tWindows=%u\n", (u_int)ctlreg->Windows);
2395
printf("\tWindowSize=0x%016jx\n",
2396
(uintmax_t)ctlreg->WindowSize);
2397
printf("\tCommandOffset=0x%016jx\n",
2398
(uintmax_t)ctlreg->CommandOffset);
2399
printf("\tCommandSize=0x%016jx\n",
2400
(uintmax_t)ctlreg->CommandSize);
2401
printf("\tStatusOffset=0x%016jx\n",
2402
(uintmax_t)ctlreg->StatusOffset);
2403
printf("\tStatusSize=0x%016jx\n",
2404
(uintmax_t)ctlreg->StatusSize);
2405
2406
#define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_## flag, #flag)
2407
2408
printf("\tFlags=");
2409
PRINTFLAG(ctlreg->Flags, CONTROL_BUFFERED);
2410
PRINTFLAG_END();
2411
2412
#undef PRINTFLAG
2413
2414
break;
2415
case ACPI_NFIT_TYPE_DATA_REGION:
2416
datareg = (ACPI_NFIT_DATA_REGION *)nfit;
2417
printf("\tRegionIndex=%u\n", (u_int)datareg->RegionIndex);
2418
printf("\tWindows=%u\n", (u_int)datareg->Windows);
2419
printf("\tOffset=0x%016jx\n", (uintmax_t)datareg->Offset);
2420
printf("\tSize=0x%016jx\n", (uintmax_t)datareg->Size);
2421
printf("\tCapacity=0x%016jx\n", (uintmax_t)datareg->Capacity);
2422
printf("\tStartAddress=0x%016jx\n",
2423
(uintmax_t)datareg->StartAddress);
2424
break;
2425
case ACPI_NFIT_TYPE_FLUSH_ADDRESS:
2426
fladdr = (ACPI_NFIT_FLUSH_ADDRESS *)nfit;
2427
printf("\tDeviceHandle=%u\n", (u_int)fladdr->DeviceHandle);
2428
printf("\tHintCount=%u\n", (u_int)fladdr->HintCount);
2429
for (m = 0; m < fladdr->HintCount; m++) {
2430
printf("\tHintAddress%u=0x%016jx\n", (u_int)m + 1,
2431
(uintmax_t)fladdr->HintAddress[m]);
2432
}
2433
break;
2434
case ACPI_NFIT_TYPE_CAPABILITIES:
2435
caps = (ACPI_NFIT_CAPABILITIES *)nfit;
2436
printf("\tHighestCapability=%u\n", (u_int)caps->HighestCapability);
2437
2438
#define PRINTFLAG(var, flag) printflag((var), ACPI_NFIT_CAPABILITY_## flag, #flag)
2439
2440
printf("\tCapabilities=");
2441
PRINTFLAG(caps->Capabilities, CACHE_FLUSH);
2442
PRINTFLAG(caps->Capabilities, MEM_FLUSH);
2443
PRINTFLAG(caps->Capabilities, MEM_MIRRORING);
2444
PRINTFLAG_END();
2445
2446
#undef PRINTFLAG
2447
break;
2448
}
2449
}
2450
2451
static void
2452
acpi_handle_nfit(ACPI_TABLE_HEADER *sdp)
2453
{
2454
ACPI_TABLE_NFIT *nfit;
2455
2456
printf(BEGIN_COMMENT);
2457
acpi_print_sdt(sdp);
2458
nfit = (ACPI_TABLE_NFIT *)sdp;
2459
acpi_walk_nfit(sdp, (nfit + 1), acpi_print_nfit);
2460
printf(END_COMMENT);
2461
}
2462
2463
static void
2464
acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
2465
{
2466
printf(" ");
2467
acpi_print_string(sdp->Signature, ACPI_NAMESEG_SIZE);
2468
printf(": Length=%d, Revision=%d, Checksum=%d,\n",
2469
sdp->Length, sdp->Revision, sdp->Checksum);
2470
printf("\tOEMID=");
2471
acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
2472
printf(", OEM Table ID=");
2473
acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
2474
printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
2475
printf("\tCreator ID=");
2476
acpi_print_string(sdp->AslCompilerId, ACPI_NAMESEG_SIZE);
2477
printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
2478
}
2479
2480
static void
2481
acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
2482
{
2483
ACPI_TABLE_RSDT *rsdt;
2484
ACPI_TABLE_XSDT *xsdt;
2485
int i, entries;
2486
2487
rsdt = (ACPI_TABLE_RSDT *)rsdp;
2488
xsdt = (ACPI_TABLE_XSDT *)rsdp;
2489
printf(BEGIN_COMMENT);
2490
acpi_print_sdt(rsdp);
2491
entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
2492
printf("\tEntries={ ");
2493
for (i = 0; i < entries; i++) {
2494
if (i > 0)
2495
printf(", ");
2496
if (addr_size == 4)
2497
printf("0x%08x", le32toh(rsdt->TableOffsetEntry[i]));
2498
else
2499
printf("0x%016jx",
2500
(uintmax_t)le64toh(xsdt->TableOffsetEntry[i]));
2501
}
2502
printf(" }\n");
2503
printf(END_COMMENT);
2504
}
2505
2506
static const char *acpi_pm_profiles[] = {
2507
"Unspecified", "Desktop", "Mobile", "Workstation",
2508
"Enterprise Server", "SOHO Server", "Appliance PC"
2509
};
2510
2511
static void
2512
acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
2513
{
2514
ACPI_TABLE_FADT *fadt;
2515
const char *pm;
2516
2517
fadt = (ACPI_TABLE_FADT *)sdp;
2518
printf(BEGIN_COMMENT);
2519
acpi_print_sdt(sdp);
2520
printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
2521
fadt->Dsdt);
2522
printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
2523
if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
2524
pm = "Reserved";
2525
else
2526
pm = acpi_pm_profiles[fadt->PreferredProfile];
2527
printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
2528
printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
2529
printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
2530
printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
2531
printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
2532
printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
2533
printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
2534
printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
2535
fadt->Pm1aEventBlock,
2536
fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
2537
if (fadt->Pm1bEventBlock != 0)
2538
printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
2539
fadt->Pm1bEventBlock,
2540
fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
2541
printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
2542
fadt->Pm1aControlBlock,
2543
fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
2544
if (fadt->Pm1bControlBlock != 0)
2545
printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
2546
fadt->Pm1bControlBlock,
2547
fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
2548
if (fadt->Pm2ControlBlock != 0)
2549
printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
2550
fadt->Pm2ControlBlock,
2551
fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
2552
printf("\tPM_TMR_BLK=0x%x-0x%x\n",
2553
fadt->PmTimerBlock,
2554
fadt->PmTimerBlock + fadt->PmTimerLength - 1);
2555
if (fadt->Gpe0Block != 0)
2556
printf("\tGPE0_BLK=0x%x-0x%x\n",
2557
fadt->Gpe0Block,
2558
fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
2559
if (fadt->Gpe1Block != 0)
2560
printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
2561
fadt->Gpe1Block,
2562
fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
2563
fadt->Gpe1Base);
2564
if (fadt->CstControl != 0)
2565
printf("\tCST_CNT=0x%x\n", fadt->CstControl);
2566
printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
2567
fadt->C2Latency, fadt->C3Latency);
2568
printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
2569
fadt->FlushSize, fadt->FlushStride);
2570
printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
2571
fadt->DutyOffset, fadt->DutyWidth);
2572
printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
2573
fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
2574
2575
#define PRINTFLAG(var, flag) printflag((var), ACPI_FADT_## flag, #flag)
2576
2577
printf("\tIAPC_BOOT_ARCH=");
2578
PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
2579
PRINTFLAG(fadt->BootFlags, 8042);
2580
PRINTFLAG(fadt->BootFlags, NO_VGA);
2581
PRINTFLAG(fadt->BootFlags, NO_MSI);
2582
PRINTFLAG(fadt->BootFlags, NO_ASPM);
2583
PRINTFLAG(fadt->BootFlags, NO_CMOS_RTC);
2584
PRINTFLAG_END();
2585
2586
printf("\tFlags=");
2587
PRINTFLAG(fadt->Flags, WBINVD);
2588
PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
2589
PRINTFLAG(fadt->Flags, C1_SUPPORTED);
2590
PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
2591
PRINTFLAG(fadt->Flags, POWER_BUTTON);
2592
PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
2593
PRINTFLAG(fadt->Flags, FIXED_RTC);
2594
PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
2595
PRINTFLAG(fadt->Flags, 32BIT_TIMER);
2596
PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
2597
PRINTFLAG(fadt->Flags, RESET_REGISTER);
2598
PRINTFLAG(fadt->Flags, SEALED_CASE);
2599
PRINTFLAG(fadt->Flags, HEADLESS);
2600
PRINTFLAG(fadt->Flags, SLEEP_TYPE);
2601
PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
2602
PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
2603
PRINTFLAG(fadt->Flags, S4_RTC_VALID);
2604
PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
2605
PRINTFLAG(fadt->Flags, APIC_CLUSTER);
2606
PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
2607
PRINTFLAG(fadt->Flags, HW_REDUCED);
2608
PRINTFLAG(fadt->Flags, LOW_POWER_S0);
2609
PRINTFLAG_END();
2610
2611
#undef PRINTFLAG
2612
2613
if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
2614
printf("\tRESET_REG=");
2615
acpi_print_gas(&fadt->ResetRegister);
2616
printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
2617
}
2618
if (acpi_get_fadt_revision(fadt) > 1) {
2619
printf("\tX_FACS=0x%016jx, ", (uintmax_t)fadt->XFacs);
2620
printf("X_DSDT=0x%016jx\n", (uintmax_t)fadt->XDsdt);
2621
printf("\tX_PM1a_EVT_BLK=");
2622
acpi_print_gas(&fadt->XPm1aEventBlock);
2623
if (fadt->XPm1bEventBlock.Address != 0) {
2624
printf("\n\tX_PM1b_EVT_BLK=");
2625
acpi_print_gas(&fadt->XPm1bEventBlock);
2626
}
2627
printf("\n\tX_PM1a_CNT_BLK=");
2628
acpi_print_gas(&fadt->XPm1aControlBlock);
2629
if (fadt->XPm1bControlBlock.Address != 0) {
2630
printf("\n\tX_PM1b_CNT_BLK=");
2631
acpi_print_gas(&fadt->XPm1bControlBlock);
2632
}
2633
if (fadt->XPm2ControlBlock.Address != 0) {
2634
printf("\n\tX_PM2_CNT_BLK=");
2635
acpi_print_gas(&fadt->XPm2ControlBlock);
2636
}
2637
printf("\n\tX_PM_TMR_BLK=");
2638
acpi_print_gas(&fadt->XPmTimerBlock);
2639
if (fadt->XGpe0Block.Address != 0) {
2640
printf("\n\tX_GPE0_BLK=");
2641
acpi_print_gas(&fadt->XGpe0Block);
2642
}
2643
if (fadt->XGpe1Block.Address != 0) {
2644
printf("\n\tX_GPE1_BLK=");
2645
acpi_print_gas(&fadt->XGpe1Block);
2646
}
2647
printf("\n");
2648
}
2649
2650
printf(END_COMMENT);
2651
}
2652
2653
static void
2654
acpi_print_facs(ACPI_TABLE_FACS *facs)
2655
{
2656
printf(BEGIN_COMMENT);
2657
printf(" FACS:\tLength=%u, ", facs->Length);
2658
printf("HwSig=0x%08x, ", facs->HardwareSignature);
2659
printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
2660
2661
printf("\tGlobal_Lock=");
2662
if (facs->GlobalLock != 0) {
2663
if (facs->GlobalLock & ACPI_GLOCK_PENDING)
2664
printf("PENDING,");
2665
if (facs->GlobalLock & ACPI_GLOCK_OWNED)
2666
printf("OWNED");
2667
}
2668
printf("\n");
2669
2670
printf("\tFlags=");
2671
if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
2672
printf("S4BIOS");
2673
printf("\n");
2674
2675
if (facs->XFirmwareWakingVector != 0)
2676
printf("\tX_Firm_Wake_Vec=%016jx\n",
2677
(uintmax_t)facs->XFirmwareWakingVector);
2678
printf("\tVersion=%u\n", facs->Version);
2679
2680
printf(END_COMMENT);
2681
}
2682
2683
static void
2684
acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
2685
{
2686
printf(BEGIN_COMMENT);
2687
acpi_print_sdt(dsdp);
2688
printf(END_COMMENT);
2689
}
2690
2691
int
2692
acpi_checksum(void *p, size_t length)
2693
{
2694
uint8_t *bp;
2695
uint8_t sum;
2696
2697
bp = p;
2698
sum = 0;
2699
while (length--)
2700
sum += *bp++;
2701
2702
return (sum);
2703
}
2704
2705
static ACPI_TABLE_HEADER *
2706
acpi_map_sdt(vm_offset_t pa)
2707
{
2708
ACPI_TABLE_HEADER *sp;
2709
2710
sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
2711
sp = acpi_map_physical(pa, sp->Length);
2712
return (sp);
2713
}
2714
2715
static void
2716
acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
2717
{
2718
printf(BEGIN_COMMENT);
2719
printf(" RSD PTR: OEM=");
2720
acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
2721
printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
2722
rp->Revision);
2723
if (rp->Revision < 2) {
2724
printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
2725
rp->Checksum);
2726
} else {
2727
printf("\tXSDT=0x%016jx, length=%u, cksum=%u\n",
2728
(uintmax_t)rp->XsdtPhysicalAddress, rp->Length,
2729
rp->ExtendedChecksum);
2730
}
2731
printf(END_COMMENT);
2732
}
2733
2734
static const struct {
2735
const char *sig;
2736
void (*fnp)(ACPI_TABLE_HEADER *);
2737
} known[] = {
2738
{ ACPI_SIG_BERT, acpi_handle_bert },
2739
{ ACPI_SIG_DMAR, acpi_handle_dmar },
2740
{ ACPI_SIG_ECDT, acpi_handle_ecdt },
2741
{ ACPI_SIG_EINJ, acpi_handle_einj },
2742
{ ACPI_SIG_ERST, acpi_handle_erst },
2743
{ ACPI_SIG_FADT, acpi_handle_fadt },
2744
{ ACPI_SIG_HEST, acpi_handle_hest },
2745
{ ACPI_SIG_HPET, acpi_handle_hpet },
2746
{ ACPI_SIG_IVRS, acpi_handle_ivrs },
2747
{ ACPI_SIG_LPIT, acpi_handle_lpit },
2748
{ ACPI_SIG_MADT, acpi_handle_madt },
2749
{ ACPI_SIG_MCFG, acpi_handle_mcfg },
2750
{ ACPI_SIG_NFIT, acpi_handle_nfit },
2751
{ ACPI_SIG_SLIT, acpi_handle_slit },
2752
{ ACPI_SIG_SPCR, acpi_handle_spcr },
2753
{ ACPI_SIG_SRAT, acpi_handle_srat },
2754
{ ACPI_SIG_TCPA, acpi_handle_tcpa },
2755
{ ACPI_SIG_TPM2, acpi_handle_tpm2 },
2756
{ ACPI_SIG_WDDT, acpi_handle_wddt },
2757
};
2758
2759
static void
2760
acpi_report_sdp(ACPI_TABLE_HEADER *sdp)
2761
{
2762
for (u_int i = 0; i < nitems(known); i++) {
2763
if (memcmp(sdp->Signature, known[i].sig, ACPI_NAMESEG_SIZE)
2764
== 0) {
2765
known[i].fnp(sdp);
2766
return;
2767
}
2768
}
2769
2770
/*
2771
* Otherwise, do a generic thing.
2772
*/
2773
printf(BEGIN_COMMENT);
2774
acpi_print_sdt(sdp);
2775
printf(END_COMMENT);
2776
}
2777
2778
static void
2779
acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp, const char *tbl)
2780
{
2781
ACPI_TABLE_HEADER *sdp;
2782
ACPI_TABLE_RSDT *rsdt;
2783
ACPI_TABLE_XSDT *xsdt;
2784
vm_offset_t addr;
2785
int entries, i;
2786
2787
if (tbl == NULL) {
2788
acpi_print_rsdt(rsdp);
2789
} else {
2790
if (memcmp(tbl, rsdp->Signature, ACPI_NAMESEG_SIZE) == 0) {
2791
acpi_print_rsdt(rsdp);
2792
return;
2793
}
2794
}
2795
rsdt = (ACPI_TABLE_RSDT *)rsdp;
2796
xsdt = (ACPI_TABLE_XSDT *)rsdp;
2797
entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
2798
for (i = 0; i < entries; i++) {
2799
if (addr_size == 4)
2800
addr = le32toh(rsdt->TableOffsetEntry[i]);
2801
else
2802
addr = le64toh(xsdt->TableOffsetEntry[i]);
2803
if (addr == 0)
2804
continue;
2805
sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
2806
if (acpi_checksum(sdp, sdp->Length)) {
2807
warnx("RSDT entry %d (sig %.4s) is corrupt", i,
2808
sdp->Signature);
2809
continue;
2810
}
2811
if (tbl != NULL && memcmp(sdp->Signature, tbl, ACPI_NAMESEG_SIZE) != 0)
2812
continue;
2813
acpi_report_sdp(sdp);
2814
}
2815
}
2816
2817
ACPI_TABLE_HEADER *
2818
sdt_load_devmem(void)
2819
{
2820
ACPI_TABLE_RSDP *rp;
2821
ACPI_TABLE_HEADER *rsdp;
2822
2823
rp = acpi_find_rsd_ptr();
2824
if (!rp)
2825
errx(1, "Can't find ACPI information");
2826
2827
if (tflag)
2828
acpi_print_rsd_ptr(rp);
2829
if (rp->Revision < 2) {
2830
rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
2831
if (memcmp(rsdp->Signature, "RSDT", ACPI_NAMESEG_SIZE) != 0 ||
2832
acpi_checksum(rsdp, rsdp->Length) != 0)
2833
errx(1, "RSDT is corrupted");
2834
addr_size = sizeof(uint32_t);
2835
} else {
2836
rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
2837
if (memcmp(rsdp->Signature, "XSDT", ACPI_NAMESEG_SIZE) != 0 ||
2838
acpi_checksum(rsdp, rsdp->Length) != 0)
2839
errx(1, "XSDT is corrupted");
2840
addr_size = sizeof(uint64_t);
2841
}
2842
return (rsdp);
2843
}
2844
2845
/* Write the DSDT to a file, concatenating any SSDTs (if present). */
2846
static int
2847
write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
2848
{
2849
ACPI_TABLE_HEADER sdt;
2850
ACPI_TABLE_HEADER *ssdt;
2851
uint8_t sum;
2852
2853
/* Create a new checksum to account for the DSDT and any SSDTs. */
2854
sdt = *dsdt;
2855
if (rsdt != NULL) {
2856
sdt.Checksum = 0;
2857
sum = acpi_checksum(dsdt + 1, dsdt->Length -
2858
sizeof(ACPI_TABLE_HEADER));
2859
ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
2860
while (ssdt != NULL) {
2861
sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
2862
sum += acpi_checksum(ssdt + 1,
2863
ssdt->Length - sizeof(ACPI_TABLE_HEADER));
2864
ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
2865
}
2866
sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
2867
sdt.Checksum -= sum;
2868
}
2869
2870
/* Write out the DSDT header and body. */
2871
write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
2872
write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
2873
2874
/* Write out any SSDTs (if present.) */
2875
if (rsdt != NULL) {
2876
ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
2877
while (ssdt != NULL) {
2878
write(fd, ssdt + 1, ssdt->Length -
2879
sizeof(ACPI_TABLE_HEADER));
2880
ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
2881
}
2882
}
2883
return (0);
2884
}
2885
2886
void
2887
dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
2888
{
2889
int fd;
2890
mode_t mode;
2891
2892
assert(outfile != NULL);
2893
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
2894
fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, mode);
2895
if (fd == -1) {
2896
perror("dsdt_save_file");
2897
return;
2898
}
2899
write_dsdt(fd, rsdt, dsdp);
2900
close(fd);
2901
}
2902
2903
void
2904
aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
2905
{
2906
char buf[PATH_MAX], tmpstr[PATH_MAX], wrkdir[PATH_MAX];
2907
const char *iname = "/acpdump.din";
2908
const char *oname = "/acpdump.dsl";
2909
const char *tmpdir;
2910
FILE *fp;
2911
size_t len;
2912
int fd, status;
2913
pid_t pid;
2914
2915
tmpdir = getenv("TMPDIR");
2916
if (tmpdir == NULL)
2917
tmpdir = _PATH_TMP;
2918
if (realpath(tmpdir, buf) == NULL) {
2919
perror("realpath tmp dir");
2920
return;
2921
}
2922
len = sizeof(wrkdir) - strlen(iname);
2923
if ((size_t)snprintf(wrkdir, len, "%s/acpidump.XXXXXX", buf) > len-1 ) {
2924
fprintf(stderr, "$TMPDIR too long\n");
2925
return;
2926
}
2927
if (mkdtemp(wrkdir) == NULL) {
2928
perror("mkdtemp tmp working dir");
2929
return;
2930
}
2931
len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, iname);
2932
assert(len <= sizeof(tmpstr) - 1);
2933
fd = open(tmpstr, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
2934
if (fd < 0) {
2935
perror("iasl tmp file");
2936
return;
2937
}
2938
write_dsdt(fd, rsdt, dsdp);
2939
close(fd);
2940
2941
/* Run iasl -d on the temp file */
2942
if ((pid = fork()) == 0) {
2943
close(STDOUT_FILENO);
2944
if (vflag == 0)
2945
close(STDERR_FILENO);
2946
execl("/usr/sbin/iasl", "iasl", "-d", tmpstr, NULL);
2947
err(1, "exec");
2948
}
2949
if (pid > 0)
2950
wait(&status);
2951
if (unlink(tmpstr) < 0) {
2952
perror("unlink");
2953
goto out;
2954
}
2955
if (pid < 0) {
2956
perror("fork");
2957
goto out;
2958
}
2959
if (status != 0) {
2960
fprintf(stderr, "iasl exit status = %d\n", status);
2961
}
2962
2963
/* Dump iasl's output to stdout */
2964
len = (size_t)snprintf(tmpstr, sizeof(tmpstr), "%s%s", wrkdir, oname);
2965
assert(len <= sizeof(tmpstr) - 1);
2966
fp = fopen(tmpstr, "r");
2967
if (unlink(tmpstr) < 0) {
2968
perror("unlink");
2969
goto out;
2970
}
2971
if (fp == NULL) {
2972
perror("iasl tmp file (read)");
2973
goto out;
2974
}
2975
while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
2976
fwrite(buf, 1, len, stdout);
2977
fclose(fp);
2978
2979
out:
2980
if (rmdir(wrkdir) < 0)
2981
perror("rmdir");
2982
}
2983
2984
void
2985
aml_disassemble_separate(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
2986
{
2987
ACPI_TABLE_HEADER *ssdt = NULL;
2988
2989
aml_disassemble(NULL, dsdp);
2990
if (rsdt != NULL) {
2991
for (;;) {
2992
ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
2993
if (ssdt == NULL)
2994
break;
2995
aml_disassemble(NULL, ssdt);
2996
}
2997
}
2998
}
2999
3000
void
3001
sdt_print_all(ACPI_TABLE_HEADER *rsdp, const char *tbl)
3002
{
3003
acpi_handle_rsdt(rsdp, tbl);
3004
}
3005
3006
/* Fetch a table matching the given signature via the RSDT. */
3007
ACPI_TABLE_HEADER *
3008
sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
3009
{
3010
ACPI_TABLE_HEADER *sdt;
3011
ACPI_TABLE_RSDT *rsdt;
3012
ACPI_TABLE_XSDT *xsdt;
3013
vm_offset_t addr;
3014
int entries, i;
3015
3016
rsdt = (ACPI_TABLE_RSDT *)rsdp;
3017
xsdt = (ACPI_TABLE_XSDT *)rsdp;
3018
entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
3019
for (i = 0; i < entries; i++) {
3020
if (addr_size == 4)
3021
addr = le32toh(rsdt->TableOffsetEntry[i]);
3022
else
3023
addr = le64toh(xsdt->TableOffsetEntry[i]);
3024
if (addr == 0)
3025
continue;
3026
sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
3027
if (last != NULL) {
3028
if (sdt == last)
3029
last = NULL;
3030
continue;
3031
}
3032
if (memcmp(sdt->Signature, sig, strlen(sig)))
3033
continue;
3034
if (acpi_checksum(sdt, sdt->Length))
3035
errx(1, "RSDT entry %d is corrupt", i);
3036
return (sdt);
3037
}
3038
3039
return (NULL);
3040
}
3041
3042
ACPI_TABLE_HEADER *
3043
dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
3044
{
3045
ACPI_TABLE_HEADER *sdt;
3046
3047
/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
3048
if (acpi_get_fadt_revision(fadt) == 1)
3049
sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
3050
else
3051
sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
3052
if (acpi_checksum(sdt, sdt->Length))
3053
errx(1, "DSDT is corrupt\n");
3054
return (sdt);
3055
}
3056
3057