Add CXL component GUIDs, b64 dumps for unknown.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 134d7cf..d1a284a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,14 @@
   GIT_REPOSITORY https://github.com/json-c/json-c.git
   GIT_TAG        d28ac67dde77566f53a97f22b4ea7cb36afe6582 # 4/6/2022
 )
-FetchContent_MakeAvailable(json-c)
+
+# Fetch b64-c from git repository.
+FetchContent_Declare(
+  b64-c
+  GIT_REPOSITORY https://github.com/jwerle/b64.c.git
+  GIT_TAG        c33188cd541f19b072ee4988d8224ea6c964bed1 # 9/2/2021
+)
+FetchContent_MakeAvailable(json-c b64-c)
 
 # Add library and test executable.
 file(GLOB SectionSources sections/*.c)
@@ -23,5 +30,5 @@
 add_executable(CPERParseTest cper-test.c)
 
 # Link library.
-target_link_libraries(CPERParseLibrary json-c)
+target_link_libraries(CPERParseLibrary json-c b64c)
 target_link_libraries(CPERParseTest CPERParseLibrary)
\ No newline at end of file
diff --git a/cper-parse.c b/cper-parse.c
index f80feb7..2bfb3cf 100644
--- a/cper-parse.c
+++ b/cper-parse.c
@@ -7,6 +7,7 @@
 
 #include <stdio.h>
 #include "json.h"
+#include "b64.h"
 #include "edk/Cper.h"
 #include "cper-parse.h"
 #include "cper-utils.h"
@@ -24,6 +25,7 @@
 #include "sections/cper-section-ccix-per.h"
 #include "sections/cper-section-cxl-protocol.h"
 #include "sections/cper-section-ipf.h"
+#include "sections/cper-section-cxl-component.h"
 
 //Private pre-definitions.
 json_object* cper_header_to_ir(EFI_COMMON_ERROR_RECORD_HEADER* header);
@@ -268,6 +270,16 @@
         section_type_readable = "CCIX PER Log Error";
     else if (guid_equal(&section_descriptor->SectionType, &gEfiCxlProtocolErrorSectionGuid))
         section_type_readable = "CXL Protocol Error";
+    else if (guid_equal(&section_descriptor->SectionType, &gEfiCxlGeneralMediaErrorSectionGuid))
+        section_type_readable = "CXL General Media Component Error";
+    else if (guid_equal(&section_descriptor->SectionType, &gEfiCxlDramEventErrorSectionGuid))
+        section_type_readable = "CXL DRAM Component Error";
+    else if (guid_equal(&section_descriptor->SectionType, &gEfiCxlPhysicalSwitchErrorSectionGuid))
+        section_type_readable = "CXL Physical Switch Component Error";
+    else if (guid_equal(&section_descriptor->SectionType, &gEfiCxlVirtualSwitchErrorSectionGuid))
+        section_type_readable = "CXL Virtual Switch Component Error";
+    else if (guid_equal(&section_descriptor->SectionType, &gEfiCxlMldPortErrorSectionGuid))
+        section_type_readable = "CXL MLD Port Component Error";
 
     //todo: How do you determine if this is a CXL component event?
     //perhaps refer to CXL Specification, Rev 2.0
@@ -346,10 +358,22 @@
         result = cper_section_ccix_per_to_ir(section, descriptor);
     else if (guid_equal(&descriptor->SectionType, &gEfiCxlProtocolErrorSectionGuid))
         result = cper_section_cxl_protocol_to_ir(section, descriptor);
+    else if (guid_equal(&descriptor->SectionType, &gEfiCxlGeneralMediaErrorSectionGuid)
+          || guid_equal(&descriptor->SectionType, &gEfiCxlDramEventErrorSectionGuid)
+          || guid_equal(&descriptor->SectionType, &gEfiCxlPhysicalSwitchErrorSectionGuid)
+          || guid_equal(&descriptor->SectionType, &gEfiCxlVirtualSwitchErrorSectionGuid)
+          || guid_equal(&descriptor->SectionType, &gEfiCxlMldPortErrorSectionGuid))
+    {
+        result = cper_section_cxl_component_to_ir(section, descriptor);
+    }
     else
     {
         //Failed read, unknown GUID.
-        //todo: dump the binary data out to b64.
+        //Output the data as formatted base64.
+        result = json_object_new_object();
+        char* encoded = b64_encode((unsigned char*)section, descriptor->SectionLength);
+        json_object_object_add(result, "data", json_object_new_string(encoded));
+        free(encoded);
     }
 
     //Free section memory, return result.
diff --git a/edk/Cper.c b/edk/Cper.c
index 2d2614d..0ccf08b 100644
--- a/edk/Cper.c
+++ b/edk/Cper.c
@@ -36,6 +36,12 @@
 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 }};
 EFI_GUID gEfiCxlProtocolErrorSectionGuid    = { 0x80B9EFB4, 0x52B5, 0x4DE3, { 0xA7, 0x77, 0x68, 0x78, 0x4B, 0x77, 0x10, 0x48 }};
+EFI_GUID gEfiCxlGeneralMediaErrorSectionGuid = { 0xfbcd0a77, 0xc260, 0x417f, { 0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6 }};
+EFI_GUID gEfiCxlDramEventErrorSectionGuid = { 0x601dcbb3, 0x9c06, 0x4eab, { 0xb8, 0xaf, 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24 }};
+EFI_GUID gEfiCxlMemoryModuleErrorSectionGuid = { 0xfe927475, 0xdd59, 0x4339, { 0xa5, 0x86, 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74 }};
+EFI_GUID gEfiCxlPhysicalSwitchErrorSectionGuid = { 0x77cf9271, 0x9c02, 0x470b, { 0x9f, 0xe4, 0xbc, 0x7b, 0x75, 0xf2, 0xda, 0x97 }};
+EFI_GUID gEfiCxlVirtualSwitchErrorSectionGuid = { 0x40d26425, 0x3396, 0x4c4d, { 0xa5, 0xda, 0x3d, 0x47, 0x26, 0x3a, 0xf4, 0x25 }};
+EFI_GUID gEfiCxlMldPortErrorSectionGuid = { 0x8dc44363, 0x0c96, 0x4710, { 0xb7, 0xbf, 0x04, 0xbb, 0x99, 0x53, 0x4c, 0x3f }};
 
 //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 5a6d2b2..0fcc967 100644
--- a/edk/Cper.h
+++ b/edk/Cper.h
@@ -1266,6 +1266,12 @@
 extern EFI_GUID   gEfiIommuDMArErrorSectionGuid;

 extern EFI_GUID   gEfiCcixPerLogErrorSectionGuid;

 extern EFI_GUID   gEfiCxlProtocolErrorSectionGuid;

+extern EFI_GUID   gEfiCxlGeneralMediaErrorSectionGuid;

+extern EFI_GUID   gEfiCxlDramEventErrorSectionGuid;

+extern EFI_GUID   gEfiCxlMemoryModuleErrorSectionGuid;

+extern EFI_GUID   gEfiCxlPhysicalSwitchErrorSectionGuid;

+extern EFI_GUID   gEfiCxlVirtualSwitchErrorSectionGuid;

+extern EFI_GUID   gEfiCxlMldPortErrorSectionGuid;

 #pragma pack()

 

 #if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)

diff --git a/sections/cper-section-arm.c b/sections/cper-section-arm.c
index b8def2b..58e97bf 100644
--- a/sections/cper-section-arm.c
+++ b/sections/cper-section-arm.c
@@ -7,6 +7,7 @@
 
 #include <stdio.h>
 #include "json.h"
+#include "b64.h"
 #include "../edk/Cper.h"
 #include "../cper-utils.h"
 #include "cper-section-arm.h"
@@ -72,7 +73,12 @@
     //Is there any vendor-specific information following?
     if (cur_pos < section + record->SectionLength)
     {
-        //todo: b64 and tag on vendor-specific binary info.
+        json_object* vendor_specific = json_object_new_object();
+        char* encoded = b64_encode((unsigned char*)cur_pos, section + record->SectionLength - cur_pos);
+        json_object_object_add(vendor_specific, "data", json_object_new_string(encoded));
+        free(encoded);
+
+        json_object_object_add(section_ir, "vendorSpecificInfo", vendor_specific);
     }
 
     return section_ir;
@@ -291,9 +297,11 @@
             register_array = cper_arm_misc_register_array_to_ir((EFI_ARM_MISC_CONTEXT_REGISTER*)cur_pos);
             break;
         default:
-            //Unknown register array type.
-            //todo: Format raw binary data and add instead of blank.
+            //Unknown register array type, add as base64 data instead.
             register_array = json_object_new_object();
+            char* encoded = b64_encode((unsigned char*)cur_pos, header->RegisterArraySize);
+            json_object_object_add(register_array, "data", json_object_new_string(encoded));
+            free(encoded);
             break;
     }
 
diff --git a/sections/cper-section-cxl-component.c b/sections/cper-section-cxl-component.c
new file mode 100644
index 0000000..ab3b34f
--- /dev/null
+++ b/sections/cper-section-cxl-component.c
@@ -0,0 +1,23 @@
+/**
+ * Describes functions for converting CXL component error 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-cxl-component.h"
+
+//Converts a single CXL component error CPER section into JSON IR.
+json_object* cper_section_cxl_component_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
+{
+    //The length of the structure (bytes).
+    EFI_CXL_COMPONENT_EVENT_HEADER* cxl_error = (EFI_CXL_COMPONENT_EVENT_HEADER*)section;
+    json_object* section_ir = json_object_new_object();
+    
+    //todo: Figure out structure for CXL Component Event log (UEFI spec is a bit vague)
+
+    return section_ir;
+}
\ No newline at end of file
diff --git a/sections/cper-section-cxl-component.h b/sections/cper-section-cxl-component.h
new file mode 100644
index 0000000..17dcedf
--- /dev/null
+++ b/sections/cper-section-cxl-component.h
@@ -0,0 +1,35 @@
+#ifndef CPER_SECTION_CXL_COMPONENT_H
+#define CPER_SECTION_CXL_COMPONENT_H
+
+#include "json.h"
+#include "../edk/Cper.h"
+
+///
+/// CXL Generic Component Error Section
+///
+typedef struct {
+  UINT64 VendorId : 16;
+  UINT64 DeviceId : 16;
+  UINT64 FunctionNumber : 8;
+  UINT64 DeviceNumber : 8;
+  UINT64 BusNumber : 8;
+  UINT64 SegmentNumber : 16;
+  UINT64 Resv1 : 3;
+  UINT64 SlotNumber : 13;
+  UINT64 Resv2 : 8;
+} EFI_CXL_DEVICE_ID_INFO;
+
+typedef struct {
+    UINT32 Length;
+    UINT64 ValidBits;
+    EFI_CXL_DEVICE_ID_INFO DeviceId;
+    UINT64 DeviceSerial;
+} EFI_CXL_COMPONENT_EVENT_HEADER;
+
+typedef struct {
+    //todo: What is the structure for this? The UEFI spec is a bit vague.
+} EFI_CXL_COMPONENT_COMMON_RECORD_HEAD;
+
+json_object* cper_section_cxl_component_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
+
+#endif
\ No newline at end of file
diff --git a/sections/cper-section-dmar-iommu.c b/sections/cper-section-dmar-iommu.c
index 14d66a3..1f479aa 100644
--- a/sections/cper-section-dmar-iommu.c
+++ b/sections/cper-section-dmar-iommu.c
@@ -6,6 +6,7 @@
  **/
 #include <stdio.h>
 #include "json.h"
+#include "b64.h"
 #include "../edk/Cper.h"
 #include "../cper-utils.h"
 #include "cper-section-dmar-iommu.h"
@@ -26,8 +27,10 @@
     //IOMMU event log entry.
     //todo: implement as specified in the IOMMU specification
 
-    //Device table entry.
-    //todo: dump as b64
+    //Device table entry (as base64).
+    char* encoded = b64_encode((unsigned char*)iommu_error->DeviceTableEntry, 32);
+    json_object_object_add(section_ir, "deviceTableEntry", json_object_new_string(encoded));
+    free(encoded);
 
     //Page table entries.
     json_object_object_add(section_ir, "pageTableEntry_Level6", json_object_new_uint64(iommu_error->PteL6));
diff --git a/sections/cper-section-ia32x64.c b/sections/cper-section-ia32x64.c
index bfe7d6e..5dbad18 100644
--- a/sections/cper-section-ia32x64.c
+++ b/sections/cper-section-ia32x64.c
@@ -7,6 +7,7 @@
 
 #include <stdio.h>
 #include "json.h"
+#include "b64.h"
 #include "../edk/Cper.h"
 #include "../cper-utils.h"
 #include "cper-section-ia32x64.h"
@@ -248,9 +249,14 @@
     }
     else 
     {
-        //No parseable data, just shift the head to the next item.
-        //todo: Dump the unparseable data into JSON IR anyway
+        //No parseable data, just dump as base64 and shift the head to the next item.
         *cur_pos = (void*)(context_info + 1);
+
+        char* encoded = b64_encode((unsigned char*)cur_pos, context_info->ArraySize);
+        register_array = json_object_new_object();
+        json_object_object_add(register_array, "data", json_object_new_string(encoded));
+        free(encoded);
+
         *cur_pos = (void*)(((char*)*cur_pos) + context_info->ArraySize);
     }
     json_object_object_add(context_info_ir, "registerArray", register_array);
diff --git a/sections/cper-section-pci-dev.h b/sections/cper-section-pci-dev.h
index 43d36ea..02c6b4f 100644
--- a/sections/cper-section-pci-dev.h
+++ b/sections/cper-section-pci-dev.h
@@ -11,14 +11,14 @@
 /// PCI/PCI-X Device Error Section
 ///
 typedef struct {
-  UINT64 VendorId : 2;
-  UINT64 DeviceId : 2;
-  UINT64 ClassCode : 3;
-  UINT64 FunctionNumber : 1;
-  UINT64 DeviceNumber : 1;
-  UINT64 BusNumber : 1;
-  UINT64 SegmentNumber : 1;
-  UINT64 Reserved : 5;
+  UINT64 VendorId : 16;
+  UINT64 DeviceId : 16;
+  UINT64 ClassCode : 24;
+  UINT64 FunctionNumber : 8;
+  UINT64 DeviceNumber : 8;
+  UINT64 BusNumber : 8;
+  UINT64 SegmentNumber : 8;
+  UINT64 Reserved : 40;
 } EFI_PCI_PCIX_DEVICE_ID_INFO;
 
 typedef struct {