Add all DMAR, CCIX, PCI, firmware conversions.
diff --git a/sections/cper-section-ccix-per.c b/sections/cper-section-ccix-per.c
index afba8d4..1df7d1b 100644
--- a/sections/cper-section-ccix-per.c
+++ b/sections/cper-section-ccix-per.c
@@ -5,6 +5,7 @@
  * Author: Lawrence.Tang@arm.com
  **/
 #include <stdio.h>
+#include <string.h>
 #include "json.h"
 #include "b64.h"
 #include "../edk/Cper.h"
@@ -31,7 +32,7 @@
     //CCIX PER Log.
     //This is formatted as described in Section 7.3.2 of CCIX Base Specification (Rev 1.0).
     unsigned char* cur_pos = (unsigned char*)(ccix_error + 1);
-    int remaining_length = section - (void*)cur_pos + ccix_error->Length;
+    int remaining_length = ccix_error->Length - sizeof(ccix_error);
     if (remaining_length > 0)
     {
         char* encoded = b64_encode(cur_pos, remaining_length);
@@ -40,4 +41,36 @@
     }
 
     return section_ir;
+}
+
+//Converts a single CCIX PER CPER-JSON section into CPER binary, outputting to the given stream.
+void ir_section_ccix_per_to_cper(json_object* section, FILE* out)
+{
+    EFI_CCIX_PER_LOG_DATA* section_cper =
+        (EFI_CCIX_PER_LOG_DATA*)calloc(1, sizeof(EFI_CCIX_PER_LOG_DATA));
+
+    //Length.
+    section_cper->Length = json_object_get_uint64(json_object_object_get(section, "length"));
+
+    //Validation bits.
+    section_cper->ValidBits = ir_to_bitfield(json_object_object_get(section, "validationBits"), 
+        3, CCIX_PER_ERROR_VALID_BITFIELD_NAMES);
+
+    //CCIX source/port IDs.
+    section_cper->CcixSourceId = (UINT8)json_object_get_int(json_object_object_get(section, "ccixSourceID"));
+    section_cper->CcixPortId = (UINT8)json_object_get_int(json_object_object_get(section, "ccixPortID"));
+    
+    //Write header out to stream.
+    fwrite(&section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+
+    //Write CCIX PER log itself to stream.
+    json_object* encoded = json_object_object_get(section, "ccixPERLog");
+    UINT8* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    fwrite(decoded, section_cper->Length - sizeof(section_cper), 1, out);
+    fflush(out);
+
+    //Free resources.
+    free(decoded);
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-ccix-per.h b/sections/cper-section-ccix-per.h
index 1f01368..0fbefe5 100644
--- a/sections/cper-section-ccix-per.h
+++ b/sections/cper-section-ccix-per.h
@@ -18,5 +18,6 @@
 } EFI_CCIX_PER_LOG_DATA;
 
 json_object* cper_section_ccix_per_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_ccix_per_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file
diff --git a/sections/cper-section-dmar-generic.c b/sections/cper-section-dmar-generic.c
index 26934f8..6d2460d 100644
--- a/sections/cper-section-dmar-generic.c
+++ b/sections/cper-section-dmar-generic.c
@@ -53,4 +53,25 @@
     json_object_object_add(section_ir, "deviceAddress", json_object_new_uint64(firmware_error->DeviceAddr));
     
     return section_ir;
+}
+
+//Converts a single generic DMAR CPER-JSON section into CPER binary, outputting to the given stream.
+void ir_section_dmar_generic_to_cper(json_object* section, FILE* out)
+{
+    EFI_DMAR_GENERIC_ERROR_DATA* section_cper =
+        (EFI_DMAR_GENERIC_ERROR_DATA*)calloc(1, sizeof(EFI_DMAR_GENERIC_ERROR_DATA));
+
+    //Record fields.
+    section_cper->RequesterId = (UINT16)json_object_get_int(json_object_object_get(section, "requesterID"));
+    section_cper->SegmentNumber = (UINT16)json_object_get_int(json_object_object_get(section, "segmentNumber"));
+    section_cper->FaultReason = (UINT8)readable_pair_to_integer(json_object_object_get(section, "faultReason"));
+    section_cper->AccessType = (UINT8)readable_pair_to_integer(json_object_object_get(section, "accessType"));
+    section_cper->AddressType = (UINT8)readable_pair_to_integer(json_object_object_get(section, "addressType"));
+    section_cper->ArchType = (UINT8)readable_pair_to_integer(json_object_object_get(section, "archType"));
+    section_cper->DeviceAddr = json_object_get_uint64(json_object_object_get(section, "deviceAddress"));
+
+    //Write to stream, free resources.
+    fwrite(&section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-dmar-generic.h b/sections/cper-section-dmar-generic.h
index 682818f..14b65a9 100644
--- a/sections/cper-section-dmar-generic.h
+++ b/sections/cper-section-dmar-generic.h
@@ -27,5 +27,7 @@
 #define DMAR_GENERIC_ERROR_ARCH_TYPES_VALUES (const char*[]){"VT-d", "IOMMU"}
 
 json_object* cper_section_dmar_generic_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_dmar_generic_to_cper(json_object* section, FILE* out);
+
 
 #endif
\ No newline at end of file
diff --git a/sections/cper-section-dmar-iommu.c b/sections/cper-section-dmar-iommu.c
index 69b150a..0298df0 100644
--- a/sections/cper-section-dmar-iommu.c
+++ b/sections/cper-section-dmar-iommu.c
@@ -5,6 +5,7 @@
  * Author: Lawrence.Tang@arm.com
  **/
 #include <stdio.h>
+#include <string.h>
 #include "json.h"
 #include "b64.h"
 #include "../edk/Cper.h"
@@ -44,4 +45,41 @@
     json_object_object_add(section_ir, "pageTableEntry_Level1", json_object_new_uint64(iommu_error->PteL1));
 
     return section_ir;
+}
+
+//Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream.
+void ir_section_dmar_iommu_to_cper(json_object* section, FILE* out)
+{
+    EFI_IOMMU_DMAR_ERROR_DATA* section_cper =
+        (EFI_IOMMU_DMAR_ERROR_DATA*)calloc(1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA));
+
+    //Revision, registers.
+    section_cper->Revision = (UINT8)json_object_get_int(json_object_object_get(section, "revision"));
+    section_cper->Control = json_object_get_uint64(json_object_object_get(section, "controlRegister"));
+    section_cper->Status = json_object_get_uint64(json_object_object_get(section, "statusRegister"));
+
+    //IOMMU event log entry.
+    json_object* encoded = json_object_object_get(section, "eventLogEntry");
+    UINT8* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    memcpy(section_cper->EventLogEntry, decoded, 16);
+    free(decoded);
+
+    //Device table entry.
+    encoded = json_object_object_get(section, "deviceTableEntry");
+    decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    memcpy(section_cper->DeviceTableEntry, decoded, 32);
+    free(decoded);
+
+    //Page table entries.
+    section_cper->PteL1 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level1"));
+    section_cper->PteL2 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level2"));
+    section_cper->PteL3 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level3"));
+    section_cper->PteL4 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level4"));
+    section_cper->PteL5 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level5"));
+    section_cper->PteL6 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level6"));
+
+    //Write to stream, free resources.
+    fwrite(&section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-dmar-iommu.h b/sections/cper-section-dmar-iommu.h
index b86b640..eaac1ae 100644
--- a/sections/cper-section-dmar-iommu.h
+++ b/sections/cper-section-dmar-iommu.h
@@ -5,5 +5,6 @@
 #include "../edk/Cper.h"
 
 json_object* cper_section_dmar_iommu_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_dmar_iommu_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file
diff --git a/sections/cper-section-dmar-vtd.c b/sections/cper-section-dmar-vtd.c
index 734e88a..c15c5f4 100644
--- a/sections/cper-section-dmar-vtd.c
+++ b/sections/cper-section-dmar-vtd.c
@@ -5,6 +5,7 @@
  * Author: Lawrence.Tang@arm.com
  **/
 #include <stdio.h>
+#include <string.h>
 #include "json.h"
 #include "b64.h"
 #include "../edk/Cper.h"
@@ -44,7 +45,7 @@
     json_object_object_add(fault_record_ir, "pasidValue", json_object_new_uint64(fault_record->PasidValue));
     json_object_object_add(fault_record_ir, "addressType", json_object_new_uint64(fault_record->AddressType));
 
-    //Fault record address type.
+    //Fault record type.
     json_object* fault_record_type = integer_to_readable_pair(fault_record->Type, 2,
         VTD_FAULT_RECORD_TYPES_KEYS,
         VTD_FAULT_RECORD_TYPES_VALUES,
@@ -71,4 +72,70 @@
     json_object_object_add(section_ir, "pageTableEntry_Level1", json_object_new_uint64(vtd_error->PteL1));
 
     return section_ir;
+}
+
+//Converts a single VT-d DMAR CPER-JSON segment into CPER binary, outputting to the given stream.
+void ir_section_dmar_vtd_to_cper(json_object* section, FILE* out)
+{
+    EFI_DIRECTED_IO_DMAR_ERROR_DATA* section_cper =
+        (EFI_DIRECTED_IO_DMAR_ERROR_DATA*)calloc(1, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA));
+
+    //OEM ID.
+    UINT64 oem_id = json_object_get_uint64(json_object_object_get(section, "oemID"));
+    section_cper->OemId[0] = oem_id >> 16;
+    section_cper->OemId[1] = (oem_id >> 8) & 0xFF;
+    section_cper->OemId[1] = oem_id & 0xFF;
+
+    //Registers & basic numeric fields.
+    section_cper->Version = (UINT8)json_object_get_int(json_object_object_get(section, "version"));
+    section_cper->Revision = (UINT8)json_object_get_int(json_object_object_get(section, "revision"));
+    section_cper->Capability = json_object_get_uint64(json_object_object_get(section, "capabilityRegister"));
+    section_cper->CapabilityEx = json_object_get_uint64(json_object_object_get(section, "extendedCapabilityRegister"));
+
+    //Fault record.
+    json_object* fault_record = json_object_object_get(section, "faultRecord");
+    EFI_VTD_FAULT_RECORD* fault_record_cper = (EFI_VTD_FAULT_RECORD*)section_cper->FaultRecord;
+    fault_record_cper->FaultInformation = 
+        json_object_get_uint64(json_object_object_get(fault_record, "faultInformation"));
+    fault_record_cper->SourceIdentifier = 
+        json_object_get_uint64(json_object_object_get(fault_record, "sourceIdentifier"));
+    fault_record_cper->PrivelegeModeRequested = 
+        json_object_get_boolean(json_object_object_get(fault_record, "privelegeModeRequested"));
+    fault_record_cper->ExecutePermissionRequested = 
+        json_object_get_boolean(json_object_object_get(fault_record, "executePermissionRequested"));
+    fault_record_cper->PasidPresent = 
+        json_object_get_boolean(json_object_object_get(fault_record, "pasidPresent"));
+    fault_record_cper->FaultReason = 
+        json_object_get_uint64(json_object_object_get(fault_record, "faultReason"));
+    fault_record_cper->PasidValue = 
+        json_object_get_uint64(json_object_object_get(fault_record, "pasidValue"));
+    fault_record_cper->AddressType = 
+        json_object_get_uint64(json_object_object_get(fault_record, "addressType"));
+    fault_record_cper->Type = 
+        readable_pair_to_integer(json_object_object_get(fault_record, "type"));
+        
+    //Root entry.
+    json_object* encoded = json_object_object_get(section, "rootEntry");
+    UINT8* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    memcpy(section_cper->RootEntry, decoded, 16);
+    free(decoded);
+
+    //Context entry.
+    encoded = json_object_object_get(section, "contextEntry");
+    decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    memcpy(section_cper->ContextEntry, decoded, 16);
+    free(decoded);
+
+    //Page table entries.
+    section_cper->PteL1 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level1"));
+    section_cper->PteL2 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level2"));
+    section_cper->PteL3 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level3"));
+    section_cper->PteL4 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level4"));
+    section_cper->PteL5 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level5"));
+    section_cper->PteL6 = json_object_get_uint64(json_object_object_get(section, "pageTableEntry_Level6"));
+
+    //Write to stream, free resources.
+    fwrite(&section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-dmar-vtd.h b/sections/cper-section-dmar-vtd.h
index 54e2082..4a49e56 100644
--- a/sections/cper-section-dmar-vtd.h
+++ b/sections/cper-section-dmar-vtd.h
@@ -23,5 +23,6 @@
 } EFI_VTD_FAULT_RECORD;
 
 json_object* cper_section_dmar_vtd_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_dmar_vtd_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file
diff --git a/sections/cper-section-firmware.c b/sections/cper-section-firmware.c
index 03ce456..02795dd 100644
--- a/sections/cper-section-firmware.c
+++ b/sections/cper-section-firmware.c
@@ -33,4 +33,23 @@
     json_object_object_add(section_ir, "recordIDGUID", json_object_new_string(record_id_guid));
 
     return section_ir;
+}
+
+//Converts a single firmware CPER-JSON section into CPER binary, outputting to the given stream.
+void ir_section_firmware_to_cper(json_object* section, FILE* out)
+{
+    EFI_FIRMWARE_ERROR_DATA* section_cper =
+        (EFI_FIRMWARE_ERROR_DATA*)calloc(1, sizeof(EFI_FIRMWARE_ERROR_DATA));
+
+    //Record fields.
+    section_cper->ErrorType = readable_pair_to_integer(json_object_object_get(section, "errorRecordType"));
+    section_cper->Revision = json_object_get_int(json_object_object_get(section, "revision"));
+    section_cper->RecordId = json_object_get_uint64(json_object_object_get(section, "revision"));
+    string_to_guid(&section_cper->RecordIdGuid, 
+        json_object_get_string(json_object_object_get(section, "recordIDGUID")));
+
+    //Write to stream, free resources.
+    fwrite(&section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-firmware.h b/sections/cper-section-firmware.h
index a879c12..531ddf7 100644
--- a/sections/cper-section-firmware.h
+++ b/sections/cper-section-firmware.h
@@ -9,5 +9,6 @@
     "SOC Firmware Error Record (Type1 Legacy)", "SOC Firmware Error Record (Type2)"}
 
 json_object* cper_section_firmware_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_firmware_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file
diff --git a/sections/cper-section-pci-bus.c b/sections/cper-section-pci-bus.c
index a219674..db034d1 100644
--- a/sections/cper-section-pci-bus.c
+++ b/sections/cper-section-pci-bus.c
@@ -46,4 +46,39 @@
     json_object_object_add(section_ir, "targetID", json_object_new_uint64(bus_error->TargetId));
 
     return section_ir;
+}
+
+//Converts a single provided PCI/PCI-X bus CPER-JSON section into CPER binary, outputting to the
+//provided stream.
+void ir_section_pci_bus_to_cper(json_object* section, FILE* out)
+{
+    EFI_PCI_PCIX_BUS_ERROR_DATA* section_cper =
+        (EFI_PCI_PCIX_BUS_ERROR_DATA*)calloc(1, sizeof(EFI_PCI_PCIX_BUS_ERROR_DATA));
+
+    //Validation bits.
+    section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"), 
+        9, PCI_BUS_ERROR_VALID_BITFIELD_NAMES);
+
+    //Error status.
+    ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
+
+    //Bus ID.
+    json_object* bus_id = json_object_object_get(section, "busID");
+    UINT16 bus_number = (UINT8)json_object_get_int(json_object_object_get(bus_id, "busNumber"));
+    UINT16 segment_number = (UINT8)json_object_get_int(json_object_object_get(bus_id, "segmentNumber"));
+    section_cper->BusId = bus_number + (segment_number << 8);
+
+    //Remaining fields.
+    section_cper->Type = (UINT16)readable_pair_to_integer(json_object_object_get(section, "errorType"));
+    section_cper->BusAddress = json_object_get_uint64(json_object_object_get(section, "busAddress"));
+    section_cper->BusData = json_object_get_uint64(json_object_object_get(section, "busData"));
+    section_cper->BusCommand = json_object_get_string(json_object_object_get(section, "busCommand")) == "PCI" ? 0 : 1;
+    section_cper->RequestorId = json_object_get_uint64(json_object_object_get(section, "requestorID"));
+    section_cper->ResponderId = json_object_get_uint64(json_object_object_get(section, "responderID"));
+    section_cper->TargetId = json_object_get_uint64(json_object_object_get(section, "targetID"));
+
+    //Write to stream, free resources.
+    fwrite(&section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-pci-bus.h b/sections/cper-section-pci-bus.h
index e0e1bbb..ab44b53 100644
--- a/sections/cper-section-pci-bus.h
+++ b/sections/cper-section-pci-bus.h
@@ -13,5 +13,6 @@
     "Master Data Parity Error", "Address Parity Error", "Command Parity Error"}
 
 json_object* cper_section_pci_bus_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_pci_bus_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file
diff --git a/sections/cper-section-pci-dev.c b/sections/cper-section-pci-dev.c
index aa3857b..cf4eb61 100644
--- a/sections/cper-section-pci-dev.c
+++ b/sections/cper-section-pci-dev.c
@@ -59,4 +59,54 @@
     json_object_object_add(section_ir, "registerDataPairs", register_data_pair_array);
 
     return section_ir;
+}
+
+void ir_section_pci_dev_to_cper(json_object* section, FILE* out)
+{
+    EFI_PCI_PCIX_DEVICE_ERROR_DATA* section_cper =
+        (EFI_PCI_PCIX_DEVICE_ERROR_DATA*)calloc(1, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA));
+
+    //Validation bits.
+    section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"), 
+        5, PCI_DEV_ERROR_VALID_BITFIELD_NAMES);
+
+    //Error status.
+    ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
+
+    //Device ID information.
+    json_object* id_info = json_object_object_get(section, "idInfo");
+    section_cper->IdInfo.VendorId = json_object_get_uint64(json_object_object_get(id_info, "vendorID"));
+    section_cper->IdInfo.DeviceId = json_object_get_uint64(json_object_object_get(id_info, "deviceID"));
+    section_cper->IdInfo.ClassCode = json_object_get_uint64(json_object_object_get(id_info, "classCode"));
+    section_cper->IdInfo.FunctionNumber = json_object_get_uint64(json_object_object_get(id_info, "functionNumber"));
+    section_cper->IdInfo.DeviceNumber = json_object_get_uint64(json_object_object_get(id_info, "deviceNumber"));
+    section_cper->IdInfo.BusNumber = json_object_get_uint64(json_object_object_get(id_info, "busNumber"));
+    section_cper->IdInfo.SegmentNumber = json_object_get_uint64(json_object_object_get(id_info, "segmentNumber"));
+
+    //Amount of following data pairs.
+    section_cper->MemoryNumber = (UINT32)json_object_get_uint64(json_object_object_get(section, "memoryNumber"));
+    section_cper->IoNumber = (UINT32)json_object_get_uint64(json_object_object_get(section, "ioNumber"));
+
+    //Write header out to stream, free it.
+    fwrite(&section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+    free(section_cper);
+
+    //Begin writing register pairs.
+    json_object* register_pairs = json_object_object_get(section, "registerPairs");
+    int num_pairs = json_object_array_length(register_pairs);
+    for (int i=0; i<num_pairs; i++)
+    {
+        //Get the pair array item out.
+        json_object* register_pair = json_object_array_get_idx(register_pairs, i);
+
+        //Create the pair array.
+        UINT64 pair[2];
+        pair[0] = json_object_get_uint64(json_object_object_get(register_pair, "firstHalf"));
+        pair[1] = json_object_get_uint64(json_object_object_get(register_pair, "secondHalf"));
+
+        //Push to stream.
+        fwrite(pair, sizeof(UINT64), 2, out);
+        fflush(out);
+    }
 }
\ No newline at end of file
diff --git a/sections/cper-section-pci-dev.h b/sections/cper-section-pci-dev.h
index f79df74..65c18d8 100644
--- a/sections/cper-section-pci-dev.h
+++ b/sections/cper-section-pci-dev.h
@@ -30,5 +30,6 @@
 } EFI_PCI_PCIX_DEVICE_ERROR_DATA;
 
 json_object* cper_section_pci_dev_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_pci_dev_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file