Add CCIX PER section support.
diff --git a/cper-parse.c b/cper-parse.c
index 6c743a1..a9c7bdc 100644
--- a/cper-parse.c
+++ b/cper-parse.c
@@ -21,6 +21,7 @@
#include "sections/cper-section-dmar-generic.h"
#include "sections/cper-section-dmar-vtd.h"
#include "sections/cper-section-dmar-iommu.h"
+#include "sections/cper-section-ccix-per.h"
//Private pre-definitions.
json_object* cper_header_to_ir(EFI_COMMON_ERROR_RECORD_HEADER* header);
@@ -239,29 +240,31 @@
char* section_type_readable = "Unknown";
if (guid_equal(§ion_descriptor->SectionType, &gEfiProcessorGenericErrorSectionGuid))
section_type_readable = "Processor Generic";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiIa32X64ProcessorErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiIa32X64ProcessorErrorSectionGuid))
section_type_readable = "IA32/X64";
//todo: Why does IPF have an overly long GUID?
// if (guid_equal(§ion_descriptor->SectionType, &gEfiIpfProcessorErrorSectionGuid))
// section_type_readable = "IPF";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiArmProcessorErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiArmProcessorErrorSectionGuid))
section_type_readable = "ARM";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiPlatformMemoryErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiPlatformMemoryErrorSectionGuid))
section_type_readable = "Platform Memory";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiPcieErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiPcieErrorSectionGuid))
section_type_readable = "PCIe";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiFirmwareErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiFirmwareErrorSectionGuid))
section_type_readable = "Firmware Error Record Reference";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiPciBusErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiPciBusErrorSectionGuid))
section_type_readable = "PCI/PCI-X Bus";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiPciDevErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiPciDevErrorSectionGuid))
section_type_readable = "PCI Component/Device";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiDMArGenericErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiDMArGenericErrorSectionGuid))
section_type_readable = "DMAr Generic";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiDirectedIoDMArErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiDirectedIoDMArErrorSectionGuid))
section_type_readable = "Intel VT for Directed I/O specific DMAr section";
- if (guid_equal(§ion_descriptor->SectionType, &gEfiIommuDMArErrorSectionGuid))
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiIommuDMArErrorSectionGuid))
section_type_readable = "IOMMU specific DMAr section";
+ else if (guid_equal(§ion_descriptor->SectionType, &gEfiCcixPerLogErrorSectionGuid))
+ section_type_readable = "CCIX PER Log Error";
//todo: How do you determine if this is a CXL component event?
// if (guid_equal(§ion_descriptor->SectionType, &gEfiProcessorGenericErrorSectionGuid))
@@ -333,6 +336,8 @@
result = cper_section_dmar_vtd_to_ir(section, descriptor);
else if (guid_equal(&descriptor->SectionType, &gEfiIommuDMArErrorSectionGuid))
result = cper_section_dmar_iommu_to_ir(section, descriptor);
+ else if (guid_equal(&descriptor->SectionType, &gEfiCcixPerLogErrorSectionGuid))
+ result = cper_section_ccix_per_to_ir(section, descriptor);
else
{
//Failed read, unknown GUID.
diff --git a/edk/Cper.c b/edk/Cper.c
index d11dfdd..dfed1ae 100644
--- a/edk/Cper.c
+++ b/edk/Cper.c
@@ -35,6 +35,7 @@
EFI_GUID gEfiDMArGenericErrorSectionGuid = { 0x5b51fef7, 0xc79d, 0x4434, { 0x8f, 0x1b, 0xaa, 0x62, 0xde, 0x3e, 0x2c, 0x64 }};
EFI_GUID gEfiDirectedIoDMArErrorSectionGuid = { 0x71761d37, 0x32b2, 0x45cd, { 0xa7, 0xd0, 0xb0, 0xfe, 0xdd, 0x93, 0xe8, 0xcf }};
EFI_GUID gEfiIommuDMArErrorSectionGuid = { 0x036f84e1, 0x7f37, 0x428c, { 0xa7, 0x9e, 0x57, 0x5f, 0xdf, 0xaa, 0x84, 0xec }};
+EFI_GUID gEfiCcixPerLogErrorSectionGuid = { 0x91335EF6, 0xEBFB, 0x4478, {0xA6, 0xA6, 0x88, 0xB7, 0x28, 0xCF, 0x75, 0xD7 }};
//IA32/x64 error segment GUIDs.
EFI_GUID gEfiIa32x64ErrorTypeCacheCheckGuid = { 0xA55701F5, 0xE3EF, 0x43de, {0xAC, 0x72, 0x24, 0x9B, 0x57, 0x3F, 0xAD, 0x2C } };
diff --git a/edk/Cper.h b/edk/Cper.h
index 4eb470d..a2e2fb6 100644
--- a/edk/Cper.h
+++ b/edk/Cper.h
@@ -1265,7 +1265,7 @@
extern EFI_GUID gEfiDMArGenericErrorSectionGuid;
extern EFI_GUID gEfiDirectedIoDMArErrorSectionGuid;
extern EFI_GUID gEfiIommuDMArErrorSectionGuid;
-
+extern EFI_GUID gEfiCcixPerLogErrorSectionGuid;
#pragma pack()
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
diff --git a/sections/cper-section-ccix-per.c b/sections/cper-section-ccix-per.c
new file mode 100644
index 0000000..ae8a797
--- /dev/null
+++ b/sections/cper-section-ccix-per.c
@@ -0,0 +1,35 @@
+/**
+ * Describes functions for converting CCIX PER log CPER sections from binary and JSON format
+ * into an intermediate format.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+#include <stdio.h>
+#include "json.h"
+#include "../edk/Cper.h"
+#include "../cper-utils.h"
+#include "cper-section-ccix-per.h"
+
+//Converts a single CCIX PER log CPER section into JSON IR.
+json_object* cper_section_ccix_per_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
+{
+ EFI_CCIX_PER_LOG_DATA* ccix_error = (EFI_CCIX_PER_LOG_DATA*)section;
+ json_object* section_ir = json_object_new_object();
+
+ //Length (bytes) for the entire structure.
+ json_object_object_add(section_ir, "length", json_object_new_uint64(ccix_error->Length));
+
+ //Validation bits.
+ json_object* validation = bitfield_to_ir(ccix_error->ValidBits, 3, CCIX_PER_ERROR_VALID_BITFIELD_NAMES);
+ json_object_object_add(section_ir, "validationBits", validation);
+
+ //CCIX source/port IDs.
+ json_object_object_add(section_ir, "ccixSourceID", json_object_new_int(ccix_error->CcixSourceId));
+ json_object_object_add(section_ir, "ccixPortID", json_object_new_int(ccix_error->CcixPortId));
+
+ //CCIX PER Log.
+ //todo: implement as described in Section 7.3.2 of CCIX Base Specification (Rev 1.0)
+ //the PER Log structure notes the number of DWORDs in the record.
+
+ return section_ir;
+}
\ No newline at end of file
diff --git a/sections/cper-section-ccix-per.h b/sections/cper-section-ccix-per.h
new file mode 100644
index 0000000..1f01368
--- /dev/null
+++ b/sections/cper-section-ccix-per.h
@@ -0,0 +1,22 @@
+#ifndef CPER_SECTION_CCIX_PER_H
+#define CPER_SECTION_CCIX_PER_H
+
+#include "json.h"
+#include "../edk/Cper.h"
+
+#define CCIX_PER_ERROR_VALID_BITFIELD_NAMES (const char*[]) {"ccixSourceIDValid", "ccixPortIDValid", "ccixPERLogValid"}
+
+///
+/// CCIX PER Log Error Section
+///
+typedef struct {
+ UINT32 Length;
+ UINT64 ValidBits;
+ UINT8 CcixSourceId;
+ UINT8 CcixPortId;
+ UINT16 Reserved;
+} EFI_CCIX_PER_LOG_DATA;
+
+json_object* cper_section_ccix_per_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+
+#endif
\ No newline at end of file