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));