Add conversion for CXL protocol/component.
diff --git a/ir-parse.c b/ir-parse.c
index 90c925c..82904b5 100644
--- a/ir-parse.c
+++ b/ir-parse.c
@@ -89,18 +89,18 @@
             ir_section_dmar_vtd_to_cper(section, out);
         else if (guid_equal(&descriptors[i]->SectionType, &gEfiIommuDMArErrorSectionGuid))
             ir_section_dmar_iommu_to_cper(section, out);
-        // else if (guid_equal(&descriptors[i]->SectionType, &gEfiCcixPerLogErrorSectionGuid))
-        //     ir_section_ccix_per_to_cper(section, out);
-        // else if (guid_equal(&descriptors[i]->SectionType, &gEfiCxlProtocolErrorSectionGuid))
-        //     ir_section_cxl_protocol_to_cper(section, out);
-        // else if (guid_equal(&descriptors[i]->SectionType, &gEfiCxlGeneralMediaErrorSectionGuid)
-        //     || guid_equal(&descriptors[i]->SectionType, &gEfiCxlDramEventErrorSectionGuid)
-        //     || guid_equal(&descriptors[i]->SectionType, &gEfiCxlPhysicalSwitchErrorSectionGuid)
-        //     || guid_equal(&descriptors[i]->SectionType, &gEfiCxlVirtualSwitchErrorSectionGuid)
-        //     || guid_equal(&descriptors[i]->SectionType, &gEfiCxlMldPortErrorSectionGuid))
-        // {
-        //     ir_section_cxl_component_to_cper(section, out);
-        // }
+        else if (guid_equal(&descriptors[i]->SectionType, &gEfiCcixPerLogErrorSectionGuid))
+            ir_section_ccix_per_to_cper(section, out);
+        else if (guid_equal(&descriptors[i]->SectionType, &gEfiCxlProtocolErrorSectionGuid))
+            ir_section_cxl_protocol_to_cper(section, out);
+        else if (guid_equal(&descriptors[i]->SectionType, &gEfiCxlGeneralMediaErrorSectionGuid)
+            || guid_equal(&descriptors[i]->SectionType, &gEfiCxlDramEventErrorSectionGuid)
+            || guid_equal(&descriptors[i]->SectionType, &gEfiCxlPhysicalSwitchErrorSectionGuid)
+            || guid_equal(&descriptors[i]->SectionType, &gEfiCxlVirtualSwitchErrorSectionGuid)
+            || guid_equal(&descriptors[i]->SectionType, &gEfiCxlMldPortErrorSectionGuid))
+        {
+            ir_section_cxl_component_to_cper(section, out);
+        }
         else
         {
             //Unknown GUID, so read as a base64 unknown section.
diff --git a/sections/cper-section-cxl-component.c b/sections/cper-section-cxl-component.c
index cb950b7..681fdae 100644
--- a/sections/cper-section-cxl-component.c
+++ b/sections/cper-section-cxl-component.c
@@ -40,7 +40,7 @@
 
     //The specification for this is defined within the CXL Specification Section 8.2.9.1.
     unsigned char* cur_pos = (unsigned char*)(cxl_error + 1);
-    int remaining_len = section - (void*)cur_pos + cxl_error->Length;
+    int remaining_len = cxl_error->Length - sizeof(cxl_error);
     if (remaining_len > 0)
     {
         json_object* event_log = json_object_new_object();
@@ -51,4 +51,51 @@
     }
 
     return section_ir;
+}
+
+//Converts a single given CXL Component CPER-JSON section into CPER binary, outputting to the
+//given stream.
+void ir_section_cxl_component_to_cper(json_object* section, FILE* out)
+{
+    EFI_CXL_COMPONENT_EVENT_HEADER* section_cper =
+        (EFI_CXL_COMPONENT_EVENT_HEADER*)calloc(1, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER));
+
+    //Length of the structure.
+    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, CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES);
+
+    //Device ID information.
+    json_object* device_id = json_object_object_get(section, "deviceID");
+    section_cper->DeviceId.VendorId = json_object_get_uint64(json_object_object_get(device_id, "vendorID"));
+    section_cper->DeviceId.DeviceId = json_object_get_uint64(json_object_object_get(device_id, "deviceID"));
+    section_cper->DeviceId.FunctionNumber = 
+        json_object_get_uint64(json_object_object_get(device_id, "functionNumber"));
+    section_cper->DeviceId.DeviceNumber = 
+        json_object_get_uint64(json_object_object_get(device_id, "deviceNumber"));
+    section_cper->DeviceId.BusNumber = 
+        json_object_get_uint64(json_object_object_get(device_id, "busNumber"));
+    section_cper->DeviceId.SegmentNumber = 
+        json_object_get_uint64(json_object_object_get(device_id, "segmentNumber"));
+    section_cper->DeviceId.SlotNumber = 
+        json_object_get_uint64(json_object_object_get(device_id, "slotNumber"));
+
+    //Device serial number.
+    section_cper->DeviceSerial = json_object_get_uint64(json_object_object_get(section, "deviceSerial"));
+
+    //Write header out to stream.
+    fwrite(section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+
+    //CXL component event log, decoded from base64.
+    json_object* encoded = json_object_object_get(section, "cxlComponentEventLog");
+    int log_length = section_cper->Length - sizeof(section_cper);
+    char* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    fwrite(decoded, log_length, 1, out);
+    fflush(out);
+    free(decoded);
+
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-cxl-component.h b/sections/cper-section-cxl-component.h
index fa93950..e9cbfd5 100644
--- a/sections/cper-section-cxl-component.h
+++ b/sections/cper-section-cxl-component.h
@@ -30,5 +30,6 @@
 } EFI_CXL_COMPONENT_EVENT_HEADER;
 
 json_object* cper_section_cxl_component_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_cxl_component_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file
