Add support for IOMMU/VT-d specific sections.
diff --git a/cper-parse.c b/cper-parse.c
index c357c7d..6c743a1 100644
--- a/cper-parse.c
+++ b/cper-parse.c
@@ -19,6 +19,8 @@
#include "sections/cper-section-pci-dev.h"
#include "sections/cper-section-firmware.h"
#include "sections/cper-section-dmar-generic.h"
+#include "sections/cper-section-dmar-vtd.h"
+#include "sections/cper-section-dmar-iommu.h"
//Private pre-definitions.
json_object* cper_header_to_ir(EFI_COMMON_ERROR_RECORD_HEADER* header);
@@ -303,6 +305,7 @@
descriptor->SectionOffset);
}
+ //Parse section to IR based on GUID.
json_object* result = NULL;
if (guid_equal(&descriptor->SectionType, &gEfiProcessorGenericErrorSectionGuid))
result = cper_section_generic_to_ir(section, descriptor);
@@ -326,10 +329,15 @@
result = cper_section_pci_dev_to_ir(section, descriptor);
else if (guid_equal(&descriptor->SectionType, &gEfiDMArGenericErrorSectionGuid))
result = cper_section_dmar_generic_to_ir(section, descriptor);
- // if (guid_equal(&descriptor->SectionType, &gEfiDirectedIoDMArErrorSectionGuid))
- // result = cper_section_intel_io_dma_to_ir(section);
- // if (guid_equal(&descriptor->SectionType, &gEfiIommuDMArErrorSectionGuid))
- // result = cper_section_iommu_dma_to_ir(section);
+ else if (guid_equal(&descriptor->SectionType, &gEfiDirectedIoDMArErrorSectionGuid))
+ 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
+ {
+ //Failed read, unknown GUID.
+ //todo: dump the binary data out to b64.
+ }
//Free section memory, return result.
free(section);
diff --git a/sections/cper-section-dmar-iommu.c b/sections/cper-section-dmar-iommu.c
new file mode 100644
index 0000000..14d66a3
--- /dev/null
+++ b/sections/cper-section-dmar-iommu.c
@@ -0,0 +1,41 @@
+/**
+ * Describes functions for converting IOMMU specific DMAr 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-dmar-iommu.h"
+
+//Converts a single IOMMU specific DMAr CPER section into JSON IR.
+json_object* cper_section_dmar_iommu_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
+{
+ EFI_IOMMU_DMAR_ERROR_DATA* iommu_error = (EFI_IOMMU_DMAR_ERROR_DATA*)section;
+ json_object* section_ir = json_object_new_object();
+
+ //Revision.
+ json_object_object_add(section_ir, "revision", json_object_new_int(iommu_error->Revision));
+
+ //IOMMU registers.
+ json_object_object_add(section_ir, "controlRegister", json_object_new_uint64(iommu_error->Control));
+ json_object_object_add(section_ir, "statusRegister", json_object_new_uint64(iommu_error->Status));
+
+ //IOMMU event log entry.
+ //todo: implement as specified in the IOMMU specification
+
+ //Device table entry.
+ //todo: dump as b64
+
+ //Page table entries.
+ json_object_object_add(section_ir, "pageTableEntry_Level6", json_object_new_uint64(iommu_error->PteL6));
+ json_object_object_add(section_ir, "pageTableEntry_Level5", json_object_new_uint64(iommu_error->PteL5));
+ json_object_object_add(section_ir, "pageTableEntry_Level4", json_object_new_uint64(iommu_error->PteL4));
+ json_object_object_add(section_ir, "pageTableEntry_Level3", json_object_new_uint64(iommu_error->PteL3));
+ json_object_object_add(section_ir, "pageTableEntry_Level2", json_object_new_uint64(iommu_error->PteL2));
+ json_object_object_add(section_ir, "pageTableEntry_Level1", json_object_new_uint64(iommu_error->PteL1));
+
+ return section_ir;
+}
\ No newline at end of file
diff --git a/sections/cper-section-dmar-iommu.h b/sections/cper-section-dmar-iommu.h
new file mode 100644
index 0000000..b86b640
--- /dev/null
+++ b/sections/cper-section-dmar-iommu.h
@@ -0,0 +1,9 @@
+#ifndef CPER_SECTION_DMAR_IOMMU_H
+#define CPER_SECTION_DMAR_IOMMU_H
+
+#include "json.h"
+#include "../edk/Cper.h"
+
+json_object* cper_section_dmar_iommu_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+
+#endif
\ No newline at end of file
diff --git a/sections/cper-section-dmar-vtd.c b/sections/cper-section-dmar-vtd.c
new file mode 100644
index 0000000..a7e13a7
--- /dev/null
+++ b/sections/cper-section-dmar-vtd.c
@@ -0,0 +1,44 @@
+/**
+ * Describes functions for converting VT-d specific DMAr 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-dmar-vtd.h"
+
+//Converts a single VT-d specific DMAr CPER section into JSON IR.
+json_object* cper_section_dmar_vtd_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
+{
+ EFI_DIRECTED_IO_DMAR_ERROR_DATA* vtd_error = (EFI_DIRECTED_IO_DMAR_ERROR_DATA*)section;
+ json_object* section_ir = json_object_new_object();
+
+ //Version, revision and OEM ID, as defined in the VT-d architecture.
+ UINT64 oem_id = (vtd_error->OemId[0] << 16) + (vtd_error->OemId[1] << 8) + vtd_error->OemId[2];
+ json_object_object_add(section_ir, "version", json_object_new_int(vtd_error->Version));
+ json_object_object_add(section_ir, "revision", json_object_new_int(vtd_error->Revision));
+ json_object_object_add(section_ir, "oemID", json_object_new_uint64(oem_id));
+
+ //Registers.
+ json_object_object_add(section_ir, "capabilityRegister", json_object_new_uint64(vtd_error->Capability));
+ json_object_object_add(section_ir, "extendedCapabilityRegister", json_object_new_uint64(vtd_error->CapabilityEx));
+ json_object_object_add(section_ir, "globalCommandRegister", json_object_new_uint64(vtd_error->GlobalCommand));
+ json_object_object_add(section_ir, "globalStatusRegister", json_object_new_uint64(vtd_error->GlobalStatus));
+ json_object_object_add(section_ir, "faultStatusRegister", json_object_new_uint64(vtd_error->FaultStatus));
+
+ //Fault record, root and context entry.
+ //todo: Look at the VT-d specification and implement
+
+ //PTE entry for all page levels.
+ json_object_object_add(section_ir, "pageTableEntry_Level6", json_object_new_uint64(vtd_error->PteL6));
+ json_object_object_add(section_ir, "pageTableEntry_Level5", json_object_new_uint64(vtd_error->PteL5));
+ json_object_object_add(section_ir, "pageTableEntry_Level4", json_object_new_uint64(vtd_error->PteL4));
+ json_object_object_add(section_ir, "pageTableEntry_Level3", json_object_new_uint64(vtd_error->PteL3));
+ json_object_object_add(section_ir, "pageTableEntry_Level2", json_object_new_uint64(vtd_error->PteL2));
+ json_object_object_add(section_ir, "pageTableEntry_Level1", json_object_new_uint64(vtd_error->PteL1));
+
+ return section_ir;
+}
\ No newline at end of file
diff --git a/sections/cper-section-dmar-vtd.h b/sections/cper-section-dmar-vtd.h
new file mode 100644
index 0000000..48be0d2
--- /dev/null
+++ b/sections/cper-section-dmar-vtd.h
@@ -0,0 +1,9 @@
+#ifndef CPER_SECTION_DMAR_VTD_H
+#define CPER_SECTION_DMAR_VTD_H
+
+#include "json.h"
+#include "../edk/Cper.h"
+
+json_object* cper_section_dmar_vtd_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+
+#endif
\ No newline at end of file
diff --git a/sections/cper-section-pcie.c b/sections/cper-section-pcie.c
index 4298889..6074839 100644
--- a/sections/cper-section-pcie.c
+++ b/sections/cper-section-pcie.c
@@ -41,9 +41,9 @@
//PCIe Device ID.
json_object* device_id = json_object_new_object();
- UINT64 class_id = pcie_error->DevBridge.ClassCode[0] +
+ UINT64 class_id = (pcie_error->DevBridge.ClassCode[0] << 16) +
(pcie_error->DevBridge.ClassCode[1] << 8) +
- (pcie_error->DevBridge.ClassCode[2] << 16);
+ pcie_error->DevBridge.ClassCode[2];
json_object_object_add(device_id, "vendorID", json_object_new_uint64(pcie_error->DevBridge.VendorId));
json_object_object_add(device_id, "deviceID", json_object_new_uint64(pcie_error->DevBridge.DeviceId));
json_object_object_add(device_id, "classCode", json_object_new_uint64(class_id));