Support to stringify CPER output

Initial commit to add a "message" property that provides a single line
description of some important properties. This makes it easier to parse
multiple CPERs in crowded logs.

For now, "message" is supported for nvidia, arm processor and memory
types. The other types contain generic messages.

Example output:

```
"sections":[
    {
      "message":"A Corrected CCPLEXSCF NVIDIA Error occurred on CPU 0",
      "Nvidia":{
        "signature":"CCPLEXSC",

 "sections":[
    {
      "message":"An ARM Processor Error occurred on CPU 0; Error Type(s): {Cache Error at Virtual Addr=0x41D6AA12D528 Physical Addr=0x80003A198DDA10}",
      "ArmProcessor":{
        "errorInfoNum":1,

"sections":[
    {
      "message":"A Multi-bit ECC Memory Error occurred at address 0x0000000080000000 at node 0",
```

Change-Id: I395d0370ec60579b8f7fede825b45a3ced8ff18f
Signed-off-by: Aushim Nagarkatti <anagarkatti@nvidia.com>
diff --git a/sections/cper-section-ampere.c b/sections/cper-section-ampere.c
index 5755fa1..8b1bedc 100644
--- a/sections/cper-section-ampere.c
+++ b/sections/cper-section-ampere.c
@@ -4,10 +4,23 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-ampere.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts the given processor-generic CPER section into JSON IR.
-json_object *cper_section_ampere_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_ampere_to_ir(const UINT8 *section, UINT32 size,
+				       char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "An Ampere Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to Ampere description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log("Error: Ampere description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_AMPERE_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-arm.c b/sections/cper-section-arm.c
index 8cce3c4..d360d18 100644
--- a/sections/cper-section-arm.c
+++ b/sections/cper-section-arm.c
@@ -13,10 +13,12 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-arm.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Private pre-definitions.
 json_object *
-cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
+cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info,
+			  char **err_info_desc_i);
 json_object *
 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
 				 const UINT8 **cur_pos, UINT32 *remaining_size);
@@ -45,8 +47,21 @@
 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
 
 //Converts the given processor-generic CPER section into JSON IR.
-json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size,
+				    char **desc_string)
 {
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	int outstr_len = 0;
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "An ARM Processor Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to ARM description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log("Error: ARM description string truncated: %s\n",
+			       *desc_string);
+	}
+
 	const UINT8 *cur_pos = section;
 	UINT32 remaining_size = size;
 
@@ -96,6 +111,29 @@
 		sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
 		json_object_object_add(section_ir, "affinity3",
 				       json_object_new_uint64(sock));
+		char *node_desc_str = malloc(EFI_ERROR_DESCRIPTION_STRING_LEN);
+		outstr_len = snprintf(node_desc_str,
+				      EFI_ERROR_DESCRIPTION_STRING_LEN,
+				      " on CPU %ld", sock);
+		if (outstr_len < 0) {
+			cper_print_log(
+				"Error: Could not write to node description string\n");
+		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+			cper_print_log(
+				"Error: Node description string truncated: %s\n",
+				node_desc_str);
+		} else {
+			if (strlen(node_desc_str) + strlen(*desc_string) <
+			    SECTION_DESC_STRING_SIZE) {
+				strncat(*desc_string, node_desc_str,
+					outstr_len);
+			} else {
+				cper_print_log(
+					"Error: Node description string too long, not added to description string: %s\n",
+					node_desc_str);
+			}
+		}
+		free(node_desc_str);
 	}
 
 	json_object_object_add(section_ir, "midrEl1",
@@ -128,11 +166,47 @@
 			"Invalid CPER file: Invalid processor error info num.\n");
 		return NULL;
 	}
