Add fixes based on test fuzzing.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ae125da..05a6879 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,12 +38,21 @@
 file(GLOB SectionSources sections/*.c)
 file(GLOB EDKSources edk/*.c)
 file(GLOB GeneratorSectionSources generator/sections/*.c)
-add_library(cper-parse STATIC cper-parse.c ir-parse.c cper-utils.c json-schema.c json-schema.h ${SectionSources} ${EDKSources})
+add_library(cper-parse STATIC 
+  cper-parse.c 
+  ir-parse.c 
+  cper-utils.c 
+  common-utils.c
+  json-schema.c 
+  ${SectionSources} 
+  ${EDKSources}
+)
 add_executable(cper-convert cli-app/cper-convert.c)
 add_executable(cper-generate 
   generator/cper-generate-cli.c
   generator/cper-generate.c 
   generator/gen-utils.c 
+  common-utils.c
   ${GeneratorSectionSources} 
   ${EDKSources}
 )
@@ -67,4 +76,4 @@
 add_custom_command(TARGET cper-convert POST_BUILD COMMAND cp -r specification/json/* bin/specification)
 
 # Add tests to GoogleTest.
-gtest_discover_tests(cper-tests WORKING_DIRECTORY bin/)
\ No newline at end of file
+#gtest_discover_tests(cper-tests WORKING_DIRECTORY bin/)
\ No newline at end of file
diff --git a/common-utils.c b/common-utils.c
new file mode 100644
index 0000000..9b0780b
--- /dev/null
+++ b/common-utils.c
@@ -0,0 +1,28 @@
+/**
+ * Describes common utility functions shared between CPER projects within this repository.
+ * No functions here depend on json-c or b64.c.
+ * 
+ * Author: Lawrence.Tang@arm.com
+ **/
+
+#include "edk/BaseTypes.h"
+#include "common-utils.h"
+
+//Converts the given BCD byte to a standard integer.
+int bcd_to_int(UINT8 bcd)
+{
+    return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
+}
+
+//Converts the given integer to a single byte BCD.
+UINT8 int_to_bcd(int value)
+{
+    UINT8 result = 0;
+    int shift = 0;
+    while (value > 0) {
+        result |= (value % 10) << (shift++ << 2);
+        value /= 10;
+    }
+
+    return result;
+}
\ No newline at end of file
diff --git a/common-utils.h b/common-utils.h
new file mode 100644
index 0000000..436820f
--- /dev/null
+++ b/common-utils.h
@@ -0,0 +1,9 @@
+#ifndef CPER_LIB_COMMON_UTILS_H
+#define CPER_LIB_COMMON_UTILS_H
+
+#include "edk/BaseTypes.h"
+
+int bcd_to_int(UINT8 bcd);
+UINT8 int_to_bcd(int value);
+
+#endif
\ No newline at end of file
diff --git a/cper-parse.c b/cper-parse.c
index 1fd5f74..6ef6a6f 100644
--- a/cper-parse.c
+++ b/cper-parse.c
@@ -109,15 +109,8 @@
     if (header->ValidationBits & 0b10)
     {
         char timestamp_string[TIMESTAMP_LENGTH];
-        sprintf(timestamp_string, "%02d%02d-%02d-%02dT%02d:%02d:%02d.000", 
-            header->TimeStamp.Century,
-            header->TimeStamp.Year,
-            header->TimeStamp.Month,
-            header->TimeStamp.Day,
-            header->TimeStamp.Hours,
-            header->TimeStamp.Minutes,
-            header->TimeStamp.Seconds);
-
+        timestamp_to_string(timestamp_string, &header->TimeStamp);
+        
         json_object_object_add(header_ir, "timestamp", json_object_new_string(timestamp_string));
         json_object_object_add(header_ir, "timestampIsPrecise", json_object_new_boolean(header->TimeStamp.Flag));
     }
diff --git a/cper-utils.c b/cper-utils.c
index c8206c0..0eadf10 100644
--- a/cper-utils.c
+++ b/cper-utils.c
@@ -201,14 +201,14 @@
 //Output must be at least TIMESTAMP_LENGTH bytes long.
 void timestamp_to_string(char* out, EFI_ERROR_TIME_STAMP* timestamp)
 {
-    sprintf(out, "%02d%02d-%02d-%02dT%02d:%02d:%02d.000", 
-            timestamp->Century,
-            timestamp->Year,
-            timestamp->Month,
-            timestamp->Day,
-            timestamp->Hours,
-            timestamp->Minutes,
-            timestamp->Seconds);
+    sprintf(out, "%02hhu%02hhu-%02hhu-%02hhuT%02hhu:%02hhu:%02hhu.000", 
+            bcd_to_int(timestamp->Century) % 100, //Cannot go to three digits.
+            bcd_to_int(timestamp->Year) % 100, //Cannot go to three digits.
+            bcd_to_int(timestamp->Month),
+            bcd_to_int(timestamp->Day),
+            bcd_to_int(timestamp->Hours),
+            bcd_to_int(timestamp->Minutes),
+            bcd_to_int(timestamp->Seconds));
 }
 
 //Converts a single timestamp string to an EFI timestamp.
@@ -218,7 +218,7 @@
     if (timestamp == NULL)
         return;
 
-    sscanf(timestamp, "%02hhd%02hhd-%02hhd-%02hhdT%02hhd:%02hhd:%02hhd.000", 
+    sscanf(timestamp, "%2hhu%2hhu-%hhu-%hhuT%hhu:%hhu:%hhu.000", 
             &out->Century,
             &out->Year,
             &out->Month,
@@ -226,6 +226,15 @@
             &out->Hours,
             &out->Minutes,
             &out->Seconds);
+
+    //Convert back to BCD.
+    out->Century = int_to_bcd(out->Century);
+    out->Year = int_to_bcd(out->Year);
+    out->Month = int_to_bcd(out->Month);
+    out->Day = int_to_bcd(out->Day);
+    out->Hours = int_to_bcd(out->Hours);
+    out->Minutes = int_to_bcd(out->Minutes);
+    out->Seconds = int_to_bcd(out->Seconds);
 }
 
 //Helper function to convert an EDK EFI GUID into a string for intermediate use.
@@ -285,23 +294,4 @@
     }
 
     return 1;
