Add fixes based on test fuzzing.
diff --git a/generator/README.md b/generator/README.md
new file mode 100644
index 0000000..d7c3f27
--- /dev/null
+++ b/generator/README.md
@@ -0,0 +1,14 @@
+# cper-generator
+This project allows you to generate pseudo-random CPER records for software testing purposes. The records are compliant (to an extent) with the CPER definitions present within UEFI Specification Appendix N.
+
+## Usage
+An example usage of `cper-generator` is shown below.
+```
+cper-generator --out mycper.dump --sections generic dmarvtd ia32x64 arm
+```
+This command would generate a CPER log with a processor generic section, VT-d DMAr section, IA32x64 section and an ARM section, outputting to the given `mycper.dump` file. To see all available names and other command switches, you can run `cper-generator --help`.
+
+## Caveats
+The generator is not completely random within the bounds of the specification, to make testing easier.
+- Validation bits are always set to "true" for optional fields, to ensure that translating from CPER binary -> JSON -> CPER binary yields the same binary output as started with, rather than changing due to optional fields being left out.
+- Parts of sections which are defined in other external specifications (i.e, not included in UEFI Appendix N) generally do not have their structures to specification, and are simply random bytes. Exceptions to this are the PCIe AER and some PCIe capability and device ID structures.
\ No newline at end of file
diff --git a/generator/cper-generate.c b/generator/cper-generate.c
index 93df4fe..85d49cd 100644
--- a/generator/cper-generate.c
+++ b/generator/cper-generate.c
@@ -44,8 +44,17 @@
     header->Flags = 4; //HW_ERROR_FLAGS_SIMULATED
     header->RecordID = (UINT64)rand();
     header->ErrorSeverity = rand() % 4;
-    *((UINT64*)&header->TimeStamp) = (UINT64)rand();
-    header->ValidationBits = rand() % 0b1000;
+
+    //Generate a valid timestamp.
+    header->TimeStamp.Century = int_to_bcd(rand() % 100);
+    header->TimeStamp.Year = int_to_bcd(rand() % 100);
+    header->TimeStamp.Month = int_to_bcd(rand() % 12 + 1);
+    header->TimeStamp.Day = int_to_bcd(rand() % 31 + 1);
+    header->TimeStamp.Hours = int_to_bcd(rand() % 24 + 1);
+    header->TimeStamp.Seconds = int_to_bcd(rand() % 60);
+
+    //Turn all validation bits on.
+    header->ValidationBits = 0b11;
 
     //Generate the section descriptors given the number of sections.
     EFI_ERROR_SECTION_DESCRIPTOR* section_descriptors[num_sections];
@@ -84,10 +93,12 @@
         (EFI_ERROR_SECTION_DESCRIPTOR*)generate_random_bytes(sizeof(EFI_ERROR_SECTION_DESCRIPTOR));
 
     //Set reserved bits to zero.
-    descriptor->SecValidMask &= 0b11;
     descriptor->Resv1 = 0;
     descriptor->SectionFlags &= 0xFF;
 
+    //Validation bits all set to 'on'.
+    descriptor->SecValidMask = 0b11;
+
     //Set severity.
     descriptor->Severity = rand() % 4;
 
@@ -97,6 +108,17 @@
         + (num_sections * sizeof(EFI_ERROR_SECTION_DESCRIPTOR));
     for (int i=0; i<index; i++)
         descriptor->SectionOffset += lengths[i];
+    
+    //Ensure the FRU text is not null terminated early.
+    for (int i=0; i<20; i++)
+    {
+        if (descriptor->FruString[i] = 0x0)
+            descriptor->FruString[i] = rand() % 127 + 1;
+
+        //Null terminate last byte.
+        if (i == 19)
+            descriptor->FruString[i] = 0x0;
+    }
 
     //Set section type GUID based on type name.
     if (strcmp(type, "generic") == 0)
diff --git a/generator/gen-utils.h b/generator/gen-utils.h
index 5dc9a56..4c9e30d 100644
--- a/generator/gen-utils.h
+++ b/generator/gen-utils.h
@@ -3,6 +3,7 @@
 
 #include <stdlib.h>
 #include "../edk/BaseTypes.h"
+#include "../common-utils.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}
 
@@ -10,5 +11,6 @@
 UINT8* generate_random_bytes(size_t size);
 void init_random();
 void create_valid_error_section(UINT8* start);
+UINT8 int_to_bcd(int value);
 
 #endif
\ No newline at end of file
diff --git a/generator/sections/gen-section-generic.c b/generator/sections/gen-section-generic.c
index b2bda16..abc9792 100644
--- a/generator/sections/gen-section-generic.c
+++ b/generator/sections/gen-section-generic.c
@@ -22,5 +22,17 @@
     *(start_byte + 12) &= 0b111;
     *((UINT16*)(start_byte + 14)) = 0x0;
     
+    //Ensure CPU brand string does not terminate early.
+    for (int i=0; i<128; i++)
+    {
+        UINT8* byte = start_byte + 24 + i;
+        if (*byte == 0x0)
+            *byte = rand() % 127 + 1;
+
+        //Null terminate last byte.
+        if (i == 127)
+            *byte = 0x0;
+    }
+
     return size;
 }
\ No newline at end of file
diff --git a/generator/sections/gen-section-ia32x64.c b/generator/sections/gen-section-ia32x64.c
index a9b41e4..0f6f709 100644
--- a/generator/sections/gen-section-ia32x64.c
+++ b/generator/sections/gen-section-ia32x64.c
@@ -37,6 +37,10 @@
         total_len += context_structure_lengths[i];
     UINT8* section = generate_random_bytes(total_len);
 
+    //Null extend the end of the CPUID in the header.
+    for (int i=0; i<16; i++)
+        *(section + 48 + i) = 0x0;
+
     //Set header information.
     UINT64* validation = (UINT64*)section;
     *validation &= 0b11;
@@ -68,33 +72,50 @@
 {
     UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE);
 
+    //Set error structure reserved space to zero.
+    UINT64* validation = (UINT64*)(error_structure + 16);
+    *validation &= 0x1F;
+
     //Create a random type of error structure.
     EFI_GUID* guid = (EFI_GUID*)error_structure;
+    UINT64* check_info = (UINT64*)(error_structure + 24);
     int error_structure_type = rand() % 4;
     switch (error_structure_type)
     {
         //Cache
         case 0:
             memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(EFI_GUID));
-            memset(error_structure + 30, 0, 34);
+
+            //Set reserved space to zero.
+            *check_info &= ~0xFF00;
+            *check_info &= 0x3FFFFFFF;
             break;
 
         //TLB
         case 1:
             memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(EFI_GUID));
-            memset(error_structure + 30, 0, 34);
+
+            //Set reserved space to zero.
+            *check_info &= ~0xFF00;
+            *check_info &= 0x3FFFFFFF;
             break;
 
         //Bus
         case 2:
             memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(EFI_GUID));
-            memset(error_structure + 35, 0, 29);
+
+            //Set reserved space to zero.
+            *check_info &= ~0xF800;
+            *check_info &= 0x7FFFFFFFF;
             break;
 
         //MS
         case 3:
             memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(EFI_GUID));
-            memset(error_structure + 24, 0, 38);
+
+            //Set reserved space to zero.
+            *check_info &= ~0xFF30;
+            *check_info &= 0xFFFFFF;
             break;
     }