Remove validation bits

Discard invalid properties from json decode. JSON output should only
contain valid properties. This saves time in preventing post
processing of output for valid fields.

Ensure round trip validity with validation bits removed and required
properties populated.

Fix bugs in json decode.

Overhaul unit tests to use valijson. Add tests with static examples
to validate against schema. Use and nlohmann for better schema
validation over intrinsic libcper validation.

Example json output before:
{
  "ValidationBits": {
    "LevelValid": false,
    "CorrectedValid": true
  },
  "Level": 1,
  "Corrected": true
}

After:
{
  "Corrected": true
}

Change-Id: I188bdc2827a57d938c22a431238fadfcdc939ab8
Signed-off-by: Aushim Nagarkatti <anagarkatti@nvidia.com>
diff --git a/sections/cper-section-cxl-component.c b/sections/cper-section-cxl-component.c
index a5c6846..f915b28 100644
--- a/sections/cper-section-cxl-component.c
+++ b/sections/cper-section-cxl-component.c
@@ -23,62 +23,68 @@
 			       json_object_new_uint64(cxl_error->Length));
 
 	//Validation bits.
-	json_object *validation =
-		bitfield_to_ir(cxl_error->ValidBits, 3,
-			       CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES);
-	json_object_object_add(section_ir, "validationBits", validation);
+	ValidationTypes ui64Type = { UINT_64T,
+				     .value.ui64 = cxl_error->ValidBits };
 
 	//Device ID.
-	json_object *device_id = json_object_new_object();
-	json_object_object_add(
-		device_id, "vendorID",
-		json_object_new_int(cxl_error->DeviceId.VendorId));
-	json_object_object_add(
-		device_id, "deviceID",
-		json_object_new_int(cxl_error->DeviceId.DeviceId));
-	json_object_object_add(
-		device_id, "functionNumber",
-		json_object_new_int(cxl_error->DeviceId.FunctionNumber));
-	json_object_object_add(
-		device_id, "deviceNumber",
-		json_object_new_int(cxl_error->DeviceId.DeviceNumber));
-	json_object_object_add(
-		device_id, "busNumber",
-		json_object_new_int(cxl_error->DeviceId.BusNumber));
-	json_object_object_add(
-		device_id, "segmentNumber",
-		json_object_new_int(cxl_error->DeviceId.SegmentNumber));
-	json_object_object_add(
-		device_id, "slotNumber",
-		json_object_new_int(cxl_error->DeviceId.SlotNumber));
-	json_object_object_add(section_ir, "deviceID", device_id);
+	if (isvalid_prop_to_ir(&ui64Type, 0)) {
+		json_object *device_id = json_object_new_object();
+		json_object_object_add(
+			device_id, "vendorID",
+			json_object_new_int(cxl_error->DeviceId.VendorId));
+		json_object_object_add(
+			device_id, "deviceID",
+			json_object_new_int(cxl_error->DeviceId.DeviceId));
+		json_object_object_add(
+			device_id, "functionNumber",
+			json_object_new_int(
+				cxl_error->DeviceId.FunctionNumber));
+		json_object_object_add(
+			device_id, "deviceNumber",
+			json_object_new_int(cxl_error->DeviceId.DeviceNumber));
+		json_object_object_add(
+			device_id, "busNumber",
+			json_object_new_int(cxl_error->DeviceId.BusNumber));
+		json_object_object_add(
+			device_id, "segmentNumber",
+			json_object_new_int(cxl_error->DeviceId.SegmentNumber));
+		json_object_object_add(
+			device_id, "slotNumber",
+			json_object_new_int(cxl_error->DeviceId.SlotNumber));
+		json_object_object_add(section_ir, "deviceID", device_id);
+	}
 
 	//Device serial.
-	json_object_object_add(section_ir, "deviceSerial",
-			       json_object_new_uint64(cxl_error->DeviceSerial));
+	if (isvalid_prop_to_ir(&ui64Type, 1)) {
+		json_object_object_add(
+			section_ir, "deviceSerial",
+			json_object_new_uint64(cxl_error->DeviceSerial));
+	}
 
 	//The specification for this is defined within the CXL Specification Section 8.2.9.1.