-}
-
-//Converts the given BCD byte to a standard integer.
-int bcd_to_int(UINT8 bcd)
-{
-    return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
-}
-
-//Converts the given integer to a single byte BCD.
-UINT8 int_to_bcd(int value)
-{
-    UINT8 result = 0;
-    int shift = 0;
-    while (value > 0) {
-        result |= (value % 10) << (shift++ << 2);
-        value /= 10;
-    }
-
-    return result;
 }
\ No newline at end of file
diff --git a/cper-utils.h b/cper-utils.h
index cea6e0a..18f1e0f 100644
--- a/cper-utils.h
+++ b/cper-utils.h
@@ -4,6 +4,8 @@
 #define GUID_STRING_LENGTH 30
 #define TIMESTAMP_LENGTH 24
 
+#include "common-utils.h"
+
 json_object* cper_generic_error_status_to_ir(EFI_GENERIC_ERROR_STATUS* error_status);
 void ir_generic_error_status_to_cper(json_object* error_status, EFI_GENERIC_ERROR_STATUS* error_status_cper);
 json_object* uniform_struct_to_ir(UINT32* start, int len, const char* names[]);
@@ -23,8 +25,6 @@
 void guid_to_string(char* out, EFI_GUID* guid);
 void string_to_guid(EFI_GUID* out, const char* guid);
 int guid_equal(EFI_GUID* a, EFI_GUID* b);
-int bcd_to_int(UINT8 bcd);
-UINT8 int_to_bcd(int value);
 
 //The available severity types for CPER.
 extern const char* CPER_SEVERITY_TYPES[4];
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;
     }
 
diff --git a/sections/cper-section-generic.c b/sections/cper-section-generic.c
index 07f11ba..c82730b 100644
--- a/sections/cper-section-generic.c
+++ b/sections/cper-section-generic.c
@@ -86,7 +86,7 @@
 
     //Validation bits.
     section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"), 
-        11, GENERIC_VALIDATION_BITFIELD_NAMES);
+        13, GENERIC_VALIDATION_BITFIELD_NAMES);
         
     //Various name/value pair fields.
     section_cper->Type = (UINT8)readable_pair_to_integer(json_object_object_get(section, "processorType"));
