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