Add generation for remaining, fix invalid fseek().
diff --git a/cper-parse.c b/cper-parse.c
index 0bc801e..1fd5f74 100644
--- a/cper-parse.c
+++ b/cper-parse.c
@@ -290,6 +290,9 @@
//Converts the section described by a single given section descriptor.
json_object* cper_section_to_ir(FILE* handle, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
{
+ //Save our current position in the stream.
+ long position = ftell(handle);
+
//Read section as described by the section descriptor.
fseek(handle, descriptor->SectionOffset, SEEK_SET);
void* section = malloc(descriptor->SectionLength);
@@ -302,6 +305,9 @@
return NULL;
}
+ //Seek back to our original position.
+ fseek(handle, position, SEEK_SET);
+
//Parse section to IR based on GUID.
json_object* result = NULL;
if (guid_equal(&descriptor->SectionType, &gEfiProcessorGenericErrorSectionGuid))
diff --git a/generator/cper-generate.c b/generator/cper-generate.c
index 90ad460..23fad1d 100644
--- a/generator/cper-generate.c
+++ b/generator/cper-generate.c
@@ -196,32 +196,32 @@
// length = generate_section_ipf(location);
else if (strcmp(type, "arm") == 0)
length = generate_section_arm(location);
- // else if (strcmp(type, "memory") == 0)
- // length = generate_section_memory(location);
- // else if (strcmp(type, "memory2") == 0)
- // length = generate_section_memory2(location);
- // else if (strcmp(type, "pcie") == 0)
- // length = generate_section_pcie(location);
- // else if (strcmp(type, "firmware") == 0)
- // length = generate_section_firmware(location);
- // else if (strcmp(type, "pcibus") == 0)
- // length = generate_section_pci_bus(location);
- // else if (strcmp(type, "pcidev") == 0)
- // length = generate_section_pci_dev(location);
- // else if (strcmp(type, "dmargeneric") == 0)
- // length = generate_section_dmar_generic(location);
- // else if (strcmp(type, "dmarvtd") == 0)
- // length = generate_section_dmar_vtd(location);
- // else if (strcmp(type, "dmariommu") == 0)
- // length = generate_section_dmar_iommu(location);
- // else if (strcmp(type, "ccixper") == 0)
- // length = generate_section_ccix_per(location);
- // else if (strcmp(type, "cxlprotocol") == 0)
- // length = generate_section_cxl_protocol(location);
- // else if (strcmp(type, "cxlcomponent") == 0)
- // length = generate_section_cxl_component(location);
- // else if (strcmp(type, "unknown") == 0)
- // length = generate_section_unknown(location);
+ else if (strcmp(type, "memory") == 0)
+ length = generate_section_memory(location);
+ else if (strcmp(type, "memory2") == 0)
+ length = generate_section_memory2(location);
+ else if (strcmp(type, "pcie") == 0)
+ length = generate_section_pcie(location);
+ else if (strcmp(type, "firmware") == 0)
+ length = generate_section_firmware(location);
+ else if (strcmp(type, "pcibus") == 0)
+ length = generate_section_pci_bus(location);
+ else if (strcmp(type, "pcidev") == 0)
+ length = generate_section_pci_dev(location);
+ else if (strcmp(type, "dmargeneric") == 0)
+ length = generate_section_dmar_generic(location);
+ else if (strcmp(type, "dmarvtd") == 0)
+ length = generate_section_dmar_vtd(location);
+ else if (strcmp(type, "dmariommu") == 0)
+ length = generate_section_dmar_iommu(location);
+ else if (strcmp(type, "ccixper") == 0)
+ length = generate_section_ccix_per(location);
+ else if (strcmp(type, "cxlprotocol") == 0)
+ length = generate_section_cxl_protocol(location);
+ else if (strcmp(type, "cxlcomponent") == 0)
+ length = generate_section_cxl_component(location);
+ else if (strcmp(type, "unknown") == 0)
+ length = generate_random_section(location, rand() % 256);
else
{
//Undefined section, show error.
diff --git a/generator/gen-utils.c b/generator/gen-utils.c
index a0f6e3c..1ab318f 100644
--- a/generator/gen-utils.c
+++ b/generator/gen-utils.c
@@ -25,6 +25,19 @@
return bytes;
}
+//Creates a valid common CPER error section, given the start of the error section.
+//Clears reserved bits.
+void create_valid_error_section(UINT8* start)
+{
+ //Fix reserved bits.
+ UINT64* error_section = (UINT64*)start;
+ *error_section &= ~0xFF; //Reserved bits 0-7.
+ *error_section &= 0x7FFFFF; //Reserved bits 23-63
+
+ //Ensure error type has a valid value.
+ *(start + 1) = CPER_ERROR_TYPES_KEYS[rand() % (sizeof(CPER_ERROR_TYPES_KEYS) / sizeof(int))];
+}
+
//Initializes the random seed for rand() using the current time.
void init_random()
{
diff --git a/generator/gen-utils.h b/generator/gen-utils.h
index 4a966db..5dc9a56 100644
--- a/generator/gen-utils.h
+++ b/generator/gen-utils.h
@@ -4,8 +4,11 @@
#include <stdlib.h>
#include "../edk/BaseTypes.h"
+#define CPER_ERROR_TYPES_KEYS (int []){1, 16, 4, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}
+
size_t generate_random_section(void** location, size_t size);
UINT8* generate_random_bytes(size_t size);
void init_random();
+void create_valid_error_section(UINT8* start);
#endif
\ No newline at end of file
diff --git a/generator/sections/gen-section-ccix-per.c b/generator/sections/gen-section-ccix-per.c
new file mode 100644
index 0000000..a61983b
--- /dev/null
+++ b/generator/sections/gen-section-ccix-per.c
@@ -0,0 +1,34 @@
+/**
+ * Functions for generating psuedo-random CCIX PER error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random CCIX PER error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_ccix_per(void** location)
+{
+ //Create a random length for the CCIX PER log.
+ //The log attached here does not necessarily conform to the CCIX specification, and is simply random.
+ int log_len = (rand() % 5 + 1) * 32;
+
+ //Create random bytes.
+ int size = 16 + log_len;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)(bytes + 4);
+ *validation &= 0b111; //Validation bits 3-63.
+ *(bytes + 13) &= 0b11111; //CCIX port ID bits 5-7.
+ UINT16* reserved = (UINT16*)(bytes + 14);
+ *reserved = 0; //Reserved bytes 14-15.
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-cxl-component.c b/generator/sections/gen-section-cxl-component.c
new file mode 100644
index 0000000..d08dc90
--- /dev/null
+++ b/generator/sections/gen-section-cxl-component.c
@@ -0,0 +1,38 @@
+/**
+ * Functions for generating psuedo-random CXL component error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random CXL component error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_cxl_component(void** location)
+{
+ //Create a random length for the CXL component event log.
+ //The logs attached here do not necessarily conform to the specification, and are simply random.
+ int log_len = rand() % 64;
+
+ //Create random bytes.
+ int size = 32 + log_len;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)(bytes + 4);
+ *validation &= 0b111;
+ UINT16* slot_number = (UINT16*)(bytes + 21);
+ *slot_number &= ~0b111; //Device ID slot number bits 0-2.
+ *(bytes + 23) = 0; //Device ID byte 11.
+
+ //Set expected values.
+ UINT32* length = (UINT32*)bytes;
+ *length = size;
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-cxl-protocol.c b/generator/sections/gen-section-cxl-protocol.c
new file mode 100644
index 0000000..64326f9
--- /dev/null
+++ b/generator/sections/gen-section-cxl-protocol.c
@@ -0,0 +1,57 @@
+/**
+ * Functions for generating psuedo-random CXL protocol error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random CXL protocol error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_cxl_protocol(void** location)
+{
+ //Create a random length for the CXL DVSEC and CXL error log.
+ //The logs attached here do not necessarily conform to the specification, and are simply random.
+ int dvsec_len = rand() % 64;
+ int error_log_len = rand() % 64;
+
+ //Create random bytes.
+ int size = 116 + dvsec_len + error_log_len;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set CXL agent type.
+ int cxl_agent_type = rand() % 2;
+ *(bytes + 8) = cxl_agent_type;
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)bytes;
+ *validation &= 0b111111; //Validation bits 6-63.
+ for (int i=0; i<7; i++)
+ *(bytes + 9 + i) = 0; //Reserved bytes 9-15.
+
+ //We only reserve bytes if it's a CXL 1.1 device, and not a host downstream port.
+ if (cxl_agent_type == 0)
+ {
+ for (int i=0; i<3; i++)
+ *(bytes + 20 + i) = 0; //CXL agent address bytes 5-7.
+ }
+
+ *(bytes + 34) &= ~0b111; //Device ID byte 10 bits 0-2.
+ UINT32* reserved = (UINT32*)(bytes + 36);
+ *reserved = 0; //Device ID bytes 12-15.
+ reserved = (UINT32*)(bytes + 112);
+ *reserved = 0; //Reserved bytes 112-115.
+
+ //Set expected values.
+ UINT16* dvsec_length_field = (UINT16*)(bytes + 108);
+ UINT16* error_log_len_field = (UINT16*)(bytes + 110);
+ *dvsec_length_field = dvsec_len;
+ *error_log_len_field = error_log_len;
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-dmar.c b/generator/sections/gen-section-dmar.c
new file mode 100644
index 0000000..d0bbb5e
--- /dev/null
+++ b/generator/sections/gen-section-dmar.c
@@ -0,0 +1,72 @@
+/**
+ * Functions for generating psuedo-random CPER DMAr error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random generic DMAr error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_dmar_generic(void** location)
+{
+ //Create random bytes.
+ int size = 32;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* reserved = (UINT64*)(bytes + 16);
+ *reserved = 0;
+ *(reserved + 1) = 0;
+
+ //Set expected values.
+ *(bytes + 4) = rand() % 0xC; //Fault reason.
+ *(bytes + 5) = rand() % 2; //Access type.
+ *(bytes + 6) = rand() % 2; //Address type.
+ *(bytes + 7) = rand() % 2 + 1; //Architecture type.
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
+
+//Generates a single psuedo-random VT-d DMAr error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_dmar_vtd(void** location)
+{
+ //Create random bytes.
+ int size = 144;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ for (int i=0; i<12; i++)
+ *(bytes + 36 + i) = 0; //Reserved bytes 36-47.
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
+
+//Generates a single psuedo-random IOMMU DMAr error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_dmar_iommu(void** location)
+{
+ //Create random bytes.
+ int size = 144;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ for (int i=0; i<7; i++)
+ *(bytes + 1 + i) + 0; //Reserved bytes 1 to 7.
+ UINT64* reserved = (UINT64*)(bytes + 24);
+ *reserved = 0; //Reserved bytes 24-31.
+ for (int i=0; i<16; i++)
+ *(bytes + 48 + i) = 0; //Reserved bytes 48-63.
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-firmware.c b/generator/sections/gen-section-firmware.c
new file mode 100644
index 0000000..09c47ff
--- /dev/null
+++ b/generator/sections/gen-section-firmware.c
@@ -0,0 +1,33 @@
+/**
+ * Functions for generating psuedo-random CPER firmware error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random firmware error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_firmware(void** location)
+{
+ //Create random bytes.
+ int size = 32;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ for (int i=0; i<7; i++)
+ *(bytes + 2 + i) = 0; //Reserved bytes 2-9.
+
+ //Set expected values.
+ *(bytes + 1) = 2; //Revision, referenced version of spec is 2.
+ UINT64* record_id = (UINT64*)(bytes + 8);
+ *record_id = 0; //Record ID, should be forced to NULL.
+ *bytes = rand() % 3; //Record type.
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-memory.c b/generator/sections/gen-section-memory.c
new file mode 100644
index 0000000..dfa713f
--- /dev/null
+++ b/generator/sections/gen-section-memory.c
@@ -0,0 +1,59 @@
+/**
+ * Functions for generating psuedo-random CPER platform memory error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random platform memory error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_memory(void** location)
+{
+ //Create random bytes.
+ int size = 80;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)bytes;
+ *validation &= 0x2FFFFF; //Validation 22-63
+ *(bytes + 73) &= ~0b11100; //Extended bits 2-4
+
+ //Fix values that could be above range.
+ *(bytes + 72) = rand() % 16; //Memory error type
+
+ //Fix error status.
+ create_valid_error_section(bytes + 8);
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
+
+//Generates a single psuedo-random memory 2 error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_memory2(void** location)
+{
+ //Create random bytes.
+ int size = 96;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)bytes;
+ *validation &= 0x2FFFFF; //Validation 22-63
+ *(bytes + 63) = 0; //Reserved byte 63
+
+ //Fix values that could be above range.
+ *(bytes + 61) = rand() % 16; //Memory error type
+ *(bytes + 62) = rand() % 2; //Status
+
+ //Fix error status.
+ create_valid_error_section(bytes + 8);
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-pci-bus.c b/generator/sections/gen-section-pci-bus.c
new file mode 100644
index 0000000..9afd9ad
--- /dev/null
+++ b/generator/sections/gen-section-pci-bus.c
@@ -0,0 +1,38 @@
+/**
+ * Functions for generating psuedo-random CPER PCI/PCI-X bus error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random PCI/PCI-X bus error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_pci_bus(void** location)
+{
+ //Create random bytes.
+ int size = 208;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)bytes;
+ *validation &= 0x1FF; //Validation 9-63
+ UINT32* reserved = (UINT32*)(bytes + 20);
+ *reserved = 0;
+ UINT64* bus_command = (UINT64*)(bytes + 40);
+ *bus_command &= 0x100000000000000; //Bus command bytes bar bit 56.
+
+ //Fix values that could be above range.
+ UINT16* error_type = (UINT16*)(bytes + 16);
+ *error_type = rand() % 8;
+
+ //Fix error status.
+ create_valid_error_section(bytes + 8);
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-pci-dev.c b/generator/sections/gen-section-pci-dev.c
new file mode 100644
index 0000000..1882d6c
--- /dev/null
+++ b/generator/sections/gen-section-pci-dev.c
@@ -0,0 +1,37 @@
+/**
+ * Functions for generating psuedo-random CPER PCI component error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+//Generates a single psuedo-random PCI component error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_pci_dev(void** location)
+{
+ //Generate how many register pairs will be attached to this section.
+ UINT32 num_memory_pairs = rand() % 4;
+ UINT32 num_io_pairs = rand() % 4;
+ UINT32 num_registers = num_memory_pairs + num_io_pairs;
+
+ //Create random bytes.
+ int size = 40 + (num_registers * 16);
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)bytes;
+ *validation &= 0b11111; //Validation 5-63
+ for (int i=0; i<5; i++)
+ *(bytes + 27 + i) = 0; //Bytes 11-15 of ID info.
+
+ //Fix error status.
+ create_valid_error_section(bytes + 8);
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-section-pcie.c b/generator/sections/gen-section-pcie.c
new file mode 100644
index 0000000..5f67c09
--- /dev/null
+++ b/generator/sections/gen-section-pcie.c
@@ -0,0 +1,38 @@
+/**
+ * Functions for generating psuedo-random CPER PCIe error sections.
+ *
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include <stdlib.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-sections.h"
+
+#define PCIE_PORT_TYPES (int []){0, 1, 4, 5, 6, 7, 8, 9, 10}
+
+//Generates a single psuedo-random PCIe error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_pcie(void** location)
+{
+ //Create random bytes.
+ int size = 208;
+ UINT8* bytes = generate_random_bytes(size);
+
+ //Set reserved areas to zero.
+ UINT64* validation = (UINT64*)bytes;
+ *validation &= 0xFF; //Validation 8-63
+ UINT32* version = (UINT32*)(bytes + 12);
+ *version &= 0xFFFF; //Version bytes 2-3
+ UINT32* reserved = (UINT32*)(bytes + 20);
+ *reserved = 0; //Reserved bytes 20-24
+ *(bytes + 39) = 0; //Device ID byte 15
+
+ //Fix values that could be above range.
+ UINT32* port_type = (UINT32*)(bytes + 8);
+ *port_type = PCIE_PORT_TYPES[rand() % (sizeof(PCIE_PORT_TYPES) / sizeof(int))];
+
+ //Set return values, exit.
+ *location = bytes;
+ return size;
+}
\ No newline at end of file
diff --git a/generator/sections/gen-sections.h b/generator/sections/gen-sections.h
index 33ecd39..50f9350 100644
--- a/generator/sections/gen-sections.h
+++ b/generator/sections/gen-sections.h
@@ -6,5 +6,17 @@
size_t generate_section_generic(void** location);
size_t generate_section_ia32x64(void** location);
size_t generate_section_arm(void** location);
+size_t generate_section_memory(void** location);
+size_t generate_section_memory2(void** location);
+size_t generate_section_pcie(void** location);
+size_t generate_section_pci_bus(void** location);
+size_t generate_section_pci_dev(void** location);
+size_t generate_section_firmware(void** location);
+size_t generate_section_dmar_generic(void** location);
+size_t generate_section_dmar_vtd(void** location);
+size_t generate_section_dmar_iommu(void** location);
+size_t generate_section_ccix_per(void** location);
+size_t generate_section_cxl_protocol(void** location);
+size_t generate_section_cxl_component(void** location);
#endif
\ No newline at end of file
diff --git a/sections/cper-section-pci-bus.c b/sections/cper-section-pci-bus.c
index db034d1..d12a6fe 100644
--- a/sections/cper-section-pci-bus.c
+++ b/sections/cper-section-pci-bus.c
@@ -38,9 +38,10 @@
json_object_object_add(section_ir, "busID", bus_id);
//Miscellaneous numeric fields.
+ UINT8 command_type = (bus_error->BusCommand >> 56) & 0b1; //Byte 7, bit 0.
json_object_object_add(section_ir, "busAddress", json_object_new_uint64(bus_error->BusAddress));
json_object_object_add(section_ir, "busData", json_object_new_uint64(bus_error->BusData));
- json_object_object_add(section_ir, "busCommandType", json_object_new_string(bus_error->BusCommand == 0 ? "PCI" : "PCI-X"));
+ json_object_object_add(section_ir, "busCommandType", json_object_new_string(command_type == 0 ? "PCI" : "PCI-X"));
json_object_object_add(section_ir, "busRequestorID", json_object_new_uint64(bus_error->RequestorId));
json_object_object_add(section_ir, "busCompleterID", json_object_new_uint64(bus_error->ResponderId));
json_object_object_add(section_ir, "targetID", json_object_new_uint64(bus_error->TargetId));