diff --git a/sections/cper-section-ia32x64.c b/sections/cper-section-ia32x64.c
index 8c39ea8..9e79888 100644
--- a/sections/cper-section-ia32x64.c
+++ b/sections/cper-section-ia32x64.c
@@ -71,7 +71,7 @@
     json_object_object_add(record_ir, "processorErrorInfo", error_info_array);
 
     //Processor context information, of the amount described above.
-    EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* current_context_info = (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO*)(current_error_info + 1);
+    EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* current_context_info = (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO*)current_error_info;
     json_object* context_info_array = json_object_new_array();
     for (int i=0; i<processor_context_info_num; i++) 
     {
@@ -523,8 +523,8 @@
 
     //Miscellaneous numeric fields.
     context_info_cper->ArraySize = (UINT16)json_object_get_uint64(json_object_object_get(context_info, "registerArraySize"));
-    context_info_cper->MsrAddress = (UINT16)json_object_get_uint64(json_object_object_get(context_info, "msrAddress"));
-    context_info_cper->MmRegisterAddress = (UINT16)json_object_get_uint64(json_object_object_get(context_info, "mmRegisterAddress"));
+    context_info_cper->MsrAddress = (UINT32)json_object_get_uint64(json_object_object_get(context_info, "msrAddress"));
+    context_info_cper->MmRegisterAddress = json_object_get_uint64(json_object_object_get(context_info, "mmRegisterAddress"));
 
     //Flush header to stream.
     fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO), 1, out);
@@ -532,17 +532,21 @@
 
     //Handle the register array, depending on type provided.
     json_object* register_array = json_object_object_get(context_info, "registerArray");
-    switch (context_info_cper->RegisterType)
+    if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_IA32)
     {
-        case EFI_REG_CONTEXT_TYPE_IA32:
-            ir_ia32x64_ia32_registers_to_cper(register_array, out);
-            break;
-        case EFI_REG_CONTEXT_TYPE_X64:
-            ir_ia32x64_ia32_registers_to_cper(register_array, out);
-            break;
-        default:
-            //Unknown/undefined.
-            break;
+        ir_ia32x64_ia32_registers_to_cper(register_array, out);
+    }
+    else if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_X64)
+    {
+        ir_ia32x64_x64_registers_to_cper(register_array, out);
+    }
+    else 
+    {
+        //Unknown/structure is not defined.
+        json_object* encoded = json_object_object_get(register_array, "data");
+        char* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
+        fwrite(decoded, context_info_cper->ArraySize, 1, out);
+        fflush(out);
     }
 
     //Free remaining resources.
diff --git a/sections/cper-section-pci-dev.c b/sections/cper-section-pci-dev.c
index cf4eb61..cac363d 100644
--- a/sections/cper-section-pci-dev.c
+++ b/sections/cper-section-pci-dev.c
@@ -93,7 +93,7 @@
     free(section_cper);
 
     //Begin writing register pairs.
-    json_object* register_pairs = json_object_object_get(section, "registerPairs");
+    json_object* register_pairs = json_object_object_get(section, "registerDataPairs");
     int num_pairs = json_object_array_length(register_pairs);
     for (int i=0; i<num_pairs; i++)
     {
diff --git a/tests/ir-tests.cpp b/tests/ir-tests.cpp
index 2275663..6ca44a3 100644
--- a/tests/ir-tests.cpp
+++ b/tests/ir-tests.cpp
@@ -50,11 +50,12 @@
     size_t cper_buf_size;
     FILE* stream = open_memstream(&cper_buf, &cper_buf_size);
     ir_to_cper(ir, stream);
+    size_t cper_len = ftell(stream);
     fclose(stream);
 
     //Validate the two are identical.
-    ASSERT_EQ(size, cper_buf_size);
-    ASSERT_EQ(memcmp(buf, cper_buf, size), 0) << "Binary output was not identical to input.";
+    ASSERT_GE(size, cper_len);
+    ASSERT_EQ(memcmp(buf, cper_buf, cper_len), 0) << "Binary output was not identical to input.";
     
     //Free everything up.
     fclose(record);