summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFu Wei <fu.wei@linaro.org>2019-01-04 19:56:44 +0800
committerThomas Abraham <thomas.abraham@arm.com>2020-04-16 13:02:14 +0530
commitc02481238db51ca4f1a24bcd063ab701bfba8730 (patch)
treeeab8c80d9fe94fddd8e5245dd7dcb1062b4c7e1a
parent4d72901e7da0983578eed6345f96eb4d44bcee4b (diff)
StandaloneMmPkg: add CperLib framework
This patch just add a library framework for CperLib. CPER Library initializes the error source information from error source definition module and provides read/write services to MM Standalone and/or DXE drivers. Change-Id: I17832230557fcb2dba5fc472898b4210cb6b1f6e Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Fu Wei <fu.wei@linaro.org>
-rw-r--r--StandaloneMmPkg/Include/Library/CperLib.h113
-rw-r--r--StandaloneMmPkg/Library/CperLib/CperLib.c467
-rw-r--r--StandaloneMmPkg/Library/CperLib/CperLib.inf47
-rw-r--r--StandaloneMmPkg/Library/CperLib/CperLib.uni29
-rw-r--r--StandaloneMmPkg/StandaloneMmPkg.dec3
5 files changed, 659 insertions, 0 deletions
diff --git a/StandaloneMmPkg/Include/Library/CperLib.h b/StandaloneMmPkg/Include/Library/CperLib.h
new file mode 100644
index 0000000000..4aa56395b6
--- /dev/null
+++ b/StandaloneMmPkg/Include/Library/CperLib.h
@@ -0,0 +1,113 @@
+/** @file
+ Common Platform Error Record (CPER) Library.
+
+ CPER Library initializes the error source information from error source
+ definition module and provides read/write services to MM Standalone and/or
+ DXE drivers. The intention is to have a generic library which can be included
+ in either non-secure or secure world or both. At present, only the secure
+ world implementation is targeted.
+ The general format of the common platform error record:
+ The record consists of a header, followed by one or more section
+ descriptors, and for each descriptor, an associated section which may
+ contain eithererror or informational data.
+
+ Copyright (c) 2017, ARM Limited. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD
+ License which accompanies this distribution. The full text of the license may
+ be found at http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CPER_LIB_H_
+#define _CPER_LIB_H_
+
+#include <Uefi.h>
+#include <Protocol/Apei.h>
+
+#define ERROR_SOURCE_DEFINITION_GUID \
+ { \
+ 0xbb8fef92, 0x206e, 0x48d6, \
+ { 0x86, 0xef, 0xd4, 0xf6, 0xa3, 0x8a, 0x98, 0x27 } \
+ }
+
+#define EFI_ERROR_SECTION_NULL_GUID \
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
+
+typedef enum {
+ EFI_ERROR_SECTION_PROCESSOR_GENERIC_TYPE = 0,
+ EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_TYPE,
+ EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_IA32X64_TYPE,
+ EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_ARM_TYPE,
+ EFI_ERROR_SECTION_PLATFORM_MEMORY_TYPE,
+ EFI_ERROR_SECTION_PLATFORM_MEMORY2_TYPE,
+ EFI_ERROR_SECTION_PCIE_TYPE,
+ EFI_ERROR_SECTION_FW_ERROR_RECORD_TYPE,
+ EFI_ERROR_SECTION_PCI_PCIX_BUS_TYPE,
+ EFI_ERROR_SECTION_PCI_DEVICE_TYPE,
+ EFI_ERROR_SECTION_DMAR_GENERIC_TYPE,
+ EFI_ERROR_SECTION_DIRECTED_IO_DMAR_TYPE,
+ EFI_ERROR_SECTION_IOMMU_DMAR_TYPE,
+ EFI_ERROR_SECTION_MAX_TYPE
+} EFI_ERROR_SECTION_TYPE;
+
+
+/**
+ @ SectionCount; Indicates the total number of section(s) in the
+ error record.
+ @ DataLength; The total length of Sections
+ @ *SectionType; GUID Array indicating the error type(s) to be
+ included in the error record.
+ @ *Section; Data buffer pointing to the section(s).
+**/
+
+typedef struct _SECTIONS_INFO {
+ UINT16 SectionCount;
+ UINT32 DataLength;
+ EFI_GUID *SectionType;
+ VOID *Section;
+} SECTIONS_INFO;
+
+/**
+ Parse the error source information argument to get the memory info for the
+ error source.
+
+ @param ErrorSource Error Source Information of a specific error source
+ from the platform specific error source definition
+ module.
+
+ @retval EFI_UNSUPPORTED Error source definition module not implemented.
+ @retval EFI_SUCCESS Memory info successfully parsed.
+**/
+EFI_STATUS
+EFIAPI
+CperInit (
+ IN EFI_APEI_ERROR_SOURCE *ErrorSource,
+ IN OUT UINTN *CperAddress
+ );
+
+/**
+ Match the section type GUID with the internal lookup table and create a common
+ platform error record at the designated memory region. The list of section
+ type GUIDs for most common platform error records are available in
+ “MdePkg/Include/Guid/Cper.h”
+ @param CperAddress Indicates the Error Record Address of the Error
+ Source
+
+ @param SectionInfo Indicates the info of in the error record.
+
+ @retval EFI_UNSUPPORTED Unable to create CPER for a variety of reasons.
+ @retval EFI_SUCCESS CPER successfully created.
+**/
+EFI_STATUS
+EFIAPI
+CperWrite (
+ IN SECTIONS_INFO *SectionInfo,
+ IN OUT UINTN CperAddress
+ );
+
+#endif
diff --git a/StandaloneMmPkg/Library/CperLib/CperLib.c b/StandaloneMmPkg/Library/CperLib/CperLib.c
new file mode 100644
index 0000000000..5cf9f7ee8b
--- /dev/null
+++ b/StandaloneMmPkg/Library/CperLib/CperLib.c
@@ -0,0 +1,467 @@
+/** @file
+
+ Copyright (c) 2017, ARM Limited. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//#define MM_TEST 1
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiLib.h>
+#include <Library/CpuLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CperLib.h>
+
+#include <Guid/DebugImageInfoTable.h>
+#include <Guid/Cper.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/Apei.h>
+#include <IndustryStandard/Acpi.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+
+#include <Pi/PiDxeCis.h>
+
+#ifdef MM_TEST
+#include <Guid/MmUefiInfo.h>
+#endif
+
+EFI_GUID EfiErrorSections_Guid[] = {
+ [EFI_ERROR_SECTION_PROCESSOR_GENERIC_TYPE] =
+ EFI_ERROR_SECTION_PROCESSOR_GENERIC_GUID,
+ [EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_TYPE] =
+ EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_GUID,
+ [EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_IA32X64_TYPE] =
+ EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_IA32X64_GUID,
+ [EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_ARM_TYPE] =
+ EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_ARM_GUID,
+ [EFI_ERROR_SECTION_PLATFORM_MEMORY_TYPE] =
+ EFI_ERROR_SECTION_PLATFORM_MEMORY_GUID,
+ [EFI_ERROR_SECTION_PLATFORM_MEMORY2_TYPE] =
+ EFI_ERROR_SECTION_PLATFORM_MEMORY2_GUID,
+ [EFI_ERROR_SECTION_PCIE_TYPE] =
+ EFI_ERROR_SECTION_PCIE_GUID,
+ [EFI_ERROR_SECTION_FW_ERROR_RECORD_TYPE] =
+ EFI_ERROR_SECTION_FW_ERROR_RECORD_GUID,
+ [EFI_ERROR_SECTION_PCI_PCIX_BUS_TYPE] =
+ EFI_ERROR_SECTION_PCI_PCIX_BUS_GUID,
+ [EFI_ERROR_SECTION_PCI_DEVICE_TYPE] =
+ EFI_ERROR_SECTION_PCI_DEVICE_GUID,
+ [EFI_ERROR_SECTION_DMAR_GENERIC_TYPE] =
+ EFI_ERROR_SECTION_DMAR_GENERIC_GUID,
+ [EFI_ERROR_SECTION_DIRECTED_IO_DMAR_TYPE] =
+ EFI_ERROR_SECTION_DIRECTED_IO_DMAR_GUID,
+ [EFI_ERROR_SECTION_IOMMU_DMAR_TYPE] =
+ EFI_ERROR_SECTION_IOMMU_DMAR_GUID,
+ [EFI_ERROR_SECTION_MAX_TYPE] = EFI_ERROR_SECTION_NULL_GUID
+};
+
+STATIC
+EFI_STATUS
+GetTimestamp (
+ IN OUT EFI_ERROR_TIME_STAMP *TimeStamp
+ )
+{
+ //EFI_STATUS Status;
+ UINT8 Year, Century;
+ EFI_TIME Time;
+
+ //
+ // How to get the current time in StandaloneMm?
+ // we can NOT use gRT !
+
+ //Status = gRT->GetTime(&Time, NULL);
+ //if (EFI_ERROR(Status)) {
+ // DEBUG ((EFI_D_ERROR, "CperLib.GetTimestamp - Failed to get RTC time.\n"));
+ // return EFI_DEVICE_ERROR;
+ //}
+ Time.Year = 2007;
+ Time.Month = 11;
+ Time.Day = 29;
+ Time.Hour = 17;
+ Time.Minute = 43;
+ Time.Second = 30;
+
+ Year = (UINT8) (Time.Year % 100);
+ Century = (UINT8) (Time.Year / 100);
+
+ //
+ // Set the Time/Date values.
+ //
+ TimeStamp->Century = DecimalToBcd8 (Century);
+ TimeStamp->Year = DecimalToBcd8 (Year);
+ TimeStamp->Month = DecimalToBcd8 (Time.Month);
+ TimeStamp->Day = DecimalToBcd8 (Time.Day);
+ TimeStamp->Flag = EFI_ERROR_TIME_STAMP_PRECISE;
+ TimeStamp->Hours = DecimalToBcd8 (Time.Hour);
+ TimeStamp->Minutes = DecimalToBcd8 (Time.Minute);
+ TimeStamp->Seconds = DecimalToBcd8 (Time.Second);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Match the section type GUID with the internal lookup table and create a common
+ platform error record at the designated memory region. The list of section
+ type GUIDs for most common platform error records are available in
+ “MdePkg/Include/Guid/Cper.h”
+
+ @param SectionCount Indicates the total number of section(s) in the error
+ record.
+ @param SectionType GUID Array indicating the error type(s) to be included
+ in the error record.
+
+ @param Section Data buffer pointing to the section(s).
+
+ @retval EFI_UNSUPPORTED Unable to create CPER for a variety of reasons.
+ @retval EFI_SUCCESS CPER successfully created.
+
+EFI_STATUS
+EFIAPI
+CperWrite (
+ IN OUT UINTN ErrorRecordAddress,
+ IN _SECTIONS_INFO SectionsInfo
+ )
+
+**/
+EFI_STATUS
+EFIAPI
+CperWrite (
+ IN SECTIONS_INFO *SectionInfo,
+ IN UINTN ErrorRecordAddress
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN i, j;
+ //statistical data
+ BOOLEAN UncorrectableErrorValid;
+ BOOLEAN CorrectableErrorValid;
+ BOOLEAN MultipleUncorrectableErrors;
+ BOOLEAN MultipleCorrectableErrors;
+
+ EFI_GUID *_ErrorSentionType;
+ VOID *_ErrorSention;
+ VOID *ErrorSention_end;
+ UINT32 _DataLength;
+
+ UINTN CperAddress;
+ EFI_COMMON_ERROR_RECORD_HEADER *ErrorRecordHeader;
+ EFI_ERROR_SECTION_DESCRIPTOR *_ErrorRecordDescriptor;
+ VOID *_ErrorRecord;
+
+ //For Generic Error Status Block
+ EFI_ACPI_6_1_GENERIC_ERROR_STATUS_STRUCTURE *GenericErrorStatusBlock;
+ EFI_ACPI_6_1_GENERIC_ERROR_DATA_ENTRY_STRUCTURE *GenericErrorDataEntry;
+
+ GenericErrorStatusBlock = (EFI_ACPI_6_1_GENERIC_ERROR_STATUS_STRUCTURE *)
+ ErrorRecordAddress;
+ GenericErrorDataEntry = (EFI_ACPI_6_1_GENERIC_ERROR_DATA_ENTRY_STRUCTURE *)
+ (ErrorRecordAddress +
+ sizeof(EFI_ACPI_6_1_GENERIC_ERROR_STATUS_STRUCTURE));
+
+ CperAddress = ErrorRecordAddress +
+ sizeof(EFI_ACPI_6_1_GENERIC_ERROR_STATUS_STRUCTURE) +
+ sizeof(EFI_ACPI_6_1_GENERIC_ERROR_DATA_ENTRY_STRUCTURE);
+ DEBUG ((DEBUG_INFO, "CperWrite - CperAddress@0x%x\n", CperAddress));
+ DEBUG ((DEBUG_INFO, "CperWrite - %d Section@%p, Length %d, SectionType@%p \n",
+ SectionInfo->SectionCount, SectionInfo->Section,
+ SectionInfo->DataLength, SectionInfo->SectionType));
+
+ ErrorRecordHeader = (EFI_COMMON_ERROR_RECORD_HEADER *)CperAddress;
+ _ErrorRecordDescriptor = (EFI_ERROR_SECTION_DESCRIPTOR *)
+ (CperAddress +
+ sizeof(EFI_COMMON_ERROR_RECORD_HEADER));
+ _ErrorRecord = (VOID *)_ErrorRecordDescriptor +
+ sizeof(EFI_ERROR_SECTION_DESCRIPTOR) * SectionInfo->SectionCount;
+
+ _ErrorSention = SectionInfo->Section;
+ ErrorSention_end = _ErrorSention + SectionInfo->DataLength;
+
+ //Init the Record Header
+ ErrorRecordHeader->SignatureStart = EFI_ERROR_RECORD_SIGNATURE_START;
+ ErrorRecordHeader->Revision = EFI_ERROR_RECORD_REVISION;
+ ErrorRecordHeader->SignatureEnd = EFI_ERROR_RECORD_SIGNATURE_END;
+
+ //TODO
+ ErrorRecordHeader->ValidationBits = 0;
+ //CopyGuid(&ErrorRecordHeader->PlatformID, );
+ //CopyGuid(&ErrorRecordHeader->PartitionID, );
+ //CopyGuid(&ErrorRecordHeader->CreatorID, );
+
+
+ Status = GetTimestamp(&ErrorRecordHeader->TimeStamp);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ //TODO: How to get this?
+ //Caller know this info, so can caller pass it to this function?
+ //CopyGuid(&ErrorRecordHeader->NotificationType, );
+
+ //TODO: These fields must to be filled according to the Hardware.
+ //ErrorRecordHeader->RecordID = ;
+ //ErrorRecordHeader->Flags = ;
+ //ErrorRecordHeader->PersistenceInfo = ;
+
+ for (j = 0; j < SectionInfo->SectionCount; j++) {
+
+ if (_ErrorSention >= ErrorSention_end) {
+ DEBUG ((EFI_D_ERROR, "CperWrite - SectionInfo Error.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //Getting Error Type from GUID
+ _ErrorSentionType = SectionInfo->SectionType + j;
+ for (i = 0; i < EFI_ERROR_SECTION_MAX_TYPE; i++ ) {
+ if (CompareGuid (EfiErrorSections_Guid + i, _ErrorSentionType))
+ break;
+ }
+
+ //Getting section data length from section type.
+ switch (i) {
+ case EFI_ERROR_SECTION_PROCESSOR_GENERIC_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Processor Generic.\n"));
+ _DataLength = sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA);
+ break;
+
+/* Unsupported*/
+/* case EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_TYPE:*/
+/* DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Processor Specific.\n"));*/
+/* _DataLength = sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA) + ;*/
+/* break;*/
+
+/* Comment out for 'default' debuging*/
+/* case EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_IA32X64_TYPE:*/
+/* DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Processor Specific x86.\n"));*/
+/* break;*/
+
+/* Unsupported*/
+/* case EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_ARM_TYPE:*/
+/* DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Processor Specific ARM.\n"));*/
+/* break;*/
+
+ case EFI_ERROR_SECTION_PLATFORM_MEMORY_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Platform Memory.\n"));
+ _DataLength = sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA);
+ break;
+
+ case EFI_ERROR_SECTION_PLATFORM_MEMORY2_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Platform Memory2.\n"));
+ _DataLength = sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA);
+ break;
+
+ case EFI_ERROR_SECTION_PCIE_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: PCIe.\n"));
+ _DataLength = sizeof(EFI_PCIE_ERROR_DATA);
+ break;
+
+ case EFI_ERROR_SECTION_FW_ERROR_RECORD_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Firmware Error.\n"));
+ _DataLength = sizeof(EFI_FIRMWARE_ERROR_DATA);
+ break;
+
+ case EFI_ERROR_SECTION_PCI_PCIX_BUS_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: PCIX.\n"));
+ _DataLength = sizeof(EFI_PCI_PCIX_BUS_ERROR_DATA);
+ break;
+
+/* Unsupported*/
+/* case EFI_ERROR_SECTION_PCI_DEVICE_TYPE:*/
+/* DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: PCI device.\n"));*/
+/* _DataLength = sizeof();*/
+/* break;*/
+
+ case EFI_ERROR_SECTION_DMAR_GENERIC_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: DMAR Generic.\n"));
+ _DataLength = sizeof(EFI_DMAR_GENERIC_ERROR_DATA);
+ break;
+
+ case EFI_ERROR_SECTION_DIRECTED_IO_DMAR_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: Directed IO DMAR.\n"));
+ _DataLength = sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA);
+ break;
+
+ case EFI_ERROR_SECTION_IOMMU_DMAR_TYPE:
+ DEBUG ((DEBUG_INFO, "CperWrite - Got Error Section: IOMMU DMAR.\n"));
+ _DataLength = sizeof(EFI_IOMMU_DMAR_ERROR_DATA);
+ break;
+
+ case EFI_ERROR_SECTION_MAX_TYPE:
+ DEBUG ((EFI_D_ERROR, "CperWrite - Fail to get Error Section Type.\n"));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "CperWrite - Unsupported Error Section Type: %d\n",
+ i));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //Init the Record Descriptor
+ _ErrorRecordDescriptor->SectionOffset = _ErrorSention - (VOID *)CperAddress;
+ _ErrorRecordDescriptor->SectionLength = _DataLength;
+ _ErrorRecordDescriptor->Revision = EFI_ERROR_SECTION_REVISION;
+ CopyGuid(&_ErrorRecordDescriptor->SectionType, _ErrorSentionType);
+
+ //TODO: Get this info from Cper data
+ //_ErrorRecordDescriptor->SectionFlags = ;
+ //_ErrorRecordDescriptor->Severity = ;
+
+ //TODO: These fields must to be filled according to the Hardware.
+ _ErrorRecordDescriptor->SecValidMask = 0x0;
+ //CopyGuid(_ErrorRecordDescriptor->FruId, );
+ //_ErrorRecordDescriptor->FruString = ;
+
+ //Copy Section data to the destination address
+ CopyMem (_ErrorRecord, _ErrorSention, _DataLength);
+
+ //Move to next section:
+ //increace src and des address of error data
+ //increace address of error record descriptor
+ _ErrorSention += _DataLength;
+ _ErrorRecord += _DataLength;
+ _ErrorRecordDescriptor += 1;
+ }
+
+ ErrorRecordHeader->SectionCount = j;
+ ErrorRecordHeader->RecordLength = _ErrorRecord - (VOID *)CperAddress;
+ //TODO: How to decide this info?
+ //ErrorRecordHeader->ErrorSeverity = ;
+
+ //For testing
+ UncorrectableErrorValid = 1;
+ CorrectableErrorValid = 0;
+ MultipleUncorrectableErrors = 0;
+ MultipleCorrectableErrors = 0;
+ //Fill the GenericErrorStatusBlock, according to the info above
+ GenericErrorStatusBlock->BlockStatus.UncorrectableErrorValid = UncorrectableErrorValid;
+ GenericErrorStatusBlock->BlockStatus.CorrectableErrorValid = CorrectableErrorValid;
+ GenericErrorStatusBlock->BlockStatus.MultipleUncorrectableErrors = MultipleUncorrectableErrors;
+ GenericErrorStatusBlock->BlockStatus.MultipleCorrectableErrors = MultipleCorrectableErrors;
+ //TODO: we just support only one ErrorDataEntry for now.
+ GenericErrorStatusBlock->BlockStatus.ErrorDataEntryCount = 1;
+
+ //TODO: what is the definition of "Raw Data"
+ GenericErrorStatusBlock->RawDataOffset = ErrorRecordHeader->RecordLength;
+ GenericErrorStatusBlock->RawDataLength = 0;
+
+ GenericErrorStatusBlock->DataLength = ErrorRecordHeader->RecordLength +
+ sizeof(EFI_ACPI_6_1_GENERIC_ERROR_DATA_ENTRY_STRUCTURE);
+ //TODO: set this value according to the error blob above
+ //GenericErrorStatusBlock->ErrorSeverity = ;
+
+ //TODO: which SectionType we should use if we have multiple sections?
+ //CopyGuid(GenericErrorDataEntry->SectionType, _ErrorSentionType);
+ //TODO: what ErrorSeverity we should set?
+ //GenericErrorDataEntry->ErrorSeverity = ;
+ GenericErrorDataEntry->Revision = EFI_ACPI_6_1_GENERIC_ERROR_DATA_ENTRY_REVISION;
+ //TODO: Get this info from Cper data
+ //GenericErrorDataEntry->Flags = ;
+ GenericErrorDataEntry->ErrorDataLength = ErrorRecordHeader->RecordLength;
+
+ GenericErrorDataEntry->ValidationBits = 0x04;
+ //TODO: These fields must to be filled according to the Hardware.
+ //CopyGuid(GenericErrorDataEntry->FruId, );
+ //GenericErrorDataEntry->FruText = ;
+ Status = GetTimestamp((EFI_ERROR_TIME_STAMP *)GenericErrorDataEntry->Timestamp);
+
+ return Status;
+}
+
+/**
+ This function parse the error source information argument to get the memory
+ info for the error source.
+
+ @param ErrorSource Error Source Information of a specific error source
+ @param ErrorRecordAddress
+
+ @retval EFI_SUCCESS Memory info successfully parsed.
+ @retval Other Some error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+CperInit (
+ IN EFI_APEI_ERROR_SOURCE *ErrorSource,
+ IN OUT UINTN *ErrorRecordAddress
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (! ErrorSource) {
+ DEBUG ((EFI_D_ERROR, "CperInit - Missing ErrorSection.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (! ErrorRecordAddress)
+ DEBUG ((EFI_D_ERROR, "CperInit - Missing ErrorRecordAddress parameter.\n"));
+
+ *ErrorRecordAddress = ErrorSource->ErrorStatusAddress.Address;
+
+ //TODO: maybe we need more init here
+
+ DEBUG ((DEBUG_INFO, "CperInit - ErrorSources %p, ErrorRecordAddress@0x%x\n",
+ ErrorSource, ErrorRecordAddress));
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+CperLibConstructor (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ //TODO: What we need to do to init this library.
+ //
+ Status = EFI_SUCCESS;
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "CperLibConstructor\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The destructor function frees resource used in the Mm Mem library
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The deconstructor always returns EFI_SUCCESS.
+**/
+EFI_STATUS
+EFIAPI
+CperLibDestructor (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "CperLibDestructor\n"));
+ return EFI_SUCCESS;
+}
diff --git a/StandaloneMmPkg/Library/CperLib/CperLib.inf b/StandaloneMmPkg/Library/CperLib/CperLib.inf
new file mode 100644
index 0000000000..cda287c074
--- /dev/null
+++ b/StandaloneMmPkg/Library/CperLib/CperLib.inf
@@ -0,0 +1,47 @@
+#/** @file
+#
+# Common Platform Error Record (CPER) Library.
+#
+# Copyright (c) 2017, Linaro Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = CperLib
+ MODULE_UNI_FILE = CperLib.uni
+ FILE_GUID = 07BC4CA2-27F3-4339-AC20-332B8EDD2BA5
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CperLib
+ CONSTRUCTOR = CperLibConstructor
+ DESTRUCTOR = CperLibDestructor
+
+#
+# VALID_ARCHITECTURES = AARCH64
+#
+
+
+[Sources]
+ CperLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+
+[LibraryClasses]
+ DebugLib
+ BaseLib
+ PcdLib
+
+[Pcd]
diff --git a/StandaloneMmPkg/Library/CperLib/CperLib.uni b/StandaloneMmPkg/Library/CperLib/CperLib.uni
new file mode 100644
index 0000000000..2b45cfee0e
--- /dev/null
+++ b/StandaloneMmPkg/Library/CperLib/CperLib.uni
@@ -0,0 +1,29 @@
+/** @file
+ Common Platform Error Record (CPER) Library.
+
+ CPER Library initializes the error source information from error source
+ definition module and provides read/write services to MM Standalone and/or
+ DXE drivers. The intention is to have a generic library which can be included
+ in either non-secure or secure world or both. At present, only the secure
+ world implementation is targeted.
+ The general format of the common platform error record:
+ The record consists of a header, followed by one or more section
+ descriptors, and for each descriptor, an associated section which may
+ contain eithererror or informational data.
+
+ Copyright (c) 2017, ARM Limited. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD
+ License which accompanies this distribution. The full text of the license may
+ be found at http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Instance of CPER Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "CPER Library that initializes the error source information from error source definition module"
diff --git a/StandaloneMmPkg/StandaloneMmPkg.dec b/StandaloneMmPkg/StandaloneMmPkg.dec
index 754678ba3e..e688ba3844 100644
--- a/StandaloneMmPkg/StandaloneMmPkg.dec
+++ b/StandaloneMmPkg/StandaloneMmPkg.dec
@@ -37,6 +37,9 @@
gMmCommTestGuid = { 0xa37721e4, 0x8c0b, 0x4bca, { 0xb5, 0xe8, 0xe9, 0x2, 0xa0, 0x25, 0x51, 0x4e }}
+ ## Include/Library/CperLib.h
+ gEfiApeiCperLibGuid = { 0xb5aabe64, 0xf09a, 0x4b94, { 0x8e, 0xfa, 0x2e, 0x23, 0x4d, 0x00, 0x6d, 0x3e }}
+
[PcdsFeatureFlag]
gStandaloneMmPkgTokenSpaceGuid.PcdStandaloneMmEnable|FALSE|BOOLEAN|0x00000001