+	strncat(*desc_string, "; Error Type(s): {",
+		EFI_ERROR_DESCRIPTION_STRING_LEN);
+	char *err_info_desc_i =
+		malloc(EFI_ERROR_INFORMATION_DESCRIPTION_STRING_LEN);
+	size_t err_info_desc_i_len = 0;
 	for (int i = 0; i < record->ErrInfoNum; i++) {
-		json_object_array_add(error_info_array,
-				      cper_arm_error_info_to_ir(cur_error));
+		json_object_array_add(
+			error_info_array,
+			cper_arm_error_info_to_ir(cur_error, &err_info_desc_i));
+		err_info_desc_i_len = strlen(err_info_desc_i);
+		if (err_info_desc_i_len > 0 &&
+		    strlen(*desc_string) + err_info_desc_i_len <
+			    SECTION_DESC_STRING_SIZE) {
+			strncat(*desc_string, err_info_desc_i,
+				err_info_desc_i_len);
+		} else {
+			cper_print_log(
+				"Error: Error info description string too long, not added to description string: %s\n",
+				err_info_desc_i);
+		}
 		cur_error++;
+		if (i == record->ErrInfoNum - 1) {
+			if (strlen(*desc_string) + 2 <
+			    SECTION_DESC_STRING_SIZE) {
+				strncat(*desc_string, "}", 2);
+			} else {
+				cper_print_log(
+					"Error: Description string too long, not added '}'to description string: %s\n",
+					*desc_string);
+			}
+			break;
+		}
+		if (strlen(*desc_string) + 3 < SECTION_DESC_STRING_SIZE) {
+			strncat(*desc_string, ", ", 3);
+		} else {
+			cper_print_log(
+				"Error: Description string too long, not added ',' to description string: %s\n",
+				*desc_string);
+		}
 	}
+	free(err_info_desc_i);
 
 	cur_pos += (UINT32)(record->ErrInfoNum *
 			    sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY));
@@ -213,9 +287,11 @@
 
 //Converts a single ARM Process Error Information structure into JSON IR.
 json_object *
-cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
+cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info,
+			  char **err_info_desc_i)
 {
 	json_object *error_info_ir = json_object_new_object();
+	int outstr_len = 0;
 
 	//Version, length.
 	json_object_object_add(error_info_ir, "version",
@@ -260,16 +336,51 @@
 		json_object *error_subinfo = NULL;
 		switch (error_info->Type) {
 		case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
-		case ARM_ERROR_INFORMATION_TYPE_TLB:   //TLB
 			error_subinfo = cper_arm_cache_tlb_error_to_ir(
 				(EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
 					->ErrorInformation,
 				error_info);
+			const char *cache_error_desc = "Cache Error";
+			if (strlen(cache_error_desc) >=
+			    EFI_ERROR_INFORMATION_DESCRIPTION_STRING_LEN) {
+				cper_print_log(
+					"Error: Cache Error Description too long %s\n",
+					cache_error_desc);
+			} else {
+				strncpy(*err_info_desc_i, cache_error_desc,
+					strlen(cache_error_desc) + 1);
+			}
+			break;
+		case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
+			error_subinfo = cper_arm_cache_tlb_error_to_ir(
+				(EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
+					->ErrorInformation,
+				error_info);
+			const char *tlb_error_desc = "TLB Error";
+			if (strlen(tlb_error_desc) >=
+			    EFI_ERROR_INFORMATION_DESCRIPTION_STRING_LEN) {
+				cper_print_log(
+					"Error: TLB Error Description too long %s\n",
+					tlb_error_desc);
+			} else {
+				strncpy(*err_info_desc_i, tlb_error_desc,
+					strlen(tlb_error_desc) + 1);
+			}
 			break;
 		case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
 			error_subinfo = cper_arm_bus_error_to_ir(
 				(EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
 					->ErrorInformation);
+			const char *bus_error_desc = "Bus Error";
+			if (strlen(bus_error_desc) >=
+			    EFI_ERROR_INFORMATION_DESCRIPTION_STRING_LEN) {
+				cper_print_log(
+					"Error: Bus Error Description too long %s\n",
+					bus_error_desc);
+			} else {
+				strncpy(*err_info_desc_i, bus_error_desc,
+					strlen(bus_error_desc) + 1);
+			}
 			break;
 
 		default:
@@ -284,19 +395,68 @@
 	}
 
 	//Virtual fault address, physical fault address.
+	char *fault_address_desc = malloc(EFI_ERROR_DESCRIPTION_STRING_LEN);
 	if (isvalid_prop_to_ir(&ui16Type, 3)) {
+		outstr_len = snprintf(fault_address_desc,
+				      EFI_ERROR_DESCRIPTION_STRING_LEN,
+				      " at Virtual Addr=0x%llX",
+				      error_info->VirtualFaultAddress);
+		if (outstr_len < 0) {
+			cper_print_log(
+				"Error: Could not write to fault address description string\n");
+		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+			cper_print_log(
+				"Error: Virtual fault address description string truncated: %s\n",
+				fault_address_desc);
+		} else {
+			if (strlen(fault_address_desc) +
+				    strlen(*err_info_desc_i) <
+			    EFI_ERROR_INFORMATION_DESCRIPTION_STRING_LEN) {
+				strncat(*err_info_desc_i, fault_address_desc,
+					outstr_len);
+			} else {
+				cper_print_log(
+					"Error: Virtual fault address description string too long, not added to description string: %s\n",
+					fault_address_desc);
+			}
+		}
 		json_object_object_add(
 			error_info_ir, "virtualFaultAddress",
 			json_object_new_uint64(
 				error_info->VirtualFaultAddress));
 	}
 	if (isvalid_prop_to_ir(&ui16Type, 4)) {
+		outstr_len = snprintf(fault_address_desc,
+				      EFI_ERROR_DESCRIPTION_STRING_LEN,
+				      " Physical Addr=0x%llX",
+				      error_info->PhysicalFaultAddress);
+		if (outstr_len < 0) {
+			cper_print_log(
+				"Error: Could not write to physical fault address description string\n");
+		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+			cper_print_log(
+				"Error: Physical fault address description string truncated: %s\n",
+				fault_address_desc);
+		} else {
+			if (strlen(fault_address_desc) +
+				    strlen(*err_info_desc_i) <
+			    EFI_ERROR_INFORMATION_DESCRIPTION_STRING_LEN) {
+				strncat(*err_info_desc_i, fault_address_desc,
+					outstr_len);
+			} else {
+				cper_print_log(
+					"Error:Physical fault address description string too long, not added to description string: %s\n",
+					fault_address_desc);
+			}
+		}
 		json_object_object_add(
 			error_info_ir, "physicalFaultAddress",
 			json_object_new_uint64(
 				error_info->PhysicalFaultAddress));
 	}
 
+	free(fault_address_desc);
+
 	return error_info_ir;
 }
 
diff --git a/sections/cper-section-ccix-per.c b/sections/cper-section-ccix-per.c
index a8a5310..4f41a28 100644
--- a/sections/cper-section-ccix-per.c
+++ b/sections/cper-section-ccix-per.c
@@ -12,10 +12,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-ccix-per.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single CCIX PER log CPER section into JSON IR.
-json_object *cper_section_ccix_per_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_ccix_per_to_ir(const UINT8 *section, UINT32 size,
+					 char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A CCIX PER Log Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to CCIX PER Log description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: CCIX PER Log description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_CCIX_PER_LOG_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-cxl-component.c b/sections/cper-section-cxl-component.c
index c4e8169..39255eb 100644
--- a/sections/cper-section-cxl-component.c
+++ b/sections/cper-section-cxl-component.c
@@ -11,10 +11,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-cxl-component.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single CXL component error CPER section into JSON IR.
-json_object *cper_section_cxl_component_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_cxl_component_to_ir(const UINT8 *section, UINT32 size,
+					      char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A CXL Component Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to CXL Component description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: CXL Component description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-cxl-protocol.c b/sections/cper-section-cxl-protocol.c
index 6ae5325..6e69153 100644
--- a/sections/cper-section-cxl-protocol.c
+++ b/sections/cper-section-cxl-protocol.c
@@ -11,10 +11,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-cxl-protocol.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single CXL protocol error CPER section into JSON IR.
-json_object *cper_section_cxl_protocol_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_cxl_protocol_to_ir(const UINT8 *section, UINT32 size,
+					     char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A CXL Protocol Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to CXL protocol description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: CXL protocol description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_CXL_PROTOCOL_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-dmar-generic.c b/sections/cper-section-dmar-generic.c
index d75647e..4605cd8 100644
--- a/sections/cper-section-dmar-generic.c
+++ b/sections/cper-section-dmar-generic.c
@@ -10,10 +10,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-dmar-generic.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single generic DMAr CPER section into JSON IR.
-json_object *cper_section_dmar_generic_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_dmar_generic_to_ir(const UINT8 *section, UINT32 size,
+					     char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A DMAr Generic Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to DMAr Generic description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: DMAr Generic description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_DMAR_GENERIC_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-dmar-iommu.c b/sections/cper-section-dmar-iommu.c
index df22ce0..6d3df8f 100644
--- a/sections/cper-section-dmar-iommu.c
+++ b/sections/cper-section-dmar-iommu.c
@@ -12,10 +12,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-dmar-iommu.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single IOMMU specific DMAr CPER section into JSON IR.
-json_object *cper_section_dmar_iommu_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_dmar_iommu_to_ir(const UINT8 *section, UINT32 size,
+					   char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A IOMMU Specific DMAr Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to IOMMU Specific DMAr description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: IOMMU Specific DMAr description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_IOMMU_DMAR_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-dmar-vtd.c b/sections/cper-section-dmar-vtd.c
index fcbce18..0b82bf6 100644
--- a/sections/cper-section-dmar-vtd.c
+++ b/sections/cper-section-dmar-vtd.c
@@ -12,10 +12,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-dmar-vtd.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single VT-d specific DMAr CPER section into JSON IR.
-json_object *cper_section_dmar_vtd_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_dmar_vtd_to_ir(const UINT8 *section, UINT32 size,
+					 char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A VT-d DMAr Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to VT-d DMAr description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: VT-d DMAr description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-firmware.c b/sections/cper-section-firmware.c
index b88d69e..f16b0dd 100644
--- a/sections/cper-section-firmware.c
+++ b/sections/cper-section-firmware.c
@@ -10,10 +10,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-firmware.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single firmware CPER section into JSON IR.
-json_object *cper_section_firmware_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_firmware_to_ir(const UINT8 *section, UINT32 size,
+					 char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A Firmware Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to Firmware description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: Firmware description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_FIRMWARE_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-generic.c b/sections/cper-section-generic.c
index 8117419..0bbe40e 100644
--- a/sections/cper-section-generic.c
+++ b/sections/cper-section-generic.c
@@ -12,10 +12,23 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-generic.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts the given processor-generic CPER section into JSON IR.
-json_object *cper_section_generic_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_generic_to_ir(const UINT8 *section, UINT32 size,
+					char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A Generic Processor Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to Generic description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log("Error: Generic description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-ia32x64.c b/sections/cper-section-ia32x64.c
index 85f03a4..81d1248 100644
--- a/sections/cper-section-ia32x64.c
+++ b/sections/cper-section-ia32x64.c
@@ -12,6 +12,7 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-ia32x64.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Private pre-definitions.
 json_object *cper_ia32x64_processor_error_info_to_ir(
@@ -45,8 +46,21 @@
 //////////////////
 
 //Converts the IA32/x64 error section described in the given descriptor into intermediate format.
-json_object *cper_section_ia32x64_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_ia32x64_to_ir(const UINT8 *section, UINT32 size,
+					char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "An IA32/x64 Processor Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to IA32/x64 description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: IA32/x64 description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-ipf.c b/sections/cper-section-ipf.c
index fb9243e..2029a22 100644
--- a/sections/cper-section-ipf.c
+++ b/sections/cper-section-ipf.c
@@ -10,14 +10,27 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-ipf.h>
 #include <libcper/log.h>
+#include <string.h>
 
 json_object *cper_ipf_mod_error_read_array(EFI_IPF_MOD_ERROR_INFO **cur_error,
 					   int num_to_read);
 json_object *cper_ipf_mod_error_to_ir(EFI_IPF_MOD_ERROR_INFO *mod_error);
 
 //Converts a single Intel IPF error CPER section into JSON IR.
-json_object *cper_section_ipf_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_ipf_to_ir(const UINT8 *section, UINT32 size,
+				    char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "An IPF Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to IPF description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log("Error: IPF description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_IPF_ERROR_INFO_HEADER)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-memory.c b/sections/cper-section-memory.c
index 347039a..95eac67 100644
--- a/sections/cper-section-memory.c
+++ b/sections/cper-section-memory.c
@@ -10,11 +10,14 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-memory.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single memory error CPER section into JSON IR.
 json_object *cper_section_platform_memory_to_ir(const UINT8 *section,
-						UINT32 size)
+						UINT32 size, char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
 	if (size < sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)) {
 		return NULL;
 	}
@@ -52,14 +55,32 @@
 	json_object_object_add(section_ir, "bank", bank);
 
 	//Memory error type.
+	const char *mem_type_str = NULL;
 	if (isvalid_prop_to_ir(&ui64Type, 14)) {
 		json_object *memory_error_type = integer_to_readable_pair(
 			memory_error->ErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
 			MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
 		json_object_object_add(section_ir, "memoryErrorType",
 				       memory_error_type);
+		mem_type_str = json_object_get_string(
+			json_object_object_get(memory_error_type, "name"));
 	}
-
+	if (mem_type_str != NULL) {
+		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+				      "A %s Memory Error occurred",
+				      mem_type_str);
+	} else {
+		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+				      "An Unknown Memory Error occurred");
+	}
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to Memory description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: Memory description string truncated: %s\n",
+			*desc_string);
+	}
 	//"Extended" row/column indication field + misc.
 	// Review this
 	if (isvalid_prop_to_ir(&ui64Type, 18)) {
@@ -105,6 +126,30 @@
 			 memory_error->PhysicalAddress);
 		json_object_object_add(section_ir, "physicalAddressHex",
 				       json_object_new_string(hexstring_buf));
+		char physical_address_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
+		outstr_len = snprintf(physical_address_desc,
+				      EFI_ERROR_DESCRIPTION_STRING_LEN,
+				      " at address 0x%016llX",
+				      memory_error->PhysicalAddress);
+		if (outstr_len < 0) {
+			cper_print_log(
+				"Error: Could not write to physical address description string\n");
+		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+			cper_print_log(
+				"Error: Physical address description string truncated: %s\n",
+				physical_address_desc);
+		} else {
+			if (strlen(physical_address_desc) +
+				    strlen(*desc_string) <
+			    SECTION_DESC_STRING_SIZE) {
+				strncat(*desc_string, physical_address_desc,
+					outstr_len);
+			} else {
+				cper_print_log(
+					"Error: Memory description string too long, not added to description string: %s\n",
+					physical_address_desc);
+			}
+		}
 	}
 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
 		json_object_object_add(
@@ -116,7 +161,29 @@
 		json_object_object_add(
 			section_ir, "node",
 			json_object_new_uint64(memory_error->Node));
+		char node_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
+		outstr_len = snprintf(node_desc,
+				      EFI_ERROR_DESCRIPTION_STRING_LEN,
+				      " at node %d", memory_error->Node);
+		if (outstr_len < 0) {
+			cper_print_log(
+				"Error: Could not write to node description string\n");
+		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+			cper_print_log(
+				"Error: Node description string truncated: %s\n",
+				node_desc);
+		} else {
+			if (strlen(node_desc) + strlen(*desc_string) <
+			    SECTION_DESC_STRING_SIZE) {
+				strncat(*desc_string, node_desc, outstr_len);
+			} else {
+				cper_print_log(
+					"Error: Memory description string too long, not added to description string: %s\n",
+					node_desc);
+			}
+		}
 	}
+
 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
 		json_object_object_add(
 			section_ir, "card",
@@ -173,8 +240,12 @@
 
 //Converts a single memory error 2 CPER section into JSON IR.
 json_object *cper_section_platform_memory2_to_ir(const UINT8 *section,
-						 UINT32 size)
+						 UINT32 size,
+						 char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+
 	if (size < sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA)) {
 		return NULL;
 	}
@@ -212,14 +283,32 @@
 	json_object_object_add(section_ir, "bank", bank);
 
 	//Memory error type.
+	const char *mem_type_str = NULL;
 	if (isvalid_prop_to_ir(&ui64Type, 13)) {
 		json_object *memory_error_type = integer_to_readable_pair(
 			memory_error->MemErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
 			MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
 		json_object_object_add(section_ir, "memoryErrorType",
 				       memory_error_type);
+		mem_type_str = json_object_get_string(
+			json_object_object_get(memory_error_type, "name"));
 	}
-
+	if (mem_type_str != NULL) {
+		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+				      "A %s Memory Error occurred",
+				      mem_type_str);
+	} else {
+		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+				      "An Unknown Memory Error occurred");
+	}
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to Memory2 description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: Memory2 description string truncated: %s\n",
+			*desc_string);
+	}
 	//Status.
 	if (isvalid_prop_to_ir(&ui64Type, 14)) {
 		json_object *status = json_object_new_object();
@@ -240,6 +329,30 @@
 		json_object_object_add(
 			section_ir, "physicalAddress",
 			json_object_new_uint64(memory_error->PhysicalAddress));
+		char physical_address_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
+		outstr_len = snprintf(physical_address_desc,
+				      EFI_ERROR_DESCRIPTION_STRING_LEN,
+				      " at address 0x%016llX",
+				      memory_error->PhysicalAddress);
+		if (outstr_len < 0) {
+			cper_print_log(
+				"Error: Could not write to physical address description string\n");
+		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+			cper_print_log(
+				"Error: Physical address description string truncated: %s\n",
+				physical_address_desc);
+		} else {
+			if (strlen(physical_address_desc) +
+				    strlen(*desc_string) <
+			    SECTION_DESC_STRING_SIZE) {
+				strncat(*desc_string, physical_address_desc,
+					outstr_len);
+			} else {
+				cper_print_log(
+					"Error: Memory2 description string too long, not added to description string: %s\n",
+					physical_address_desc);
+			}
+		}
 	}
 
 	char hexstring_buf[EFI_UINT64_HEX_STRING_LEN];
@@ -258,6 +371,27 @@
 		json_object_object_add(
 			section_ir, "node",
 			json_object_new_uint64(memory_error->Node));
+		char node_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
+		outstr_len = snprintf(node_desc,
+				      EFI_ERROR_DESCRIPTION_STRING_LEN,
+				      " on node %d", memory_error->Node);
+		if (outstr_len < 0) {
+			cper_print_log(
+				"Error: Could not write to node description string\n");
+		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+			cper_print_log(
+				"Error: Node description string truncated: %s\n",
+				node_desc);
+		} else {
+			if (strlen(node_desc) + strlen(*desc_string) <
+			    SECTION_DESC_STRING_SIZE) {
+				strncat(*desc_string, node_desc, outstr_len);
+			} else {
+				cper_print_log(
+					"Error: Memory2 description string too long, not added to description string: %s\n",
+					node_desc);
+			}
+		}
 	}
 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
 		json_object_object_add(
diff --git a/sections/cper-section-nvidia.c b/sections/cper-section-nvidia.c
index b633396..c75bf8a 100644
--- a/sections/cper-section-nvidia.c
+++ b/sections/cper-section-nvidia.c
@@ -11,6 +11,7 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-nvidia.h>
 #include <libcper/log.h>
+#include <string.h>
 
 void parse_cmet_info(EFI_NVIDIA_REGISTER_DATA *regPtr, UINT8 NumberRegs,
 		     size_t size, json_object *section_ir)
@@ -110,9 +111,15 @@
 };
 
 //Converts a single NVIDIA CPER section into JSON IR.
-json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size,
+				       char **desc_string)
 {
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	char *property_desc = malloc(EFI_ERROR_DESCRIPTION_STRING_LEN);
+
 	if (size < sizeof(EFI_NVIDIA_ERROR_DATA)) {
+		free(property_desc);
+		*desc_string = NULL;
 		return NULL;
 	}
 
@@ -120,15 +127,27 @@
 
 	json_object *section_ir = json_object_new_object();
 
-	add_untrusted_string(section_ir, "signature", nvidia_error->Signature,
-			     sizeof(nvidia_error->Signature));
+	const char *signature = nvidia_error->Signature;
+	add_untrusted_string(section_ir, "signature", signature,
+			     strlen(signature));
 
 	json_object *severity = json_object_new_object();
 	json_object_object_add(severity, "code",
 			       json_object_new_uint64(nvidia_error->Severity));
+	const char *severity_name = severity_to_string(nvidia_error->Severity);
 	json_object_object_add(severity, "name",
-			       json_object_new_string(severity_to_string(
-				       nvidia_error->Severity)));
+			       json_object_new_string(severity_name));
+	int outstr_len = 0;
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A %s %s NVIDIA Error occurred", severity_name,
+			      signature);
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log("Error: Description string truncated: %s\n",
+			       *desc_string);
+	}
 	json_object_object_add(section_ir, "severity", severity);
 
 	json_object_object_add(section_ir, "errorType",
@@ -138,6 +157,26 @@
 		json_object_new_int(nvidia_error->ErrorInstance));
 	json_object_object_add(section_ir, "socket",
 			       json_object_new_int(nvidia_error->Socket));
+
+	outstr_len = snprintf(property_desc, EFI_ERROR_DESCRIPTION_STRING_LEN,
+			      " on CPU %d", nvidia_error->Socket);
+	if (outstr_len < 0) {
+		cper_print_log("Error: Could not write to property string\n");
+	} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
+		cper_print_log("Error: Property string truncated: %s\n",
+			       property_desc);
+	}
+
+	int property_desc_len = strlen(property_desc);
+	strncat(*desc_string, property_desc, property_desc_len);
+	// We still want to get as much info as possible, just warn about truncation
+	if (property_desc_len + strlen(*desc_string) >=
+	    SECTION_DESC_STRING_SIZE) {
+		cper_print_log("Error: Description string truncated: %s\n",
+			       *desc_string);
+	}
+	free(property_desc);
+
 	json_object_object_add(section_ir, "registerCount",
 			       json_object_new_int(nvidia_error->NumberRegs));
 	json_object_object_add(
diff --git a/sections/cper-section-pci-bus.c b/sections/cper-section-pci-bus.c
index 60840e7..a593aeb 100644
--- a/sections/cper-section-pci-bus.c
+++ b/sections/cper-section-pci-bus.c
@@ -11,10 +11,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-pci-bus.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single PCI/PCI-X bus CPER section into JSON IR.
-json_object *cper_section_pci_bus_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_pci_bus_to_ir(const UINT8 *section, UINT32 size,
+					char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A PCI/PCI-X Bus Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to PCI/PCI-X Bus description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: PCI/PCI-X Bus description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_PCI_PCIX_BUS_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-pci-dev.c b/sections/cper-section-pci-dev.c
index 359e56e..b034d5f 100644
--- a/sections/cper-section-pci-dev.c
+++ b/sections/cper-section-pci-dev.c
@@ -10,10 +10,24 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-pci-dev.h>
 #include <libcper/log.h>
+#include <string.h>
 
 //Converts a single PCI/PCI-X device CPER section into JSON IR.
-json_object *cper_section_pci_dev_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_pci_dev_to_ir(const UINT8 *section, UINT32 size,
+					char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A PCI/PCI-X Device Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to PCI/PCI-X Device description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log(
+			"Error: PCI/PCI-X Device description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA)) {
 		return NULL;
 	}
diff --git a/sections/cper-section-pcie.c b/sections/cper-section-pcie.c
index e39dafd..ee00a02 100644
--- a/sections/cper-section-pcie.c
+++ b/sections/cper-section-pcie.c
@@ -12,6 +12,7 @@
 #include <libcper/cper-utils.h>
 #include <libcper/sections/cper-section-pcie.h>
 #include <libcper/log.h>
+#include <string.h>
 
 json_object *pcie_capability_to_ir(EFI_PCIE_ERROR_DATA *pcie_error);
 json_object *pcie_aer_to_ir(EFI_PCIE_ERROR_DATA *pcie_error);
@@ -293,8 +294,20 @@
 }
 
 //Converts a single PCIe CPER section into JSON IR.
-json_object *cper_section_pcie_to_ir(const UINT8 *section, UINT32 size)
+json_object *cper_section_pcie_to_ir(const UINT8 *section, UINT32 size,
+				     char **desc_string)
 {
+	int outstr_len = 0;
+	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
+	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
+			      "A PCIe Error occurred");
+	if (outstr_len < 0) {
+		cper_print_log(
+			"Error: Could not write to PCIe description string\n");
+	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
+		cper_print_log("Error: PCIe description string truncated\n");
+	}
+
 	if (size < sizeof(EFI_PCIE_ERROR_DATA)) {
 		return NULL;
 	}