summaryrefslogtreecommitdiff
path: root/ShellPkg
diff options
context:
space:
mode:
authorlevi.yun <yeoreum.yun@arm.com>2024-06-05 13:03:47 +0100
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-07-23 11:07:42 +0000
commitf96298d75cebfe2a7707157ed644eb86bf6d46ca (patch)
treecdda8c82e8c6885cfc120f7eec7cea0b66251e58 /ShellPkg
parent32e7f9aa6cdfe406034e2ce3f8714a968dae3a7c (diff)
downloadedk2-f96298d75cebfe2a7707157ed644eb86bf6d46ca.zip
edk2-f96298d75cebfe2a7707157ed644eb86bf6d46ca.tar.gz
edk2-f96298d75cebfe2a7707157ed644eb86bf6d46ca.tar.bz2
ShellPkg/Acpiview: Add HEST Parser
Add a new pareser for the Hardware Error Source Table (HEST). The HEST table is used to describe a system's hardware error sources to OSPM. Cc: Zhichao Gao <zhichao.gao@intel.com> Cc: Sami Mujawar <sami.mujawar@arm.com> Cc: Pierre Gondois <pierre.gondois@arm.com> Signed-off-by: levi.yun <yeoreum.yun@arm.com>
Diffstat (limited to 'ShellPkg')
-rw-r--r--ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h21
-rw-r--r--ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hest/HestParser.c958
-rw-r--r--ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c1
-rw-r--r--ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf3
4 files changed, 982 insertions, 1 deletions
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
index b41f110..b449ded 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
@@ -726,6 +726,27 @@ ParseAcpiGtdt (
);
/**
+ This function parses the ACPI HEST table.
+ When trace is enabled this function parses the HEST table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiHest (
+ IN BOOLEAN Trace,
+ IN UINT8 *Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ );
+
+/**
This function parses the ACPI HMAT table.
When trace is enabled this function parses the HMAT table and
traces the ACPI table fields.
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hest/HestParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hest/HestParser.c
new file mode 100644
index 0000000..9631634
--- /dev/null
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hest/HestParser.c
@@ -0,0 +1,958 @@
+/** @file
+ HEST table parser
+
+ Copyright (c) 2024, Arm Limited.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Specification Reference:
+ - ACPI 6.5, Table 18.3.2 ACPI Error Source
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiView.h"
+
+STATIC ACPI_DESCRIPTION_HEADER_INFO mAcpiHdrInfo;
+STATIC UINT32 *mHestErrorSourceCount;
+STATIC UINT16 *mHestErrorSourceType;
+STATIC UINT8 *mHestIA32HardwareBankCount;
+
+/**
+ An String array for Error Notification Structure's type.
+ Cf ACPI 6.5 Table 18.14: Hardware Error Notification Structure
+**/
+STATIC CONST CHAR16 *HestErrorNotificationStructureTypeStr[] = {
+ L"Polled",
+ L"External Interrupt",
+ L"Local Interrupt",
+ L"SCI",
+ L"NMI",
+ L"CMCI",
+ L"MCE",
+ L"GPIO-Signal",
+ L"ARMv8 SEA",
+ L"ARMv8 SEI",
+ L"External Interrupt - GSIV",
+ L"Software Delegated Exception",
+};
+
+/**
+ An ACPI_PARSER array describing the ACPI HEST Table.
+**/
+STATIC CONST ACPI_PARSER HestParser[] = {
+ PARSE_ACPI_HEADER (&mAcpiHdrInfo),
+ { L"Error Source Count", 4, 36, L"%d", NULL,
+ (VOID **)&mHestErrorSourceCount,NULL, NULL },
+ // Error Source Descriptor 1
+ // Error Source Descriptor Type
+ // Error Source Descriptor Data
+ // ...
+ // Error Source Descriptor 2
+ // Error Source Descriptor Type
+ // Error Source Descriptor Data
+ // ...
+ // ....
+ // Error Source Descriptor n
+ // Error Source Descriptor Type
+ // Error Source Descriptor Data
+ // ...
+};
+
+/**
+ An ACPI_PARSER array describing the HEST error source descriptor type.
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceTypeParser[] = {
+ { L"Type", 2, 0, L"%d", NULL, (VOID **)&mHestErrorSourceType, NULL, NULL },
+};
+
+/**
+ An ACPI_PARSER array describing the HEST error source flags information.
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceFlags[] = {
+ { L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL },
+ { L"Global", 1, 1, L"%d", NULL, NULL, NULL, NULL },
+ { L"GHES Assist", 1, 2, L"%d", NULL, NULL, NULL, NULL },
+ { L"Reserved", 5, 3, NULL, NULL, NULL, NULL, NULL }
+};
+
+/**
+ An ACPI_PARSER array describing IA-32 Architecture Machine Check Bank Structure
+ Cf ACPI 6.5 Table 18.4: IA-32 Architecture Machine Check Error Bank Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorIA32ArchMachineCheckBankStructureParser[] = {
+ { L"Bank Number", 1, 0, L"%d", NULL, NULL, NULL, NULL },
+ { L"Clear Status On Initialization", 1, 1, L"%d", NULL, NULL, NULL, NULL },
+ { L"Status Data Format", 1, 2, L"%d", NULL, NULL, NULL, NULL },
+ { L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL },
+ { L"Control Register MSR Address", 4, 4, L"0x%lx", NULL, NULL, NULL, NULL },
+ { L"Control Init Data", 8, 8, L"0x%llx", NULL, NULL, NULL, NULL },
+ { L"Status Register MSR Address", 4, 16, L"0x%lx", NULL, NULL, NULL, NULL },
+ { L"Address Register MSR Address", 4, 20, L"0x%lx", NULL, NULL, NULL, NULL },
+ { L"Misc Register MSR Address", 4, 24, L"0x%lx", NULL, NULL, NULL, NULL },
+};
+
+/**
+ An ACPI_PARSER array describing the Hardware Error Notification Structure's
+ Configuration Write Enable Field (CWE)
+ Cf ACPI 6.5 Table 18.14: Hardware Error Notification Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorNotificationCweParser[] = {
+ { L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL },
+ { L"Poll Interval", 1, 1, L"%d", NULL, NULL, NULL, NULL },
+ { L"Switch To Polling Threshold Value", 1, 2, L"%d", NULL, NULL, NULL, NULL },
+ { L"Switch To Polling Threshold Window", 1, 3, L"%d", NULL, NULL, NULL, NULL },
+ { L"Error Threshold Value", 1, 4, L"%d", NULL, NULL, NULL, NULL },
+ { L"Error Threshold Window", 1, 5, L"%d", NULL, NULL, NULL, NULL },
+ { L"Reserved", 10, 6, L"0x%x", NULL, NULL, NULL, NULL },
+};
+
+/**
+ This function validates the Type field of Hardware Error Notification Structure
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateErrorNotificationType (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ UINT8 Type;
+
+ Type = *(UINT8 *)Ptr;
+
+ if (Type >
+ EFI_ACPI_6_5_HARDWARE_ERROR_NOTIFICATION_SOFTWARE_DELEGATED_EXCEPTION)
+ {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Notification Structure Type must be <= 0x%x.",
+ EFI_ACPI_6_5_HARDWARE_ERROR_NOTIFICATION_SOFTWARE_DELEGATED_EXCEPTION
+ );
+ }
+}
+
+/**
+ Dumps flags fields of error source descriptor.
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpSourceFlags (
+ IN CONST CHAR16 *Format OPTIONAL,
+ IN UINT8 *Ptr
+ )
+{
+ if (Format != NULL) {
+ Print (Format, *(UINT32 *)Ptr);
+ return;
+ }
+
+ Print (L"0x%x\n", *Ptr);
+ ParseAcpiBitFields (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 1,
+ PARSER_PARAMS (HestErrorSourceFlags)
+ );
+}
+
+/**
+ Dumps type fields of Error Notification Structure
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpErrorNotificationType (
+ IN CONST CHAR16 *Format OPTIONAL,
+ IN UINT8 *Ptr
+ )
+{
+ if (Format != NULL) {
+ Print (Format, *Ptr);
+ return;
+ }
+
+ if (*Ptr <= EFI_ACPI_6_5_HARDWARE_ERROR_NOTIFICATION_SOFTWARE_DELEGATED_EXCEPTION) {
+ Print (L"%s(0x%x)", HestErrorNotificationStructureTypeStr[*Ptr]);
+ } else {
+ Print (L"UNKNOWN(0x%x)", HestErrorNotificationStructureTypeStr[*Ptr]);
+ }
+}
+
+/**
+ Dumps Configuration Write Enable fields of Hardware Error Notification Structure.
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpErrorNotificationCwe (
+ IN CONST CHAR16 *Format OPTIONAL,
+ IN UINT8 *Ptr
+ )
+{
+ if (Format != NULL) {
+ Print (Format, *(UINT32 *)Ptr);
+ return;
+ }
+
+ Print (L"0x%x\n", *Ptr);
+ ParseAcpiBitFields (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 1,
+ PARSER_PARAMS (HestErrorNotificationCweParser)
+ );
+}
+
+/**
+ An ACPI_PARSER array describing the Hardware Error Notification Structure
+ Cf ACPI 6.5 Table 18.14: Hardware Error Notification Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorNotificationParser[] = {
+ { L"Type", 1, 0, NULL, DumpErrorNotificationType, NULL, ValidateErrorNotificationType, NULL },
+ { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
+ { L"Configuration Write Enable", 2, 2, NULL, DumpErrorNotificationCwe, NULL, NULL, NULL },
+ { L"Pull Interval", 4, 4, L"%d ms", NULL, NULL, NULL, NULL },
+ { L"Vector", 4, 8, L"%d", NULL, NULL, NULL, NULL },
+ { L"Switch To Polling Threshold Value", 4, 12, L"%d", NULL, NULL, NULL, NULL },
+ { L"Switch To Polling Threshold Window", 4, 16, L"%d ms", NULL, NULL, NULL, NULL },
+ { L"Error Threshold Value", 4, 20, L"%d", NULL, NULL, NULL, NULL },
+ { L"Error Threshold Window", 4, 24, L"%d ms", NULL, NULL, NULL, NULL },
+};
+
+/**
+ This function validates reserved bits of
+ pci related Error source structure's bus field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePciBusReservedBits (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ if (*Ptr != 0x00) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: bits[31:24] should must be zero...");
+ }
+}
+
+/**
+ An ACPI_PARSER array describing the PCI related Error Source Bus field.
+**/
+STATIC CONST ACPI_PARSER HestErrorSourcePciCommonBusParser[] = {
+ { L"Bus", 8, 0, L"%d", NULL, NULL, NULL, NULL },
+ { L"Segment Number", 16, 8, L"%d", NULL, NULL, NULL, NULL },
+ { L"Reserved", 8, 24, L"0x%x", NULL, NULL, ValidatePciBusReservedBits, NULL },
+};
+
+/**
+ This function validates the flags field of IA32 related
+ error source descriptor structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateIA32ErrorSourceFlags (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ UINT8 SourceFlags;
+
+ SourceFlags = *(UINT8 *)Ptr;
+
+ if ((SourceFlags &
+ ~(EFI_ACPI_6_5_ERROR_SOURCE_FLAG_FIRMWARE_FIRST |
+ EFI_ACPI_6_5_ERROR_SOURCE_FLAG_GHES_ASSIST)) != 0)
+ {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Invalid IA32 source flags field value...");
+ }
+
+ if (((SourceFlags & EFI_ACPI_6_5_ERROR_SOURCE_FLAG_FIRMWARE_FIRST) != 0) &&
+ ((SourceFlags & EFI_ACPI_6_5_ERROR_SOURCE_FLAG_GHES_ASSIST) != 0))
+ {
+ IncrementErrorCount ();
+ Print (L"\nERROR: GHES_ASSIST should be reserved if FIRMWARE_FIRST is set...");
+ }
+}
+
+/**
+ This function validates the flags field of PCI related
+ error source descriptor structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePciErrorSourceFlags (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ UINT8 SourceFlags;
+
+ SourceFlags = *(UINT8 *)Ptr;
+
+ if ((SourceFlags &
+ ~(EFI_ACPI_6_5_ERROR_SOURCE_FLAG_FIRMWARE_FIRST |
+ EFI_ACPI_6_5_ERROR_SOURCE_FLAG_GLOBAL)) != 0)
+ {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Invalid PCI source flags field value...");
+ }
+}
+
+/**
+ This function validates the flags field of Ghes related
+ error source descriptor structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateGhesSourceFlags (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ UINT8 SourceFlags;
+
+ SourceFlags = *(UINT8 *)Ptr;
+
+ if (SourceFlags != 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Ghes'source flags should be reserved...");
+ }
+}
+
+/**
+ This function validates the enabled field of error source descriptor
+ structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateEnabledField (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ if (*(UINT8 *)Ptr > 1) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Invalid Enabled field value must be either 0 or 1.");
+ }
+}
+
+/**
+ This function validates the number of records to preallocated and
+ max sections per record fields of error source descriptor
+ structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRecordCount (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ UINT8 RecordCount;
+ BOOLEAN CheckRecordCount;
+
+ RecordCount = *Ptr;
+ CheckRecordCount = ((BOOLEAN)(UINTN)Context);
+
+ if ((CheckRecordCount) && (RecordCount == 0)) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Record count must be >= 1...");
+ }
+}
+
+/**
+ Dumps the notification structure fields.
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpNotificationStructure (
+ IN CONST CHAR16 *Format OPTIONAL,
+ IN UINT8 *Ptr
+ )
+{
+ UINT32 Offset;
+ UINT32 Size;
+
+ Size = sizeof (EFI_ACPI_6_5_HARDWARE_ERROR_NOTIFICATION_STRUCTURE);
+ Print (L"\n");
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ Size,
+ PARSER_PARAMS (HestErrorNotificationParser)
+ );
+ if (Offset != Size) {
+ IncrementErrorCount ();
+ Print (L"ERROR: Failed to parse Hardware Error Notification Structure!\n");
+ }
+}
+
+/**
+ Dumps bus field in the PCI related Error Source Structure.
+ from HestTable.
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpPciBus (
+ IN CONST CHAR16 *Format OPTIONAL,
+ IN UINT8 *Ptr
+ )
+{
+ if (Format != NULL) {
+ Print (Format, *(UINT32 *)Ptr);
+ return;
+ }
+
+ Print (L"0x%x\n", *Ptr);
+ ParseAcpiBitFields (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 1,
+ PARSER_PARAMS (HestErrorSourcePciCommonBusParser)
+ );
+}
+
+/**
+ Dumps the IA32 Arch Machine Check Error Bank structure fields.
+
+ @param [in] HestTable Start pointer to Hest table.
+ @param [in] AcpiTableLength Length of HestTable.
+ @param [in,out] Offset Offset to machine check bank structure
+ from HestTable.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_INVALID_PARAMETER Invalid Hest Table
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+DumpIA32ArchMachineCheckErrorBankStructure (
+ IN UINT8 *HestTable,
+ UINT32 AcpiTableLength,
+ UINT32 *Offset
+ )
+{
+ UINT8 Idx;
+ UINT8 *IA32BankStructPtr;
+ UINT32 TotalBankStructSize;
+
+ TotalBankStructSize = *mHestIA32HardwareBankCount *
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE);
+
+ if ((*Offset + TotalBankStructSize) > AcpiTableLength) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Not enough data for "
+ "IA-32 Architecture Machine Check Exception Error source.\n"
+ );
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Idx = 0; Idx < *mHestIA32HardwareBankCount; Idx++) {
+ IA32BankStructPtr = HestTable + *Offset;
+ ParseAcpi (
+ TRUE,
+ 4,
+ "IA-32 Architecture Machine Check Bank Structure",
+ IA32BankStructPtr,
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE),
+ PARSER_PARAMS (HestErrorIA32ArchMachineCheckBankStructureParser)
+ );
+ *Offset +=
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE);
+ }
+
+ *mHestIA32HardwareBankCount = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Helper macro to populate the header fields of error source descriptor in the
+ ACPI_PARSER array.
+**/
+#define PARSE_HEST_ERROR_SOURCE_COMMON_HEADER(FlagsValidateFunc, CheckRecordCount) \
+ { L"Type", 2, 0, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Source Id", 2, 2, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Reserved", 2, 4, NULL, NULL, NULL, NULL, NULL }, \
+ { L"Flags", 1, 6, NULL, DumpSourceFlags, NULL, \
+ FlagsValidateFunc, NULL }, \
+ { L"Enabled", 1, 7, L"%d", NULL, NULL, ValidateEnabledField, NULL }, \
+ { L"Number of Records to Pre-allocate", 4, 8, L"%d", NULL, NULL, \
+ ValidateRecordCount, (VOID *) ((UINTN) CheckRecordCount) }, \
+ { L"Max Sections Per Record", 4, 12, L"%d", NULL, NULL, \
+ ValidateRecordCount, (VOID *) ((UINTN) CheckRecordCount) }
+
+/**
+ Helper macro to populate the header fields of PCI related
+ error source descriptor in the ACPI_PARSER array.
+**/
+#define PARSE_HEST_PCI_ERROR_SOURCE_COMMON_HEADER() \
+ PARSE_HEST_ERROR_SOURCE_COMMON_HEADER(ValidatePciErrorSourceFlags, TRUE), \
+ { L"Bus", 4, 16, NULL, DumpPciBus, NULL, NULL, NULL }, \
+ { L"Device", 2, 20, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Function", 2, 22, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Device Control", 2, 24, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Reserved", 2, 26, NULL, NULL, NULL, NULL, NULL }, \
+ { L"Uncorrectable Error Mask", 4, 28, L"0x%lx", NULL, NULL, NULL, NULL }, \
+ { L"Uncorrectable Error Severity", 4, 32, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Correctable Error Mask", 4, 36, L"0x%lx", NULL, NULL, NULL, NULL }, \
+ { L"Advanced Error Capabilities and Control", 4, 40, L"%d", NULL, NULL, \
+ NULL, NULL }
+
+/**
+ Helper macro to populate the header fields of GHES related
+ error source descriptor in the ACPI_PARSER array.
+**/
+#define PARSE_HEST_GHES_ERROR_SOURCE() \
+ { L"Type", 2, 0, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Source Id", 2, 2, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Related Source Id", 2, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
+ { L"Flags", 1, 6, L"0x%x", NULL, NULL, ValidateGhesSourceFlags, NULL }, \
+ { L"Enabled", 1, 7, L"%d", NULL, NULL, ValidateEnabledField, NULL }, \
+ { L"Number of Records to Pre-allocate", 4, 8, L"%d", NULL, NULL, \
+ ValidateRecordCount, (VOID *) ((UINTN) TRUE) }, \
+ { L"Max Sections Per Record", 4, 12, L"%d", NULL, NULL, \
+ ValidateRecordCount, (VOID *) ((UINTN) TRUE) }, \
+ { L"Max Raw Data Length", 4, 16, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Error Status Address", 12, 20, NULL, DumpGas, NULL, NULL, NULL }, \
+ { L"Notification Structure", 28, 32, NULL, DumpNotificationStructure, \
+ NULL, NULL, NULL }, \
+ { L"Error Status Block Length", 4, 60, L"%d", NULL, NULL, NULL, NULL }
+
+/**
+ An ACPI_PARSER array describing the IA-32 Architecture Machine Check Exception
+ error source descriptor.
+ Cf ACPI 6.5 Table 18.3: IA-32 Architecture Machine Check Exception Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceIA32ArchMachineCheckExceptionParser[] = {
+ PARSE_HEST_ERROR_SOURCE_COMMON_HEADER (ValidateIA32ErrorSourceFlags, FALSE),
+ { L"Global Capability Init Data",
+ 8, 16, L"0x%llx", NULL, NULL, NULL, NULL },
+ { L"Global Control Init Data",
+ 8, 24, L"0x%llx", NULL, NULL, NULL, NULL },
+ { L"Number of Hardware Banks",
+ 1, 32, L"%d", NULL, (VOID **)&mHestIA32HardwareBankCount, NULL, NULL },
+ { L"Reserved",
+ 7, 33, NULL, NULL, NULL, NULL, NULL },
+ /// HestErrorIA32ArchMachineCheckBankStructureParser
+ /// ...
+};
+
+/**
+ An ACPI_PARSER array describing the IA-32 Architecture Machine Check Exception
+ error source descriptor.
+ Cf ACPI 6.5 Table 18.5: IA-32 Architecture Machine Check Exception Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceIA32ArchCorrectedMachineCheckParser[] = {
+ PARSE_HEST_ERROR_SOURCE_COMMON_HEADER (ValidateIA32ErrorSourceFlags, TRUE),
+ { L"Notification Structure",
+ 28, 16, NULL, DumpNotificationStructure, NULL, NULL, NULL },
+ { L"Number of Hardware Banks",
+ 1, 44, L"%d", NULL, (VOID **)&mHestIA32HardwareBankCount, NULL, NULL },
+ { L"Reserved",
+ 3, 45, NULL, NULL, NULL, NULL, NULL },
+ /// HestErrorIA32ArchMachineCheckBankStructureParser
+ /// ...
+};
+
+/**
+ An ACPI_PARSER array describing the IA-32 Non-Maskable Interrupt
+ error source descriptor.
+ Cf ACPI 6.5 Table 18.6: IA-32 Architecture NMI Error Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceIA32ArchNonMaskableInterruptParser[] = {
+ { L"Type", 2, 0, L"%d", NULL, NULL, NULL, NULL },
+ { L"Source Id", 2, 2, L"%d", NULL, NULL, NULL, NULL },
+ { L"Reserved", 4, 4, NULL, NULL, NULL, NULL, NULL },
+ { L"Number of Records to Pre-allocate", 4, 8, L"%d", NULL, NULL,
+ ValidateRecordCount, (VOID *)((UINTN)TRUE) },
+ { L"Max Sections Per Record", 4, 12, L"%d", NULL, NULL,
+ ValidateRecordCount, (VOID *)((UINTN)TRUE) },
+ { L"Max Raw Data Length", 4, 16, L"%d", NULL, NULL, NULL, NULL },
+};
+
+/**
+ An ACPI_PARSER array describing the HEST PCIe Root Port AER
+ error source descriptor.
+ Cf ACPI 6.5 Table 18.7: PCI Express Root Port AER Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourcePciExpressRootPortAerParser[] = {
+ PARSE_HEST_PCI_ERROR_SOURCE_COMMON_HEADER (),
+ { L"Root Error Command",
+ 4, 44,L"%d", NULL, NULL, NULL, NULL },
+};
+
+/**
+ An ACPI_PARSER array describing the HEST PCIe Device AER
+ error source descriptor.
+ Cf ACPI 6.5 Table 18.8: PCI Express Device AER Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourcePciExpressDeviceAerParser[] = {
+ PARSE_HEST_PCI_ERROR_SOURCE_COMMON_HEADER (),
+};
+
+/**
+ An ACPI_PARSER array describing the HEST PCIe/PCI-X Bridge AER
+ error source descriptor.
+ Cf ACPI 6.5 Table 18.9: PCI Express/PCI-X Bridge AER Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourcePciExpressBridgeAerParser[] = {
+ PARSE_HEST_PCI_ERROR_SOURCE_COMMON_HEADER (),
+ { L"Secondary Uncorrectable Error Mask",
+ 4, 44, L"0x%lx", NULL, NULL, NULL, NULL },
+ { L"Secondary Uncorrectable Error Severity",
+ 4, 48, L"%d", NULL, NULL, NULL, NULL },
+ { L"Secondary Advanced Error Capabilities and Control",
+ 4, 52, L"%d", NULL, NULL, NULL, NULL },
+};
+
+/**
+ An ACPI_PARSER array describing the HEST GHES error source descriptor.
+ Cf ACPI 6.5 Table 18.10: Generic Hardware Error Source Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceGhesParser[] = {
+ PARSE_HEST_GHES_ERROR_SOURCE (),
+};
+
+/**
+ An ACPI_PARSER array describing the HEST GHESv2 error source descriptor.
+ Cf ACPI 6.5 Table 18.11: Generic Hardware Error Source version 2 Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceGhesv2Parser[] = {
+ PARSE_HEST_GHES_ERROR_SOURCE (),
+ { L"Read Ack Register", 12, 64, NULL, DumpGas, NULL, NULL, NULL },
+ { L"Read Ack Preserve", 8, 76, L"%llx", NULL, NULL, NULL, NULL },
+ { L"Read Ack Write", 8, 84, L"%llx", NULL, NULL, NULL, NULL },
+};
+
+/**
+ An ACPI_PARSER array describing the IA-32 Architecture Deferred Machine Check
+ error source descriptor.
+ Cf ACPI 6.5 Table 18.15: IA-32 Architecture Deferred Machine Check Structure
+**/
+STATIC CONST ACPI_PARSER HestErrorSourceIA32ArchDeferredMachineCheckParser[] = {
+ PARSE_HEST_ERROR_SOURCE_COMMON_HEADER (ValidateIA32ErrorSourceFlags, TRUE),
+ { L"Notification Structure", 28, 16, NULL, DumpNotificationStructure,
+ NULL, NULL, NULL },
+ { L"Number of Hardware Banks", 1, 44, L"%d", NULL,
+ (VOID **)&mHestIA32HardwareBankCount, NULL, NULL },
+ { L"Reserved", 3, 45, NULL, NULL, NULL,NULL, NULL },
+ /// HestErrorIA32ArchMachineCheckBankStructureParser
+ /// ...
+};
+
+/**
+ This function parses the ACPI HEST table.
+ When trace is enabled this function parses the HEST table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiHest (
+ IN BOOLEAN Trace,
+ IN UINT8 *Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Offset;
+ UINT8 *ErrorSourcePtr;
+ UINT32 ParsedErrorSourceCount;
+ UINT32 CurErrorSourceType;
+
+ if (Trace != TRUE) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "HEST",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (HestParser)
+ );
+
+ // Validate Error Source Descriptors Count.
+ if (mHestErrorSourceCount == NULL) {
+ IncrementErrorCount ();
+ Print (L"ERROR: Invalid Hardware Error Source Table Header...\n");
+ return;
+ }
+
+ ParsedErrorSourceCount = 0;
+ CurErrorSourceType = EFI_ACPI_6_5_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION;
+
+ while ((Offset < AcpiTableLength) && (ParsedErrorSourceCount < *mHestErrorSourceCount)) {
+ ErrorSourcePtr = Ptr + Offset;
+
+ // Get Type of Error Source Descriptor.
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ ErrorSourcePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (HestErrorSourceTypeParser)
+ );
+
+ // Validate Error Source Descriptors Type.
+ if (mHestErrorSourceType == NULL) {
+ IncrementErrorCount ();
+ Print (L"ERROR: Invalid Error Source Structure...\n");
+ return;
+ }
+
+ if (CurErrorSourceType > *mHestErrorSourceType) {
+ IncrementErrorCount ();
+ Print (L"ERROR: Error Source Structure must be sorted in Type with ascending order...\n");
+ return;
+ }
+
+ switch (*mHestErrorSourceType) {
+ case EFI_ACPI_6_5_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "IA-32 Architecture Machine Check Exception",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourceIA32ArchMachineCheckExceptionParser)
+ );
+
+ Offset +=
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE);
+
+ Status = DumpIA32ArchMachineCheckErrorBankStructure (
+ Ptr,
+ AcpiTableLength,
+ &Offset
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ break;
+ case EFI_ACPI_6_5_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "IA-32 Architecture Corrected Machine Check",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourceIA32ArchCorrectedMachineCheckParser)
+ );
+
+ Offset +=
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE);
+
+ Status = DumpIA32ArchMachineCheckErrorBankStructure (
+ Ptr,
+ AcpiTableLength,
+ &Offset
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ break;
+ case EFI_ACPI_6_5_IA32_ARCHITECTURE_NMI_ERROR:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "IA-32 Architecture Non-Maskable Interrupt",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourceIA32ArchNonMaskableInterruptParser)
+ );
+
+ Offset +=
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE);
+ break;
+ case EFI_ACPI_6_5_PCI_EXPRESS_ROOT_PORT_AER:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "PCI Express RootPort AER Structure",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourcePciExpressRootPortAerParser)
+ );
+
+ Offset += sizeof (EFI_ACPI_6_5_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE);
+ break;
+ case EFI_ACPI_6_5_PCI_EXPRESS_DEVICE_AER:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "PCI Express Device AER Structure",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_PCI_EXPRESS_DEVICE_AER_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourcePciExpressDeviceAerParser)
+ );
+
+ Offset += sizeof (EFI_ACPI_6_5_PCI_EXPRESS_DEVICE_AER_STRUCTURE);
+ break;
+ case EFI_ACPI_6_5_PCI_EXPRESS_BRIDGE_AER:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "PCI Express Bridge AER Structure",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_PCI_EXPRESS_BRIDGE_AER_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourcePciExpressBridgeAerParser)
+ );
+
+ Offset += sizeof (EFI_ACPI_6_5_PCI_EXPRESS_BRIDGE_AER_STRUCTURE);
+ break;
+ case EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Generic Hardware Error Source Structure",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourceGhesParser)
+ );
+
+ Offset += sizeof (EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE);
+ break;
+ case EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_VERSION_2:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Generic Hardware Error Source V2 Structure",
+ ErrorSourcePtr,
+ sizeof (
+ EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE
+ ),
+ PARSER_PARAMS (HestErrorSourceGhesv2Parser)
+ );
+
+ Offset +=
+ sizeof (
+ EFI_ACPI_6_5_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE
+ );
+ break;
+ case EFI_ACPI_6_5_IA32_ARCHITECTURE_DEFERRED_MACHINE_CHECK:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "IA-32 Architecture Deferred Machine Check",
+ ErrorSourcePtr,
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_DEFERRED_MACHINE_CHECK_STRUCTURE),
+ PARSER_PARAMS (HestErrorSourceIA32ArchDeferredMachineCheckParser)
+ );
+
+ Offset +=
+ sizeof (EFI_ACPI_6_5_IA32_ARCHITECTURE_DEFERRED_MACHINE_CHECK_STRUCTURE),
+
+ Status = DumpIA32ArchMachineCheckErrorBankStructure (
+ Ptr,
+ AcpiTableLength,
+ &Offset
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (L"ERROR: Invalid Error Source Descriptor Type(%d).\n", *mHestErrorSourceType);
+ return;
+ } // switch
+
+ ParsedErrorSourceCount++;
+ } // while
+
+ if (ParsedErrorSourceCount < *mHestErrorSourceCount) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Error Source Count... Real:%d, ErrorSourceCount:%d\n",
+ ParsedErrorSourceCount,
+ *mHestErrorSourceCount
+ );
+ return;
+ }
+
+ if (Offset < AcpiTableLength) {
+ IncrementErrorCount ();
+ Print (L"ERROR: Invalid Error Source Count, There's more data...\n");
+ return;
+ }
+}
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
index 4a90372..81c58da 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
@@ -59,6 +59,7 @@ ACPI_TABLE_PARSER ParserList[] = {
{ EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE, ParseAcpiFacs },
{ EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiFadt },
{ EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiGtdt },
+ { EFI_ACPI_6_5_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE, ParseAcpiHest },
{ EFI_ACPI_6_4_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE, ParseAcpiHmat },
{ EFI_ACPI_6_5_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE, ParseAcpiHpet },
{ EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE, ParseAcpiIort },
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
index 9c2e2b7..87998b2 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
@@ -2,7 +2,7 @@
# Provides Shell 'acpiview' command functions
#
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
-# Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.<BR>
+# Copyright (c) 2016 - 2024, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -38,6 +38,7 @@
Parsers/Facs/FacsParser.c
Parsers/Fadt/FadtParser.c
Parsers/Gtdt/GtdtParser.c
+ Parsers/Hest/HestParser.c
Parsers/Hmat/HmatParser.c
Parsers/Hpet/HpetParser.c
Parsers/Iort/IortParser.c