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