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