From d1fb5651e5d7d2cf2b44a873785ed7bdedef282e Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Tue, 14 Jul 2020 17:23:25 +0000 Subject: [PATCH] MFC r362811: Decode APEI tables (BERT, EINJ, ERST, HEST). --- usr.sbin/acpi/acpidump/acpi.c | 295 ++++++++++++++++++++++++++++-- usr.sbin/acpi/acpidump/acpidump.8 | 10 +- 2 files changed, 290 insertions(+), 15 deletions(-) diff --git a/usr.sbin/acpi/acpidump/acpi.c b/usr.sbin/acpi/acpidump/acpi.c index 578a5886d50..61bdad11eb1 100644 --- a/usr.sbin/acpi/acpidump/acpi.c +++ b/usr.sbin/acpi/acpidump/acpi.c @@ -3,6 +3,7 @@ * * Copyright (c) 1998 Doug Rabson * Copyright (c) 2000 Mitsuru IWASAKI + * Copyright (c) 2020 Alexander Motin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -177,23 +178,17 @@ acpi_print_gas(ACPI_GENERIC_ADDRESS *gas) { switch(gas->SpaceId) { case ACPI_GAS_MEMORY: - if (gas->BitWidth <= 32) - printf("0x%08x:%u[%u] (Memory)", - (u_int)gas->Address, gas->BitOffset, - gas->BitWidth); - else - printf("0x%016jx:%u[%u] (Memory)", - (uintmax_t)gas->Address, gas->BitOffset, - gas->BitWidth); + printf("0x%016jx:%u[%u] (Memory)", (uintmax_t)gas->Address, + gas->BitOffset, gas->BitWidth); break; case ACPI_GAS_IO: - printf("0x%02x:%u[%u] (IO)", (u_int)gas->Address, + printf("0x%02jx:%u[%u] (IO)", (uintmax_t)gas->Address, gas->BitOffset, gas->BitWidth); break; case ACPI_GAS_PCI: - printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32), + printf("%x:%x+0x%x:%u[%u] (PCI)", (uint16_t)(gas->Address >> 32), (uint16_t)((gas->Address >> 16) & 0xffff), - (uint16_t)gas->Address); + (uint16_t)gas->Address, gas->BitOffset, gas->BitWidth); break; /* XXX How to handle these below? */ case ACPI_GAS_EMBEDDED: @@ -587,6 +582,269 @@ acpi_handle_madt(ACPI_TABLE_HEADER *sdp) printf(END_COMMENT); } +static void +acpi_handle_bert(ACPI_TABLE_HEADER *sdp) +{ + ACPI_TABLE_BERT *bert; + + printf(BEGIN_COMMENT); + acpi_print_sdt(sdp); + bert = (ACPI_TABLE_BERT *)sdp; + printf("\tRegionLength=%d\n", bert->RegionLength); + printf("\tAddress=0x%016jx\n", bert->Address); + printf(END_COMMENT); +} + +static void +acpi_print_whea(ACPI_WHEA_HEADER *w) +{ + + printf("\n\tAction=%d\n", w->Action); + printf("\tInstruction=%d\n", w->Instruction); + printf("\tFlags=%02x\n", w->Flags); + printf("\tRegisterRegion="); + acpi_print_gas(&w->RegisterRegion); + printf("\n\tValue=0x%016jx\n", w->Value); + printf("\tMask=0x%016jx\n", w->Mask); +} + +static void +acpi_handle_einj(ACPI_TABLE_HEADER *sdp) +{ + ACPI_TABLE_EINJ *einj; + ACPI_WHEA_HEADER *w; + u_int i; + + printf(BEGIN_COMMENT); + acpi_print_sdt(sdp); + einj = (ACPI_TABLE_EINJ *)sdp; + printf("\tHeaderLength=%d\n", einj->HeaderLength); + printf("\tFlags=0x%02x\n", einj->Flags); + printf("\tEntries=%d\n", einj->Entries); + w = (ACPI_WHEA_HEADER *)(einj + 1); + for (i = 0; i < MIN(einj->Entries, (sdp->Length - + sizeof(ACPI_TABLE_EINJ)) / sizeof(ACPI_WHEA_HEADER)); i++) + acpi_print_whea(w + i); + printf(END_COMMENT); +} + +static void +acpi_handle_erst(ACPI_TABLE_HEADER *sdp) +{ + ACPI_TABLE_ERST *erst; + ACPI_WHEA_HEADER *w; + u_int i; + + printf(BEGIN_COMMENT); + acpi_print_sdt(sdp); + erst = (ACPI_TABLE_ERST *)sdp; + printf("\tHeaderLength=%d\n", erst->HeaderLength); + printf("\tEntries=%d\n", erst->Entries); + w = (ACPI_WHEA_HEADER *)(erst + 1); + for (i = 0; i < MIN(erst->Entries, (sdp->Length - + sizeof(ACPI_TABLE_ERST)) / sizeof(ACPI_WHEA_HEADER)); i++) + acpi_print_whea(w + i); + printf(END_COMMENT); +} + +static void +acpi_print_hest_bank(ACPI_HEST_IA_ERROR_BANK *b) +{ + + printf("\tBank:\n"); + printf("\t\tBankNumber=%d\n", b->BankNumber); + printf("\t\tClearStatusOnInit=%d\n", b->ClearStatusOnInit); + printf("\t\tStatusFormat=%d\n", b->StatusFormat); + printf("\t\tControlRegister=%x\n", b->ControlRegister); + printf("\t\tControlData=%jx\n", b->ControlData); + printf("\t\tStatusRegister=%x\n", b->StatusRegister); + printf("\t\tAddressRegister=%x\n", b->AddressRegister); + printf("\t\tMiscRegister=%x\n", b->MiscRegister); +} + +static void +acpi_print_hest_notify(ACPI_HEST_NOTIFY *n) +{ + + printf("\t\tType=%d\n", n->Type); + printf("\t\tLength=%d\n", n->Length); + printf("\t\tConfigWriteEnable=%04x\n", n->ConfigWriteEnable); + printf("\t\tPollInterval=%d\n", n->PollInterval); + printf("\t\tVector=%d\n", n->Vector); + printf("\t\tPollingThresholdValue=%d\n", n->PollingThresholdValue); + printf("\t\tPollingThresholdWindow=%d\n", n->PollingThresholdWindow); + printf("\t\tErrorThresholdValue=%d\n", n->ErrorThresholdValue); + printf("\t\tErrorThresholdWindow=%d\n", n->ErrorThresholdWindow); +} + +static void +acpi_print_hest_aer(ACPI_HEST_AER_COMMON *a) +{ + + printf("\tFlags=%02x\n", a->Flags); + printf("\tEnabled=%d\n", a->Enabled); + printf("\tRecordsToPreallocate=%d\n", a->RecordsToPreallocate); + printf("\tMaxSectionsPerRecord=%d\n", a->MaxSectionsPerRecord); + printf("\tBus=%d\n", a->Bus); + printf("\tDevice=%d\n", a->Device); + printf("\tFunction=%d\n", a->Function); + printf("\tDeviceControl=%d\n", a->DeviceControl); + printf("\tUncorrectableMask=%d\n", a->UncorrectableMask); + printf("\tUncorrectableSeverity=%d\n", a->UncorrectableSeverity); + printf("\tCorrectableMask=%d\n", a->CorrectableMask); + printf("\tAdvancedCapabilities=%d\n", a->AdvancedCapabilities); +} + +static int +acpi_handle_hest_structure(void *addr, int remaining) +{ + ACPI_HEST_HEADER *hdr = addr; + int i; + + if (remaining < (int)sizeof(ACPI_HEST_HEADER)) + return (-1); + + printf("\n\tType=%d\n", hdr->Type); + printf("\tSourceId=%d\n", hdr->SourceId); + switch (hdr->Type) { + case ACPI_HEST_TYPE_IA32_CHECK: { + ACPI_HEST_IA_MACHINE_CHECK *s = addr; + printf("\tFlags=%02x\n", s->Flags); + printf("\tEnabled=%d\n", s->Enabled); + printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate); + printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord); + printf("\tGlobalCapabilityData=%jd\n", s->GlobalCapabilityData); + printf("\tGlobalControlData=%jd\n", s->GlobalControlData); + printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks); + for (i = 0; i < s->NumHardwareBanks; i++) { + acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *) + (s + 1) + i); + } + return (sizeof(*s) + s->NumHardwareBanks * + sizeof(ACPI_HEST_IA_ERROR_BANK)); + } + case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: { + ACPI_HEST_IA_CORRECTED *s = addr; + printf("\tFlags=%02x\n", s->Flags); + printf("\tEnabled=%d\n", s->Enabled); + printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate); + printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord); + printf("\tNotify:\n"); + acpi_print_hest_notify(&s->Notify); + printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks); + for (i = 0; i < s->NumHardwareBanks; i++) { + acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *) + (s + 1) + i); + } + return (sizeof(*s) + s->NumHardwareBanks * + sizeof(ACPI_HEST_IA_ERROR_BANK)); + } + case ACPI_HEST_TYPE_IA32_NMI: { + ACPI_HEST_IA_NMI *s = addr; + printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate); + printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord); + printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_AER_ROOT_PORT: { + ACPI_HEST_AER_ROOT *s = addr; + acpi_print_hest_aer(&s->Aer); + printf("\tRootErrorCommand=%d\n", s->RootErrorCommand); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_AER_ENDPOINT: { + ACPI_HEST_AER *s = addr; + acpi_print_hest_aer(&s->Aer); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_AER_BRIDGE: { + ACPI_HEST_AER_BRIDGE *s = addr; + acpi_print_hest_aer(&s->Aer); + printf("\tUncorrectableMask2=%d\n", s->UncorrectableMask2); + printf("\tUncorrectableSeverity2=%d\n", s->UncorrectableSeverity2); + printf("\tAdvancedCapabilities2=%d\n", s->AdvancedCapabilities2); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_GENERIC_ERROR: { + ACPI_HEST_GENERIC *s = addr; + printf("\tRelatedSourceId=%d\n", s->RelatedSourceId); + printf("\tEnabled=%d\n", s->Enabled); + printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate); + printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord); + printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength); + printf("\tErrorStatusAddress="); + acpi_print_gas(&s->ErrorStatusAddress); + printf("\n"); + printf("\tNotify:\n"); + acpi_print_hest_notify(&s->Notify); + printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_GENERIC_ERROR_V2: { + ACPI_HEST_GENERIC_V2 *s = addr; + printf("\tRelatedSourceId=%d\n", s->RelatedSourceId); + printf("\tEnabled=%d\n", s->Enabled); + printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate); + printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord); + printf("\tMaxRawDataLength=%d\n", s->MaxRawDataLength); + printf("\tErrorStatusAddress="); + acpi_print_gas(&s->ErrorStatusAddress); + printf("\n"); + printf("\tNotify:\n"); + acpi_print_hest_notify(&s->Notify); + printf("\tErrorBlockLength=%d\n", s->ErrorBlockLength); + printf("\tReadAckRegister="); + acpi_print_gas(&s->ReadAckRegister); + printf("\n"); + printf("\tReadAckPreserve=%jd\n", s->ReadAckPreserve); + printf("\tReadAckWrite=%jd\n", s->ReadAckWrite); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: { + ACPI_HEST_IA_DEFERRED_CHECK *s = addr; + printf("\tFlags=%02x\n", s->Flags); + printf("\tEnabled=%d\n", s->Enabled); + printf("\tRecordsToPreallocate=%d\n", s->RecordsToPreallocate); + printf("\tMaxSectionsPerRecord=%d\n", s->MaxSectionsPerRecord); + printf("\tNotify:\n"); + acpi_print_hest_notify(&s->Notify); + printf("\tNumHardwareBanks=%d\n", s->NumHardwareBanks); + for (i = 0; i < s->NumHardwareBanks; i++) { + acpi_print_hest_bank((ACPI_HEST_IA_ERROR_BANK *) + (s + 1) + i); + } + return (sizeof(*s) + s->NumHardwareBanks * + sizeof(ACPI_HEST_IA_ERROR_BANK)); + } + default: + return (-1); + } +} + +static void +acpi_handle_hest(ACPI_TABLE_HEADER *sdp) +{ + char *cp; + int remaining, consumed; + ACPI_TABLE_HEST *hest; + + printf(BEGIN_COMMENT); + acpi_print_sdt(sdp); + hest = (ACPI_TABLE_HEST *)sdp; + printf("\tErrorSourceCount=%d\n", hest->ErrorSourceCount); + + remaining = sdp->Length - sizeof(ACPI_TABLE_HEST); + while (remaining > 0) { + cp = (char *)sdp + sdp->Length - remaining; + consumed = acpi_handle_hest_structure(cp, remaining); + if (consumed <= 0) + break; + else + remaining -= consumed; + } + printf(END_COMMENT); +} + static void acpi_handle_hpet(ACPI_TABLE_HEADER *sdp) { @@ -598,7 +856,7 @@ acpi_handle_hpet(ACPI_TABLE_HEADER *sdp) printf("\tHPET Number=%d\n", hpet->Sequence); printf("\tADDR="); acpi_print_gas(&hpet->Address); - printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID); + printf("\n\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID); printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >> 8); printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ? @@ -721,13 +979,14 @@ acpi_print_native_lpit(ACPI_LPIT_NATIVE *nl) { printf("\tEntryTrigger="); acpi_print_gas(&nl->EntryTrigger); - printf("\tResidency=%u\n", nl->Residency); + printf("\n\tResidency=%u\n", nl->Residency); printf("\tLatency=%u\n", nl->Latency); if (nl->Header.Flags & ACPI_LPIT_NO_COUNTER) printf("\tResidencyCounter=Not Present"); else { printf("\tResidencyCounter="); acpi_print_gas(&nl->ResidencyCounter); + printf("\n"); } if (nl->CounterFrequency) printf("\tCounterFrequency=%ju\n", nl->CounterFrequency); @@ -1756,10 +2015,18 @@ acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp) sdp->Signature); continue; } - if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4)) + if (!memcmp(sdp->Signature, ACPI_SIG_BERT, 4)) + acpi_handle_bert(sdp); + else if (!memcmp(sdp->Signature, ACPI_SIG_EINJ, 4)) + acpi_handle_einj(sdp); + else if (!memcmp(sdp->Signature, ACPI_SIG_ERST, 4)) + acpi_handle_erst(sdp); + else if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4)) acpi_handle_fadt(sdp); else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4)) acpi_handle_madt(sdp); + else if (!memcmp(sdp->Signature, ACPI_SIG_HEST, 4)) + acpi_handle_hest(sdp); else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4)) acpi_handle_hpet(sdp); else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4)) diff --git a/usr.sbin/acpi/acpidump/acpidump.8 b/usr.sbin/acpi/acpidump/acpidump.8 index d98fd38d44f..438ef425b4d 100644 --- a/usr.sbin/acpi/acpidump/acpidump.8 +++ b/usr.sbin/acpi/acpidump/acpidump.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 10, 2018 +.Dd June 29, 2020 .Dt ACPIDUMP 8 .Os .Sh NAME @@ -97,11 +97,15 @@ flag, the utility dumps contents of the following tables: .Pp .Bl -tag -offset indent -width 12345 -compact +.It BERT .It DMAR .It DSDT .It ECDT +.It EINJ +.It ERST .It FACS .It FADT +.It HEST .It HPET .It LPIT .It MADT @@ -109,6 +113,10 @@ utility dumps contents of the following tables: .It NFIT .It RSD PTR .It RSDT +.It SLIT +.It SRAT +.It TCPA +.It TPM2 .It WDDT .El .Pp -- 2.45.0