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(§ion_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(§ion_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(§ion_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(§ion_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(§ion_cper->RecordIdGuid,
+ json_object_get_string(json_object_object_get(section, "recordIDGUID")));
+
+ //Write to stream, free resources.
+ fwrite(§ion_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"), §ion_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(§ion_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"), §ion_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(§ion_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