* [edk2-platforms][PATCH v2 1/5] Platform/ARM: Add DMC-620 ECC error handling driver
2021-07-10 16:24 [edk2-platforms][PATCH v2 0/5] Platform/Sgi: Add platform support for firmware first error handling Omkar Anand Kulkarni
@ 2021-07-10 16:24 ` Omkar Anand Kulkarni
2021-07-10 16:24 ` [edk2-platforms][PATCH v2 2/5] Platform/Sgi: dmc-620 firmware-first error handling Omkar Anand Kulkarni
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Omkar Anand Kulkarni @ 2021-07-10 16:24 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Sami Mujawar
DMC-620 memory controller improves system reliability by generating
interrupts on detecting ECC errors on the data. Add a initial DMC-620 MM
driver that implements a MMI handler for handling single-bit ECC error
events originating from the DRAM.
The driver implements the HEST error source descriptor protocol in order
to publish the GHES error source descriptor for single-bit DRAM errors.
The GHES error source descriptor that is published is of type 'memory
error'. A GHES error source descriptor is published for each instances
if the DMC-620 controller in the system.
The driver registers a MMI handler for handling 1-bit DRAM ECC error
events. The MMI handler, when invoked, reads the DMC-620 error record
registers and populates the EFI_PLATFORM_MEMORY_ERROR_DATA type error
section information structure with the corresponding information read
from the error record registers.
Co-authored-by: Thomas Abraham <thomas.abraham@arm.com>
Signed-off-by: Omkar Anand Kulkarni <omkar.kulkarni@arm.com>
---
Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec | 30 ++
Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.inf | 60 ++++
Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.h | 175 ++++++++++
Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.c | 360 ++++++++++++++++++++
Platform/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c | 198 +++++++++++
5 files changed, 823 insertions(+)
diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec
new file mode 100644
index 000000000000..b111ae59322c
--- /dev/null
+++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec
@@ -0,0 +1,30 @@
+## @file
+# DMC-620 MM driver specific declrations.
+#
+# This file defines GUIDs and declares PCD values for DMC-620 MM driver.
+#
+# Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x0001001A
+ PACKAGE_NAME = Dmc620Mm
+ PACKAGE_GUID = 94110B10-8E72-42A0-8963-D2B57FCF0F38
+ PACKAGE_VERSION = 0.1
+
+[Guids]
+ gDmc620MmTokenSpaceGuid = {0xc305f72a, 0xd10d, 0x45e8, { 0x81, 0x78, 0x51, 0x8b, 0x78, 0x62, 0x77, 0x79 } }
+ gArmDmcEventHandlerGuid = { 0x5ef0afd5, 0xe01a, 0x4c30, { 0x86, 0x19, 0x45, 0x46, 0x26, 0x91, 0x80, 0x98 }}
+
+[PcdsFixedAtBuild.common]
+ gDmc620MmTokenSpaceGuid.PcdDmc620NumCtrl|2|UINT32|0x00000001
+ gDmc620MmTokenSpaceGuid.PcdDmc620RegisterBase|0x4E000000|UINT64|0x00000002
+ gDmc620MmTokenSpaceGuid.PcdDmc620CtrlSize|0x100000|UINT32|0x00000003
+ gDmc620MmTokenSpaceGuid.PcdDmc620CorrectableErrorThreshold|10|UINT32|0x00000004
+ gDmc620MmTokenSpaceGuid.PcdDmc620ErrSourceCount|1|UINT32|0x00000005
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramErrorSdeiEventBase|0|UINT32|0x00000006
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataBase|0|UINT64|0x00000007
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataSize|0|UINT64|0x00000008
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorSourceId|0|UINT16|0x00000009
diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.inf b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.inf
new file mode 100644
index 000000000000..3f470d466725
--- /dev/null
+++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.inf
@@ -0,0 +1,60 @@
+## @file
+# StandaloneMM driver for the DMC620 Memory Controller.
+#
+# Driver to handle 1-bit Corrected DRAM errors for DMC(s).
+#
+# Copyright (c) 2020, ARM Limited. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = StandaloneMmDmc620Driver
+ FILE_GUID = CB53ACD9-A1A1-43B3-A638-AC74DA5D9DA2
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ ENTRY_POINT = Dmc620MmDriverInitialize
+
+[Sources]
+ Dmc620Mm.c
+ Dmc620MmErrorSourceInfo.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+ StandaloneMmDriverEntryPoint
+ DebugLib
+ ArmSvcLib
+ ArmLib
+ BaseMemoryLib
+
+[Protocols]
+ gMmHestErrorSourceDescProtocolGuid ##PRODUCES
+
+[FixedPcd]
+ gArmPlatformTokenSpaceGuid.PcdGhesGenericErrorDataMmBufferBase
+ gArmPlatformTokenSpaceGuid.PcdGhesGenericErrorDataMmBufferSize
+
+ gDmc620MmTokenSpaceGuid.PcdDmc620CorrectableErrorThreshold
+ gDmc620MmTokenSpaceGuid.PcdDmc620CtrlSize
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramErrorSdeiEventBase
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataBase
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorDataSize
+ gDmc620MmTokenSpaceGuid.PcdDmc620DramOneBitErrorSourceId
+ gDmc620MmTokenSpaceGuid.PcdDmc620ErrSourceCount
+ gDmc620MmTokenSpaceGuid.PcdDmc620NumCtrl
+ gDmc620MmTokenSpaceGuid.PcdDmc620RegisterBase
+
+[Guids]
+ gArmDmcEventHandlerGuid
+
+[Depex]
+ TRUE
diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.h b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.h
new file mode 100644
index 000000000000..c114b1b24c4e
--- /dev/null
+++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.h
@@ -0,0 +1,175 @@
+/** @file
+ DMC-620 memory controller MM driver definitions.
+
+ Macros and structure definitions for DMC-620 error handling MM driver.
+
+ Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef DMC620_MM_DRIVER_H_
+#define DMC620_MM_DRIVER_H_
+
+#include <Base.h>
+#include <Guid/Cper.h>
+#include <IndustryStandard/Acpi.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Protocol/HestErrorSourceInfo.h>
+
+// DMC-620 memc register field values and masks.
+#define DMC620_MEMC_STATUS_MASK (BIT2|BIT1|BIT0)
+#define DMC620_MEMC_STATUS_READY (BIT1|BIT0)
+#define DMC620_MEMC_CMD_EXECUTE_DRAIN (BIT2|BIT0)
+
+// DMC-620 Error Record Status register fields values and masks.
+#define DMC620_ERR_STATUS_MV BIT26
+#define DMC620_ERR_STATUS_AV BIT31
+
+// DMC-620 Error Record MISC-0 register fields values and masks.
+#define DMC620_ERR_MISC0_COLUMN_MASK \
+ (BIT9|BIT8|BIT7|BIT6|BIT5|BIT4|BIT3|BIT2|BIT1|BIT0)
+#define DMC620_ERR_MISC0_ROW_MASK (0x0FFFFC00)
+#define DMC620_ERR_MISC0_ROW_SHIFT 10
+#define DMC620_ERR_MISC0_RANK_MASK (BIT30|BIT29|BIT28)
+#define DMC620_ERR_MISC0_RANK_SHIFT 28
+#define DMC620_ERR_MISC0_VAILD BIT31
+
+// DMC-620 Error Record register fields values and mask.
+#define DMC620_ERR_MISC1_VAILD BIT31
+#define DMC620_ERR_MISC1_BANK_MASK (BIT3|BIT2|BIT1|BIT0)
+
+// DMC-620 Error Record Global Status register bit field.
+#define DMC620_ERR_GSR_ECC_CORRECTED_FH BIT1
+
+//
+// DMC-620 Memory Mapped register definitions.
+//
+
+// Unused DMC-620 register fields.
+#define RESV_0 0x1BD
+#define RESV_1 0x2C
+#define RESV_2 0x8
+#define RESV_3 0x58
+
+#pragma pack(1)
+typedef struct {
+ UINT32 MemcStatus;
+ UINT32 MemcConfig;
+ UINT32 MemcCmd;
+ UINT32 Reserved[RESV_0];
+ UINT32 Err0Fr;
+ UINT32 Reserved1;
+ UINT32 Err0Ctlr0;
+ UINT32 Err0Ctlr1;
+ UINT32 Err0Status;
+ UINT8 Reserved2[RESV_1];
+ UINT32 Err1Fr;
+ UINT32 Reserved3;
+ UINT32 Err1Ctlr;
+ UINT32 Reserved4;
+ UINT32 Err1Status;
+ UINT32 Reserved5;
+ UINT32 Err1Addr0;
+ UINT32 Err1Addr1;
+ UINT32 Err1Misc0;
+ UINT32 Err1Misc1;
+ UINT32 Err1Misc2;
+ UINT32 Err1Misc3;
+ UINT32 Err1Misc4;
+ UINT32 Err1Misc5;
+ UINT8 Reserved6[RESV_2];
+ UINT32 Err2Fr;
+ UINT32 Reserved7;
+ UINT32 Err2Ctlr;
+ UINT32 Reserved8;
+ UINT32 Err2Status;
+ UINT32 Reserved9;
+ UINT32 Err2Addr0;
+ UINT32 Err2Addr1;
+ UINT32 Err2Misc0;
+ UINT32 Err2Misc1;
+ UINT32 Err2Misc2;
+ UINT32 Err2Misc3;
+ UINT32 Err2Misc4;
+ UINT32 Err2Misc5;
+ UINT8 Reserved10[RESV_2];
+ UINT32 Reserved11[RESV_3];
+ UINT32 Errgsr;
+} DMC620_REGS_TYPE;
+
+// DMC-620 Typical Error Record register definition.
+typedef struct {
+ UINT32 ErrFr;
+ UINT32 Reserved;
+ UINT32 ErrCtlr;
+ UINT32 Reserved1;
+ UINT32 ErrStatus;
+ UINT32 Reserved2;
+ UINT32 ErrAddr0;
+ UINT32 ErrAddr1;
+ UINT32 ErrMisc0;
+ UINT32 ErrMisc1;
+ UINT32 ErrMisc2;
+ UINT32 ErrMisc3;
+ UINT32 ErrMisc4;
+ UINT32 ErrMisc5;
+ UINT8 Reserved3[RESV_2];
+} DMC620_ERR_REGS_TYPE;
+#pragma pack()
+
+// List of supported error sources by DMC-620.
+typedef enum {
+ DramEccCfh = 0,
+ DramEccFh,
+ ChiFh,
+ SramEccCfh,
+ SramEccFh,
+ DmcErrRecovery
+} DMC_ERR_SOURCES;
+
+/**
+ MMI handler implementing the HEST error source desc protocol.
+
+ Returns the error source descriptor information for all DMC(s) error sources
+ and also returns its count and length.
+
+ @param[in] This Pointer for this protocol.
+
+ @param[out] Buffer HEST error source descriptor Information
+ buffer.
+ @param[out] ErrorSourcesLength Total length of Error Source Descriptors.
+ @param[out] ErrorSourceCount Total number of supported error sources.
+
+ @retval EFI_SUCCESS Buffer has valid Error Source descriptor
+ information.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+**/
+EFI_STATUS
+EFIAPI
+DmcErrorSourceDescInfoGet (
+ IN MM_HEST_ERROR_SOURCE_DESC_PROTOCOL *This,
+ OUT VOID **Buffer,
+ OUT UINTN *ErrorSourcesLength,
+ OUT UINTN *ErrorSourcesCount
+ );
+
+/**
+ Allow reporting of supported DMC-620 error sources.
+
+ Install the HEST Error Source Descriptor protocol handler to allow publishing
+ of the supported DMC-620 memory controller error sources.
+
+ @param[in] MmSystemTable Pointer to System table.
+
+ @retval EFI_SUCCESS Protocol installation successful.
+ @retval EFI_INVALID_PARAMETER Invalid system table parameter.
+**/
+EFI_STATUS
+Dmc620InstallErrorSourceDescProtocol (
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ );
+
+#endif // DMC620_MM_DRIVER_H_
diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.c b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.c
new file mode 100644
index 000000000000..dfc06ca61f96
--- /dev/null
+++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620Mm.c
@@ -0,0 +1,360 @@
+/** @file
+ DMC-620 Memory Controller error handling (Standalone MM) driver.
+
+ Supports 1-bit Bit DRAM error handling for multiple DMC instances. On a error
+ event, publishes the CPER error record of Memory Error type.
+
+ Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Specification Reference
+ - DMC620 Dynamic Memory Controller, revision r1p0.
+ - UEFI Reference Specification 2.8, Section N.2.5 Memory Error Section
+**/
+
+#include <Dmc620Mm.h>
+
+/**
+ Helper function to handle the DMC-620 DRAM errors.
+
+ Reads the DRAM error record registers. Creates a CPER error record of type
+ 'Memory Error' and populates it with information collected from DRAM error
+ record registers.
+
+ @param[in] DmcCtrl A pointer to DMC control registers.
+ @param[in] DmcInstance DMC instance which raised the fault event.
+ @param[in] ErrRecType A type of the DMC error record.
+ @param[in] ErrorBlockBaseAddress Unique address for populating the error
+ block status for given DMC error source.
+**/
+STATIC
+VOID
+Dmc620HandleDramError (
+ IN DMC620_REGS_TYPE *DmcCtrl,
+ IN UINTN DmcInstance,
+ IN UINTN ErrRecType,
+ IN UINTN ErrorBlockBaseAddress
+ )
+{
+ EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE *ErrBlockSectionDesc;
+ EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE *ErrBlockStatusHeaderData;
+ EFI_PLATFORM_MEMORY_ERROR_DATA MemorySectionInfo = {0};
+ DMC620_ERR_REGS_TYPE *ErrRecord;
+ EFI_GUID SectionType;
+ UINT32 ResetReg;
+ VOID *ErrBlockSectionData;
+ UINTN *ErrorStatusRegister;
+ UINTN *ReadAckRegister;
+ UINTN *ErrStatusBlock;
+ UINTN ErrStatus;
+ UINTN ErrAddr0;
+ UINTN ErrAddr1;
+ UINTN ErrMisc0;
+ UINTN ErrMisc1;
+ UINT8 CorrectedError;
+
+ //
+ // Check the type of DRAM error (1-bit or 2-bit) and accordingly select
+ // error record to use.
+ //
+ if (ErrRecType == DMC620_ERR_GSR_ECC_CORRECTED_FH) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: DRAM ECC Corrected Fault (1-Bit ECC error)\n",
+ __FUNCTION__
+ ));
+ ErrRecord = (DMC620_ERR_REGS_TYPE *)&DmcCtrl->Err1Fr;
+ CorrectedError = 1;
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: DRAM ECC Fault Handling (2-bit ECC error)\n",
+ __FUNCTION__
+ ));
+ ErrRecord = (DMC620_ERR_REGS_TYPE *)&DmcCtrl->Err2Fr;
+ CorrectedError = 0;
+ }
+
+ // Read most recent DRAM error record registers.
+ ErrStatus = MmioRead32 ((UINTN)&ErrRecord->ErrStatus);
+ ErrAddr0 = MmioRead32 ((UINTN)&ErrRecord->ErrAddr0);
+ ErrAddr1 = MmioRead32 ((UINTN)&ErrRecord->ErrAddr1);
+ ErrMisc0 = MmioRead32 ((UINTN)&ErrRecord->ErrMisc0);
+ ErrMisc1 = MmioRead32 ((UINTN)&ErrRecord->ErrMisc1);
+
+ // Clear the status register so that new error records are populated.
+ ResetReg = MmioRead32 ((UINTN)&ErrRecord->ErrStatus);
+ MmioWrite32 ((UINTN)&ErrRecord->ErrStatus, ResetReg);
+
+ //
+ // Get Physical address of DRAM error from Error Record Address register
+ // and populate Memory Error Section.
+ //
+ if (ErrStatus & DMC620_ERR_STATUS_AV) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: DRAM Error: Address_0 : 0x%x Address_1 : 0x%x\n",
+ __FUNCTION__,
+ ErrAddr0,
+ ErrAddr1
+ ));
+
+ //
+ // Populate Memory CPER section with DRAM error address (48 bits) and
+ // address mask fields.
+ //
+ MemorySectionInfo.ValidFields |=
+ EFI_PLATFORM_MEMORY_PHY_ADDRESS_MASK_VALID |
+ EFI_PLATFORM_MEMORY_PHY_ADDRESS_VALID;
+ MemorySectionInfo.PhysicalAddressMask = 0xFFFFFFFFFFFF;
+ MemorySectionInfo.PhysicalAddress = (ErrAddr1 << 32) | ErrAddr0;
+ }
+
+ //
+ // Read the Error Record Misc registers and populate relevant fields in
+ // Memory CPER error section.
+ //
+ if ((ErrStatus & DMC620_ERR_STATUS_MV)
+ && (ErrMisc0 & DMC620_ERR_MISC0_VAILD))
+ {
+ // Populate Memory error section wih DRAM column information.
+ MemorySectionInfo.ValidFields |= EFI_PLATFORM_MEMORY_COLUMN_VALID;
+ MemorySectionInfo.Column = ErrMisc0 & DMC620_ERR_MISC0_COLUMN_MASK;
+
+ //
+ // Populate Memory Error Section with DRAM row information.
+ // Row bits (bit 16 and 17) are to be filled as extended.
+ //
+ MemorySectionInfo.ValidFields |=
+ EFI_PLATFORM_MEMORY_ERROR_EXTENDED_ROW_BIT_16_17_VALID;
+ MemorySectionInfo.Row =
+ (ErrMisc0 & DMC620_ERR_MISC0_ROW_MASK) >> DMC620_ERR_MISC0_ROW_SHIFT;
+ MemorySectionInfo.Extended =
+ ((ErrMisc0 & DMC620_ERR_MISC0_ROW_MASK) >>
+ (DMC620_ERR_MISC0_ROW_SHIFT + 16));
+
+ // Populate Memory Error Section wih DRAM rank information.
+ MemorySectionInfo.ValidFields |= EFI_PLATFORM_MEMORY_ERROR_RANK_NUM_VALID;
+ MemorySectionInfo.RankNum = (ErrMisc0 & DMC620_ERR_MISC0_RANK_MASK) >>
+ DMC620_ERR_MISC0_RANK_SHIFT;
+ }
+
+ // Read Error Record MISC1 register and populate the Memory Error Section.
+ if ((ErrStatus & DMC620_ERR_STATUS_MV)
+ && (ErrMisc1 & DMC620_ERR_MISC1_VAILD))
+ {
+ MemorySectionInfo.ValidFields |= EFI_PLATFORM_MEMORY_BANK_VALID;
+ MemorySectionInfo.Bank = (ErrMisc1 & DMC620_ERR_MISC1_BANK_MASK);
+ }
+
+ //
+ // Misc registers 2..5 are not used and convey only the error counter
+ // information. They are cleared as they do not contribute in Error
+ // Record creation.
+ //
+ if (ErrStatus & DMC620_ERR_STATUS_MV) {
+ ResetReg = 0x0;
+ MmioWrite32 ((UINTN)&ErrRecord->ErrMisc2, ResetReg);
+ MmioWrite32 ((UINTN)&ErrRecord->ErrMisc3, ResetReg);
+ MmioWrite32 ((UINTN)&ErrRecord->ErrMisc4, ResetReg);
+ MmioWrite32 ((UINTN)&ErrRecord->ErrMisc5, ResetReg);
+ }
+
+ //
+ // Reset error records Status register for recording new DRAM error syndrome
+ // information.
+ //
+ ResetReg = MmioRead32 ((UINTN)&ErrRecord->ErrStatus);
+ MmioWrite32 ((UINTN)&ErrRecord->ErrStatus, ResetReg);
+
+ //
+ // Allocate memory for Error Acknowledge register, Error Status register and
+ // Error status block data.
+ //
+ ReadAckRegister = (UINTN *)ErrorBlockBaseAddress;
+ ErrorStatusRegister = (UINTN *)ErrorBlockBaseAddress + 1;
+ ErrStatusBlock = (UINTN *)ErrorStatusRegister + 1;
+
+ // Initialize Error Status Register with Error Status Block address.
+ *ErrorStatusRegister = (UINTN)ErrStatusBlock;
+
+ //
+ // Locate Block Status Header base address and populate it with Error Status
+ // Block Header information.
+ //
+ ErrBlockStatusHeaderData = (EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE *)
+ ErrStatusBlock;
+ *ErrBlockStatusHeaderData =
+ (EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE) {
+ .BlockStatus = {
+ .UncorrectableErrorValid = ((CorrectedError == 0) ? 0:1),
+ .CorrectableErrorValid = ((CorrectedError == 1) ? 1:0),
+ .MultipleUncorrectableErrors = 0x0,
+ .MultipleCorrectableErrors = 0x0,
+ .ErrorDataEntryCount = 0x1
+ },
+ .RawDataOffset = (sizeof(EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE) +
+ sizeof(EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE)),
+ .RawDataLength = 0,
+ .DataLength = (sizeof(EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE) +
+ sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)),
+ .ErrorSeverity = ((CorrectedError == 1) ?
+ EFI_ACPI_6_3_ERROR_SEVERITY_CORRECTED:
+ EFI_ACPI_6_3_ERROR_SEVERITY_FATAL),
+ };
+
+ //
+ // Locate Section Descriptor base address and populate Error Status Section
+ // Descriptor data.
+ //
+ ErrBlockSectionDesc = (EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE *)
+ (ErrBlockStatusHeaderData + 1);
+ *ErrBlockSectionDesc =
+ (EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE) {
+ .ErrorSeverity = ((CorrectedError == 1) ?
+ EFI_ACPI_6_3_ERROR_SEVERITY_CORRECTED:
+ EFI_ACPI_6_3_ERROR_SEVERITY_FATAL),
+ .Revision = EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_REVISION,
+ .ValidationBits = 0,
+ .Flags = 0,
+ .ErrorDataLength = sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA),
+ .FruId = {0},
+ .FruText = {0},
+ .Timestamp = {0},
+ };
+ SectionType = (EFI_GUID) EFI_ERROR_SECTION_PLATFORM_MEMORY_GUID;
+ CopyGuid ((EFI_GUID *)ErrBlockSectionDesc->SectionType, &SectionType);
+
+ // Locate Section base address and populate Memory Error Section(Cper) data.
+ ErrBlockSectionData = (VOID *)(ErrBlockSectionDesc + 1);
+ CopyMem (
+ ErrBlockSectionData,
+ (VOID *)&MemorySectionInfo,
+ sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA)
+ );
+}
+
+/**
+ DMC-620 1-bit ECC event handler.
+
+ Supports multiple DMC error processing. Current implementation handles the
+ DRAM ECC errors.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by
+ MmiHandlerRegister().
+ @param[in] Context Points to an optional handler context which
+ was specified when the handler was
+ registered.
+ @param[in, out] CommBuffer Buffer passed from Non-MM to MM environmvent.
+ @param[in, out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS Event handler successful.
+ @retval Other Failure of event handler.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+Dmc620ErrorEventHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context, OPTIONAL
+ IN OUT VOID *CommBuffer, OPTIONAL
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ DMC620_REGS_TYPE *DmcCtrl;
+ UINTN DmcIdx;
+ UINTN ErrGsr;
+
+ // DMC instance which raised the error event.
+ DmcIdx = *(UINTN *)CommBuffer;
+ // Error Record Base address for that DMC instance.
+ DmcCtrl = (DMC620_REGS_TYPE *)(FixedPcdGet64 (PcdDmc620RegisterBase) +
+ (FixedPcdGet64 (PcdDmc620CtrlSize) * DmcIdx));
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: DMC error event raised for DMC: %d with DmcBaseAddr: 0x%x \n",
+ __FUNCTION__,
+ DmcIdx,
+ (UINTN)DmcCtrl
+ ));
+
+ ErrGsr = MmioRead32 ((UINTN)&DmcCtrl->Errgsr);
+
+ if (ErrGsr & DMC620_ERR_GSR_ECC_CORRECTED_FH) {
+ // Handle corrected 1-bit DRAM ECC error.
+ Dmc620HandleDramError (
+ DmcCtrl,
+ DmcIdx,
+ DMC620_ERR_GSR_ECC_CORRECTED_FH,
+ FixedPcdGet64 (
+ PcdDmc620DramOneBitErrorDataBase) +
+ (FixedPcdGet64 (PcdDmc620DramOneBitErrorDataSize) * DmcIdx)
+ );
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Unsupported DMC-620 error reported, ignoring\n",
+ __FUNCTION__
+ ));
+ }
+
+ // No data to send using the MM communication buffer so clear the comm buffer
+ // size.
+ *CommBufferSize = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize function for the driver.
+
+ Registers MMI handlers to process fault events on DMC and installs required
+ protocols to publish the error source descriptors.
+
+ @param[in] ImageHandle Handle to image.
+ @param[in] SystemTable Pointer to System table.
+
+ @retval EFI_SUCCESS On successful installation of error event handler for
+ DMC.
+ @retval Other Failure in installing error event handlers for DMC.
+**/
+EFI_STATUS
+EFIAPI
+Dmc620MmDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_MM_SYSTEM_TABLE *mMmst;
+ EFI_STATUS Status;
+ EFI_HANDLE DispatchHandle;
+
+ ASSERT (SystemTable != NULL);
+ mMmst = SystemTable;
+
+ // Register MMI handlers for DMC-620 error events.
+ Status = mMmst->MmiHandlerRegister (
+ Dmc620ErrorEventHandler,
+ &gArmDmcEventHandlerGuid,
+ &DispatchHandle
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Registration failed for DMC error event handler, Status:%r\n",
+ __FUNCTION__,
+ Status
+ ));
+
+ return Status;
+ }
+
+ // Installs the HEST error source descriptor protocol.
+ Status = Dmc620InstallErrorSourceDescProtocol (SystemTable);
+ if (EFI_ERROR(Status)) {
+ mMmst->MmiHandlerUnRegister (DispatchHandle);
+ }
+
+ return Status;
+}
diff --git a/Platform/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c b/Platform/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c
new file mode 100644
index 000000000000..f5ee62beed67
--- /dev/null
+++ b/Platform/ARM/Drivers/Dmc620Mm/Dmc620MmErrorSourceInfo.c
@@ -0,0 +1,198 @@
+/** @file
+ Create and populate DMC-620 HEST error source descriptors.
+
+ Implements the HEST Error Source Descriptor protocol. Creates the GHESv2
+ type error source descriptors for supported hardware errors. Appends
+ the created descriptors to the Buffer parameter of the protocol.
+
+ Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Specification Reference:
+ - ACPI Reference Specification 6.3, Table 18-393 GHESv2 Structure.
+**/
+
+#include <Dmc620Mm.h>
+#include <HestAcpiHeader.h>
+
+/**
+ Populate the DMC-620 DRAM Error Source Descriptor.
+
+ Creates error source descriptor of GHESv2 type to be appended to the Hest
+ table. The error source descriptor is populated with appropriate values
+ based on the instance number of DMC-620. Allocates and initializes memory
+ for Error Status Block(Cper) section for each error source.
+
+ @param[in] ErrorDesc HEST error source descriptor Information.
+ @param[in] DmcIdx Instance number of the DMC-620.
+**/
+STATIC
+VOID
+EFIAPI
+Dmc620SetupDramErrorDescriptor (
+ IN EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *ErrorDesc,
+ IN UINTN DmcIdx
+ )
+{
+ UINTN ErrorBlockData;
+
+ //
+ // Address of reserved memory for the error status block that will be used
+ // to hold the information about the DRAM error. Initialize this memory
+ // with 0.
+ //
+ ErrorBlockData = FixedPcdGet64 (PcdDmc620DramOneBitErrorDataBase) +
+ (FixedPcdGet64 (PcdDmc620DramOneBitErrorDataSize) *
+ DmcIdx);
+ SetMem (
+ (VOID *)ErrorBlockData,
+ FixedPcdGet64 (PcdDmc620DramOneBitErrorDataSize),
+ 0
+ );
+
+ // Build the DRAM error source descriptor.
+ *ErrorDesc =
+ (EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE) {
+ .Type = EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_VERSION_2,
+ .SourceId = FixedPcdGet16 (PcdDmc620DramOneBitErrorSourceId) + DmcIdx,
+ .RelatedSourceId = 0xFFFF,
+ .Flags = 0,
+ .Enabled = 1,
+ .NumberOfRecordsToPreAllocate = 1,
+ .MaxSectionsPerRecord = 1,
+ .MaxRawDataLength = sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA),
+ .ErrorStatusAddress =
+ EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE_INIT (
+ (ErrorBlockData + 8)
+ ),
+ .NotificationStructure =
+ EFI_ACPI_6_3_HARDWARE_ERROR_NOTIFICATION_STRUCTURE_INIT (
+ EFI_ACPI_6_3_HARDWARE_ERROR_NOTIFICATION_SOFTWARE_DELEGATED_EXCEPTION,
+ 0,
+ FixedPcdGet32 (PcdDmc620DramErrorSdeiEventBase) + DmcIdx
+ ),
+ .ErrorStatusBlockLength =
+ sizeof (EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE) +
+ sizeof (EFI_ACPI_6_3_GENERIC_ERROR_DATA_ENTRY_STRUCTURE) +
+ sizeof (EFI_PLATFORM_MEMORY_ERROR_DATA),
+ .ReadAckRegister =
+ EFI_ACPI_6_3_GENERIC_ERROR_STATUS_STRUCTURE_INIT (ErrorBlockData),
+ .ReadAckPreserve = 0,
+ .ReadAckWrite = 0
+ };
+}
+
+/**
+ MMI handler implementing the HEST error source descriptor protocol.
+
+ Returns the error source descriptor information for all supported hardware
+ error sources. As mentioned in the HEST Error Source Decriptor protocol this
+ handler returns with error source count and length when Buffer parameter is
+ NULL.
+
+ @param[in] This Pointer for this protocol.
+ @param[out] Buffer HEST error source descriptor Information
+ buffer.
+ @param[out] ErrorSourcesLength Total length of Error Source Descriptors
+ @param[out] ErrorSourceCount Total number of supported error spurces.
+
+ @retval EFI_SUCCESS Buffer has valid Error Source descriptor
+ information.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+Dmc620ErrorSourceDescInfoGet (
+ IN MM_HEST_ERROR_SOURCE_DESC_PROTOCOL *This,
+ OUT VOID **Buffer,
+ OUT UINTN *ErrorSourcesLength,
+ OUT UINTN *ErrorSourcesCount
+ )
+{
+ EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *ErrorDescriptor;
+ UINTN DmcIdx;
+
+ //
+ // Update the error source length and error source count parameters.
+ //
+ *ErrorSourcesLength =
+ FixedPcdGet64 (PcdDmc620NumCtrl) *
+ FixedPcdGet64 (PcdDmc620ErrSourceCount) *
+ sizeof(EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE);
+ *ErrorSourcesCount = FixedPcdGet64 (PcdDmc620NumCtrl) *
+ FixedPcdGet64 (PcdDmc620ErrSourceCount);
+
+ //
+ // If 'Buffer' is NULL return, as this invocation of the protocol handler is
+ // to determine the total size of all the error source descriptor instances.
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Buffer to be updated with error source descriptor(s) information.
+ ErrorDescriptor =
+ (EFI_ACPI_6_3_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE *)*Buffer;
+
+ //
+ // Create and populate the available error source descriptor for all DMC(s).
+ //
+ for (DmcIdx = 0; DmcIdx < FixedPcdGet64 (PcdDmc620NumCtrl); DmcIdx++) {
+ // Add the one-bit DRAM error source descriptor.
+ Dmc620SetupDramErrorDescriptor(ErrorDescriptor, DmcIdx);
+ ErrorDescriptor++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// DMC-620 MM_HEST_ERROR_SOURCE_DESC_PROTOCOL protocol instance.
+//
+STATIC MM_HEST_ERROR_SOURCE_DESC_PROTOCOL mDmc620ErrorSourceDesc = {
+ Dmc620ErrorSourceDescInfoGet
+};
+
+/**
+ Allow reporting of supported DMC-620 error sources.
+
+ Install the HEST Error Source Descriptor protocol handler to allow publishing
+ of the supported Dmc(s) hardware error sources.
+
+ @param[in] MmSystemTable Pointer to System table.
+
+ @retval EFI_SUCCESS Protocol installation successful.
+ @retval EFI_INVALID_PARAMETER Invalid system table parameter.
+**/
+EFI_STATUS
+Dmc620InstallErrorSourceDescProtocol (
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ EFI_HANDLE mDmcHandle = NULL;
+ EFI_STATUS Status;
+
+ // Check if the MmSystemTable is initialized.
+ if (MmSystemTable == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Install HEST error source descriptor protocol for DMC(s).
+ Status = MmSystemTable->MmInstallProtocolInterface (
+ &mDmcHandle,
+ &gMmHestErrorSourceDescProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mDmc620ErrorSourceDesc
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed installing HEST error source protocol, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ }
+
+ return Status;
+}
--
2.17.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [edk2-platforms][PATCH v2 5/5] Platform/Sgi: Add platform error handling driver
2021-07-10 16:24 [edk2-platforms][PATCH v2 0/5] Platform/Sgi: Add platform support for firmware first error handling Omkar Anand Kulkarni
` (3 preceding siblings ...)
2021-07-10 16:24 ` [edk2-platforms][PATCH v2 4/5] Platform/Sgi: Define values for ACPI table header Omkar Anand Kulkarni
@ 2021-07-10 16:24 ` Omkar Anand Kulkarni
4 siblings, 0 replies; 6+ messages in thread
From: Omkar Anand Kulkarni @ 2021-07-10 16:24 UTC (permalink / raw)
To: devel; +Cc: Ard Biesheuvel, Sami Mujawar
Enables firmware first error handling on the given platform. Installs
and publishes the SDEI and HEST ACPI tables required for firmware first
error handling.
Signed-off-by: Omkar Anand Kulkarni <omkar.kulkarni@arm.com>
---
Platform/ARM/SgiPkg/SgiPlatform.dsc.inc | 10 ++
Platform/ARM/SgiPkg/SgiPlatform.fdf | 7 +
Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.inf | 51 ++++++
Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.c | 171 ++++++++++++++++++++
4 files changed, 239 insertions(+)
diff --git a/Platform/ARM/SgiPkg/SgiPlatform.dsc.inc b/Platform/ARM/SgiPkg/SgiPlatform.dsc.inc
index 87803c4e5785..f9bae632b1f6 100644
--- a/Platform/ARM/SgiPkg/SgiPlatform.dsc.inc
+++ b/Platform/ARM/SgiPkg/SgiPlatform.dsc.inc
@@ -24,6 +24,9 @@
# To allow firmware first error handling, set this to TRUE.
DEFINE ENABLE_GHES_MM = FALSE
+ # To allow firmware first error handling, set this to TRUE.
+ DEFINE ENABLE_FIRWARE_FIRST = FALSE
+
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
@@ -326,6 +329,13 @@
#
Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.inf
+ #
+ # platform error handler driver
+ #
+!if $(ENABLE_FIRMWARE_FIRST) == TRUE
+ Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.inf
+!endif
+
#
# FAT filesystem + GPT/MBR partitioning
#
diff --git a/Platform/ARM/SgiPkg/SgiPlatform.fdf b/Platform/ARM/SgiPkg/SgiPlatform.fdf
index a7100743bbc4..ecc99edf115b 100644
--- a/Platform/ARM/SgiPkg/SgiPlatform.fdf
+++ b/Platform/ARM/SgiPkg/SgiPlatform.fdf
@@ -190,6 +190,13 @@ READ_LOCK_STATUS = TRUE
#
INF Platform/ARM/SgiPkg/Drivers/PlatformDxe/PlatformDxe.inf
+ #
+ # platform error handler driver
+ #
+!if $(ENABLE_FIRMWARE_FIRST) == TRUE
+ INF Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.inf
+!endif
+
#
# Bds
#
diff --git a/Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.inf b/Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.inf
new file mode 100644
index 000000000000..fe9ed4175b0b
--- /dev/null
+++ b/Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.inf
@@ -0,0 +1,51 @@
+## @file
+# Dxe driver to handle platform errors.
+#
+# This driver installs SDEI and HEST ACPI tables required for firmware first
+# error handling.
+#
+# Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = PlatformErrorHandlerDxe
+ FILE_GUID = a3187ea4-feb4-415f-b11e-2312623ffa6f
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformErrorHandlerEntryPoint
+
+[Sources.common]
+ PlatformErrorHandlerDxe.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Platform/ARM/SgiPkg/SgiPlatform.dec
+
+[LibraryClasses]
+ AcpiLib
+ BaseLib
+ DebugLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gArmSgiAcpiTablesGuid
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid ## PROTOCOL ALWAYS_CONSUMED
+ gHestTableProtocolGuid ## PROTOCOL ALWAYS_CONSUMED
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+
+[Depex]
+ AFTER gArmPlatformHestErrorSourcesGuid
diff --git a/Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.c b/Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.c
new file mode 100644
index 000000000000..25b29152f1bb
--- /dev/null
+++ b/Platform/ARM/SgiPkg/Drivers/PlatformErrorHandlerDxe/PlatformErrorHandlerDxe.c
@@ -0,0 +1,171 @@
+/** @file
+ Driver to handle and support all platform errors.
+
+ Installs the SDEI and HEST ACPI tables for firmware first error handling.
+
+ Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Specification Reference:
+ - ACPI 6.3, Table 18-382, Hardware Error Source Table
+ - SDEI Platform Design Document, revision b, 10 Appendix C, ACPI table
+ definitions for SDEI
+**/
+
+#include <IndustryStandard/Acpi.h>
+
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/HestTable.h>
+
+
+/**
+ Build and install the SDEI ACPI table.
+
+ For platforms that allow firmware-first platform error handling, SDEI is used
+ as the notification mechanism for those errors.
+
+ @retval EFI_SUCCESS SDEI table installed successfully.
+ @retval Other For any error during installation.
+**/
+STATIC
+EFI_STATUS
+InstallSdeiTable (VOID)
+{
+ EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol = NULL;
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ EFI_STATUS Status;
+ UINTN AcpiTableHandle;
+
+ Header =
+ (EFI_ACPI_DESCRIPTION_HEADER) {
+ EFI_ACPI_6_3_SOFTWARE_DELEGATED_EXCEPTIONS_INTERFACE_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER), // Length
+ 0x01, // Revision
+ 0x00, // Checksum
+ {'A', 'R', 'M', 'L', 'T', 'D'}, // OemId
+ 0x4152464e49464552, // OemTableId:"REFINFRA"
+ 0x20201027, // OemRevision
+ 0x204d5241, // CreatorId:"ARM "
+ 0x00000001, // CreatorRevision
+ };
+
+ Header.Checksum = CalculateCheckSum8 ((UINT8 *)&Header, Header.Length);
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID **)&mAcpiTableProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to locate ACPI table protocol, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return Status;
+ }
+
+ Status = mAcpiTableProtocol->InstallAcpiTable (
+ mAcpiTableProtocol,
+ &Header,
+ Header.Length,
+ &AcpiTableHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to install SDEI ACPI table, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ }
+
+ return Status;
+}
+
+/**
+ Install the HEST ACPI table.
+
+ HEST ACPI table is used to list the platform errors for which the error
+ handling has been supported. Use the HEST table generation protocol to
+ install the HEST table.
+
+ @retval EFI_SUCCESS HEST table installed successfully.
+ @retval Other For any error during installation.
+**/
+STATIC
+EFI_STATUS
+InstallHestTable (VOID)
+{
+ HEST_TABLE_PROTOCOL *HestProtocol;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (
+ &gHestTableProtocolGuid,
+ NULL,
+ (VOID **)&HestProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to locate HEST DXE Protocol, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ return Status;
+ }
+
+ Status = HestProtocol->InstallHestTable ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to install HEST table, status: %r\n",
+ __FUNCTION__,
+ Status
+ ));
+ }
+
+ return Status;
+}
+
+/**
+ Entry point for the DXE driver.
+
+ This function installs the HEST ACPI table, using the HEST table generation
+ protocol. Also creates and installs the SDEI ACPI table required for firmware
+ first error handling.
+
+ @param[in] ImageHandle Handle to the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS On successful installation of ACPI tables
+ @retval Other On Failure
+**/
+EFI_STATUS
+EFIAPI
+PlatformErrorHandlerEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ // Build and install SDEI table.
+ Status = InstallSdeiTable ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Install the created HEST table.
+ Status = InstallHestTable ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
--
2.17.1
^ permalink raw reply related [flat|nested] 6+ messages in thread