diff --git a/sections/cper-section-cxl-protocol.c b/sections/cper-section-cxl-protocol.c
index d7fbf0a..c8c2c09 100644
--- a/sections/cper-section-cxl-protocol.c
+++ b/sections/cper-section-cxl-protocol.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"
@@ -99,4 +100,85 @@
     free(encoded);
     
     return section_ir;
+}
+
+//Converts a single CXL protocol CPER-JSON section into CPER binary, outputting to the given stream.
+void ir_section_cxl_protocol_to_cper(json_object* section, FILE* out)
+{
+    EFI_CXL_PROTOCOL_ERROR_DATA* section_cper =
+        (EFI_CXL_PROTOCOL_ERROR_DATA*)calloc(1, sizeof(EFI_CXL_PROTOCOL_ERROR_DATA));
+
+    //Validation bits.
+    section_cper->ValidBits = ir_to_bitfield(json_object_object_get(section, "validationBits"), 
+        7, CXL_PROTOCOL_ERROR_VALID_BITFIELD_NAMES);
+
+    //Detecting agent type.
+    section_cper->CxlAgentType = readable_pair_to_integer(json_object_object_get(section, "agentType"));
+
+    //Based on the agent type, set the address.
+    json_object* address = json_object_object_get(section, "cxlAgentAddress");
+    if (section_cper->CxlAgentType == CXL_PROTOCOL_ERROR_DEVICE_AGENT)
+    {
+        //Address is split by function, device, bus & segment.
+        UINT64 function = json_object_get_uint64(json_object_object_get(address, "functionNumber"));
+        UINT64 device = json_object_get_uint64(json_object_object_get(address, "deviceNumber"));
+        UINT64 bus = json_object_get_uint64(json_object_object_get(address, "busNumber"));
+        UINT64 segment = json_object_get_uint64(json_object_object_get(address, "segmentNumber"));
+        section_cper->CxlAgentAddress.DeviceAddress.FunctionNumber = function;
+        section_cper->CxlAgentAddress.DeviceAddress.DeviceNumber = device;
+        section_cper->CxlAgentAddress.DeviceAddress.BusNumber = bus;
+        section_cper->CxlAgentAddress.DeviceAddress.SegmentNumber = segment;
+    }
+    else if (section_cper->CxlAgentType == CXL_PROTOCOL_ERROR_HOST_DOWNSTREAM_PORT_AGENT)
+    {
+        //Plain RCRB base address.
+        section_cper->CxlAgentAddress.PortRcrbBaseAddress = 
+            json_object_get_uint64(json_object_object_get(address, "value"));
+    }
+
+    //Device ID information.
+    json_object* device_id = json_object_object_get(section, "deviceID");
+    section_cper->DeviceId.VendorId = json_object_get_uint64(json_object_object_get(device_id, "vendorID"));
+    section_cper->DeviceId.DeviceId = json_object_get_uint64(json_object_object_get(device_id, "deviceID"));
+    section_cper->DeviceId.SubsystemVendorId = 
+        json_object_get_uint64(json_object_object_get(device_id, "subsystemVendorID"));
+    section_cper->DeviceId.SubsystemDeviceId = 
+        json_object_get_uint64(json_object_object_get(device_id, "subsystemDeviceID"));
+    section_cper->DeviceId.ClassCode = json_object_get_uint64(json_object_object_get(device_id, "classCode"));
+    section_cper->DeviceId.SlotNumber = json_object_get_uint64(json_object_object_get(device_id, "slotNumber"));
+
+    //If CXL 1.1 device, the serial number & PCI capability structure.
+    if (section_cper->CxlAgentType == CXL_PROTOCOL_ERROR_DEVICE_AGENT)
+    {
+        section_cper->DeviceSerial = json_object_get_uint64(json_object_object_get(section, "deviceSerial"));
+
+        json_object* encoded = json_object_object_get(section, "capabilityStructure");
+        char* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+        memcpy(section_cper->CapabilityStructure.PcieCap, decoded, 60);
+        free(decoded);
+    }
+
+    //DVSEC length & error log length.
+    section_cper->CxlDvsecLength = (UINT16)json_object_get_int(json_object_object_get(section, "dvsecLength"));
+    section_cper->CxlErrorLogLength = (UINT16)json_object_get_int(json_object_object_get(section, "errorLogLength"));
+
+    //Write header to stream.
+    fwrite(section_cper, sizeof(section_cper), 1, out);
+    fflush(out);
+
+    //DVSEC out to stream.
+    json_object* encoded = json_object_object_get(section, "cxlDVSEC");
+    char* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    fwrite(decoded, section_cper->CxlDvsecLength, 1, out);
+    fflush(out);
+    free(decoded);
+
+    //Error log out to stream.
+    encoded = json_object_object_get(section, "cxlErrorLog");
+    decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+    fwrite(decoded, section_cper->CxlErrorLogLength, 1, out);
+    fflush(out);
+    free(decoded);
+
+    free(section_cper);
 }
\ No newline at end of file
diff --git a/sections/cper-section-cxl-protocol.h b/sections/cper-section-cxl-protocol.h
index c3ac312..33b45d9 100644
--- a/sections/cper-section-cxl-protocol.h
+++ b/sections/cper-section-cxl-protocol.h
@@ -51,5 +51,6 @@
 } EFI_CXL_PROTOCOL_ERROR_DATA;
 
 json_object* cper_section_cxl_protocol_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+void ir_section_cxl_protocol_to_cper(json_object* section, FILE* out);
 
 #endif
\ No newline at end of file