-	const char *cur_pos = (const char *)(cxl_error + 1);
-	int remaining_len =
-		cxl_error->Length - sizeof(EFI_CXL_COMPONENT_EVENT_HEADER);
-	if (remaining_len > 0) {
-		json_object *event_log = json_object_new_object();
+	if (isvalid_prop_to_ir(&ui64Type, 2)) {
+		const char *cur_pos = (const char *)(cxl_error + 1);
+		int remaining_len = cxl_error->Length -
+				    sizeof(EFI_CXL_COMPONENT_EVENT_HEADER);
+		if (remaining_len > 0) {
+			json_object *event_log = json_object_new_object();
 
-		int32_t encoded_len = 0;
+			int32_t encoded_len = 0;
 
-		char *encoded = base64_encode((UINT8 *)cur_pos, remaining_len,
-					      &encoded_len);
-		if (encoded == NULL) {
-			printf("Failed to allocate encode output buffer. \n");
-			return NULL;
+			char *encoded = base64_encode(
+				(UINT8 *)cur_pos, remaining_len, &encoded_len);
+			if (encoded == NULL) {
+				printf("Failed to allocate encode output buffer. \n");
+				return NULL;
+			}
+			json_object_object_add(event_log, "data",
+					       json_object_new_string_len(
+						       encoded, encoded_len));
+
+			free(encoded);
+			json_object_object_add(
+				section_ir, "cxlComponentEventLog", event_log);
 		}
-		json_object_object_add(event_log, "data",
-				       json_object_new_string_len(encoded,
-								  encoded_len));
-
-		free(encoded);
-		json_object_object_add(section_ir, "cxlComponentEventLog",
-				       event_log);
 	}
 
 	return section_ir;
@@ -97,52 +103,64 @@
 		json_object_object_get(section, "length"));
 
 	//Validation bits.
-	section_cper->ValidBits = ir_to_bitfield(
-		json_object_object_get(section, "validationBits"), 3,
-		CXL_COMPONENT_ERROR_VALID_BITFIELD_NAMES);
+	ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
+	struct json_object *obj = NULL;
 
 	//Device ID information.
-	json_object *device_id = json_object_object_get(section, "deviceID");
-	section_cper->DeviceId.VendorId = json_object_get_uint64(
-		json_object_object_get(device_id, "vendorID"));
-	section_cper->DeviceId.DeviceId = json_object_get_uint64(
-		json_object_object_get(device_id, "deviceID"));
-	section_cper->DeviceId.FunctionNumber = json_object_get_uint64(
-		json_object_object_get(device_id, "functionNumber"));
-	section_cper->DeviceId.DeviceNumber = json_object_get_uint64(
-		json_object_object_get(device_id, "deviceNumber"));
-	section_cper->DeviceId.BusNumber = json_object_get_uint64(
-		json_object_object_get(device_id, "busNumber"));
-	section_cper->DeviceId.SegmentNumber = json_object_get_uint64(
-		json_object_object_get(device_id, "segmentNumber"));
-	section_cper->DeviceId.SlotNumber = json_object_get_uint64(
-		json_object_object_get(device_id, "slotNumber"));
+	if (json_object_object_get_ex(section, "deviceID", &obj)) {
+		json_object *device_id = obj;
+		section_cper->DeviceId.VendorId = json_object_get_uint64(
+			json_object_object_get(device_id, "vendorID"));
+		section_cper->DeviceId.DeviceId = json_object_get_uint64(
+			json_object_object_get(device_id, "deviceID"));
+		section_cper->DeviceId.FunctionNumber = json_object_get_uint64(
+			json_object_object_get(device_id, "functionNumber"));
+		section_cper->DeviceId.DeviceNumber = json_object_get_uint64(
+			json_object_object_get(device_id, "deviceNumber"));
+		section_cper->DeviceId.BusNumber = json_object_get_uint64(
+			json_object_object_get(device_id, "busNumber"));
+		section_cper->DeviceId.SegmentNumber = json_object_get_uint64(
+			json_object_object_get(device_id, "segmentNumber"));
+		section_cper->DeviceId.SlotNumber = json_object_get_uint64(
+			json_object_object_get(device_id, "slotNumber"));
+		add_to_valid_bitfield(&ui64Type, 0);
+	}
 
 	//Device serial number.
-	section_cper->DeviceSerial = json_object_get_uint64(
-		json_object_object_get(section, "deviceSerial"));
+	if (json_object_object_get_ex(section, "deviceSerial", &obj)) {
+		section_cper->DeviceSerial = json_object_get_uint64(obj);
+		add_to_valid_bitfield(&ui64Type, 1);
+	}
+
+	//CXL component event log, decoded from base64.
+	json_object *event_log = NULL;
+	if (json_object_object_get_ex(section, "cxlComponentEventLog", &obj)) {
+		event_log = obj;
+		add_to_valid_bitfield(&ui64Type, 2);
+	}
+	section_cper->ValidBits = ui64Type.value.ui64;
 
 	//Write header out to stream.
 	fwrite(section_cper, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER), 1, out);
 	fflush(out);
 
-	//CXL component event log, decoded from base64.
-	json_object *event_log =
-		json_object_object_get(section, "cxlComponentEventLog");
-	json_object *encoded = json_object_object_get(event_log, "data");
+	if (event_log != NULL) {
+		json_object *encoded =
+			json_object_object_get(event_log, "data");
 
-	int32_t decoded_len = 0;
+		int32_t decoded_len = 0;
 
-	UINT8 *decoded = base64_decode(json_object_get_string(encoded),
-				       json_object_get_string_len(encoded),
-				       &decoded_len);
+		UINT8 *decoded = base64_decode(
+			json_object_get_string(encoded),
+			json_object_get_string_len(encoded), &decoded_len);
 
-	if (decoded == NULL) {
-		printf("Failed to allocate decode output buffer. \n");
-	} else {
-		fwrite(decoded, decoded_len, 1, out);
-		fflush(out);
-		free(decoded);
+		if (decoded == NULL) {
+			printf("Failed to allocate decode output buffer. \n");
+		} else {
+			fwrite(decoded, decoded_len, 1, out);
+			fflush(out);
+			free(decoded);
+		}
 	}
 
 	free(section_cper);