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-pci-dev.c b/sections/cper-section-pci-dev.c
index ccf9f0c..8dc899b 100644
--- a/sections/cper-section-pci-dev.c
+++ b/sections/cper-section-pci-dev.c
@@ -18,67 +18,85 @@
json_object *section_ir = json_object_new_object();
//Validation bits.
- json_object *validation = bitfield_to_ir(
- dev_error->ValidFields, 5, PCI_DEV_ERROR_VALID_BITFIELD_NAMES);
- json_object_object_add(section_ir, "validationBits", validation);
+ ValidationTypes ui64Type = { UINT_64T,
+ .value.ui64 = dev_error->ValidFields };
//Error status.
- json_object *error_status =
- cper_generic_error_status_to_ir(&dev_error->ErrorStatus);
- json_object_object_add(section_ir, "errorStatus", error_status);
+ if (isvalid_prop_to_ir(&ui64Type, 0)) {
+ json_object *error_status = cper_generic_error_status_to_ir(
+ &dev_error->ErrorStatus);
+ json_object_object_add(section_ir, "errorStatus", error_status);
+ }
//ID information.
- json_object *id_info = json_object_new_object();
- json_object_object_add(
- id_info, "vendorID",
- json_object_new_uint64(dev_error->IdInfo.VendorId));
- json_object_object_add(
- id_info, "deviceID",
- json_object_new_uint64(dev_error->IdInfo.DeviceId));
- json_object_object_add(
- id_info, "classCode",
- json_object_new_uint64(dev_error->IdInfo.ClassCode));
- json_object_object_add(
- id_info, "functionNumber",
- json_object_new_uint64(dev_error->IdInfo.FunctionNumber));
- json_object_object_add(
- id_info, "deviceNumber",
- json_object_new_uint64(dev_error->IdInfo.DeviceNumber));
- json_object_object_add(
- id_info, "busNumber",
- json_object_new_uint64(dev_error->IdInfo.BusNumber));
- json_object_object_add(
- id_info, "segmentNumber",
- json_object_new_uint64(dev_error->IdInfo.SegmentNumber));
- json_object_object_add(section_ir, "idInfo", id_info);
+ if (isvalid_prop_to_ir(&ui64Type, 1)) {
+ json_object *id_info = json_object_new_object();
+ json_object_object_add(
+ id_info, "vendorID",
+ json_object_new_uint64(dev_error->IdInfo.VendorId));
+ json_object_object_add(
+ id_info, "deviceID",
+ json_object_new_uint64(dev_error->IdInfo.DeviceId));
+ json_object_object_add(
+ id_info, "classCode",
+ json_object_new_uint64(dev_error->IdInfo.ClassCode));
+ json_object_object_add(
+ id_info, "functionNumber",
+ json_object_new_uint64(
+ dev_error->IdInfo.FunctionNumber));
+ json_object_object_add(
+ id_info, "deviceNumber",
+ json_object_new_uint64(dev_error->IdInfo.DeviceNumber));
+ json_object_object_add(
+ id_info, "busNumber",
+ json_object_new_uint64(dev_error->IdInfo.BusNumber));
+ json_object_object_add(
+ id_info, "segmentNumber",
+ json_object_new_uint64(
+ dev_error->IdInfo.SegmentNumber));
+ json_object_object_add(section_ir, "idInfo", id_info);
+ }
//Number of following register data pairs.
- json_object_object_add(section_ir, "memoryNumber",
- json_object_new_uint64(dev_error->MemoryNumber));
- json_object_object_add(section_ir, "ioNumber",
- json_object_new_uint64(dev_error->IoNumber));
- int num_data_pairs = dev_error->MemoryNumber + dev_error->IoNumber;
-
- //Register pairs, described by the numeric fields.
- //The actual "pairs" of address and data aren't necessarily 8 bytes long, so can't assume the contents.
- //Hence the naming "firstHalf" and "secondHalf" rather than "address" and "data".
- json_object *register_data_pair_array = json_object_new_array();
- UINT64 *cur_pos = (UINT64 *)(dev_error + 1);
- for (int i = 0; i < num_data_pairs; i++) {
- //Save current pair to array.
- json_object *register_data_pair = json_object_new_object();
- json_object_object_add(register_data_pair, "firstHalf",
- json_object_new_uint64(*cur_pos));
- json_object_object_add(register_data_pair, "secondHalf",
- json_object_new_uint64(*(cur_pos + 1)));
- json_object_array_add(register_data_pair_array,
- register_data_pair);
-
- //Move to next pair.
- cur_pos += 2;
+ if (isvalid_prop_to_ir(&ui64Type, 2)) {
+ json_object_object_add(
+ section_ir, "memoryNumber",
+ json_object_new_uint64(dev_error->MemoryNumber));
}
- json_object_object_add(section_ir, "registerDataPairs",
- register_data_pair_array);
+ if (isvalid_prop_to_ir(&ui64Type, 3)) {
+ json_object_object_add(
+ section_ir, "ioNumber",
+ json_object_new_uint64(dev_error->IoNumber));
+ }
+
+ if (isvalid_prop_to_ir(&ui64Type, 4)) {
+ int num_data_pairs =
+ dev_error->MemoryNumber + dev_error->IoNumber;
+
+ //Register pairs, described by the numeric fields.
+ //The actual "pairs" of address and data aren't necessarily 8 bytes long, so can't assume the contents.
+ //Hence the naming "firstHalf" and "secondHalf" rather than "address" and "data".
+ json_object *register_data_pair_array = json_object_new_array();
+ UINT64 *cur_pos = (UINT64 *)(dev_error + 1);
+ for (int i = 0; i < num_data_pairs; i++) {
+ //Save current pair to array.
+ json_object *register_data_pair =
+ json_object_new_object();
+ json_object_object_add(
+ register_data_pair, "firstHalf",
+ json_object_new_uint64(*cur_pos));
+ json_object_object_add(
+ register_data_pair, "secondHalf",
+ json_object_new_uint64(*(cur_pos + 1)));
+ json_object_array_add(register_data_pair_array,
+ register_data_pair);
+
+ //Move to next pair.
+ cur_pos += 2;
+ }
+ json_object_object_add(section_ir, "registerDataPairs",
+ register_data_pair_array);
+ }
return section_ir;
}
@@ -90,37 +108,53 @@
1, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA));
//Validation bits.
- section_cper->ValidFields = ir_to_bitfield(
- json_object_object_get(section, "validationBits"), 5,
- PCI_DEV_ERROR_VALID_BITFIELD_NAMES);
+ ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
+ struct json_object *obj = NULL;
//Error status.
- ir_generic_error_status_to_cper(json_object_object_get(section,
- "errorStatus"),
- §ion_cper->ErrorStatus);
+ if (json_object_object_get_ex(section, "errorStatus", &obj)) {
+ ir_generic_error_status_to_cper(obj,
+ §ion_cper->ErrorStatus);
+ add_to_valid_bitfield(&ui64Type, 0);
+ }
//Device ID information.
- json_object *id_info = json_object_object_get(section, "idInfo");
- section_cper->IdInfo.VendorId = json_object_get_uint64(
- json_object_object_get(id_info, "vendorID"));
- section_cper->IdInfo.DeviceId = json_object_get_uint64(
- json_object_object_get(id_info, "deviceID"));
- section_cper->IdInfo.ClassCode = json_object_get_uint64(
- json_object_object_get(id_info, "classCode"));
- section_cper->IdInfo.FunctionNumber = json_object_get_uint64(
- json_object_object_get(id_info, "functionNumber"));
- section_cper->IdInfo.DeviceNumber = json_object_get_uint64(
- json_object_object_get(id_info, "deviceNumber"));
- section_cper->IdInfo.BusNumber = json_object_get_uint64(
- json_object_object_get(id_info, "busNumber"));
- section_cper->IdInfo.SegmentNumber = json_object_get_uint64(
- json_object_object_get(id_info, "segmentNumber"));
+ if (json_object_object_get_ex(section, "idInfo", &obj)) {
+ json_object *id_info = obj;
+ section_cper->IdInfo.VendorId = json_object_get_uint64(
+ json_object_object_get(id_info, "vendorID"));
+ section_cper->IdInfo.DeviceId = json_object_get_uint64(
+ json_object_object_get(id_info, "deviceID"));
+ section_cper->IdInfo.ClassCode = json_object_get_uint64(
+ json_object_object_get(id_info, "classCode"));
+ section_cper->IdInfo.FunctionNumber = json_object_get_uint64(
+ json_object_object_get(id_info, "functionNumber"));
+ section_cper->IdInfo.DeviceNumber = json_object_get_uint64(
+ json_object_object_get(id_info, "deviceNumber"));
+ section_cper->IdInfo.BusNumber = json_object_get_uint64(
+ json_object_object_get(id_info, "busNumber"));
+ section_cper->IdInfo.SegmentNumber = json_object_get_uint64(
+ json_object_object_get(id_info, "segmentNumber"));
+ add_to_valid_bitfield(&ui64Type, 1);
+ }
//Amount of following data pairs.
- section_cper->MemoryNumber = (UINT32)json_object_get_uint64(
- json_object_object_get(section, "memoryNumber"));
- section_cper->IoNumber = (UINT32)json_object_get_uint64(
- json_object_object_get(section, "ioNumber"));
+ if (json_object_object_get_ex(section, "memoryNumber", &obj)) {
+ section_cper->MemoryNumber =
+ (UINT32)json_object_get_uint64(obj);
+ add_to_valid_bitfield(&ui64Type, 2);
+ }
+ if (json_object_object_get_ex(section, "ioNumber", &obj)) {
+ section_cper->IoNumber = (UINT32)json_object_get_uint64(obj);
+ add_to_valid_bitfield(&ui64Type, 3);
+ }
+ json_object *register_pairs = NULL;
+ if (json_object_object_get_ex(section, "registerDataPairs", &obj)) {
+ register_pairs = obj;
+ add_to_valid_bitfield(&ui64Type, 4);
+ }
+
+ section_cper->ValidFields = ui64Type.value.ui64;
//Write header out to stream, free it.
fwrite(section_cper, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA), 1, out);
@@ -128,23 +162,23 @@
free(section_cper);
//Begin writing register pairs.
- 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++) {
- //Get the pair array item out.
- json_object *register_pair =
- json_object_array_get_idx(register_pairs, i);
+ if (register_pairs != NULL) {
+ int num_pairs = json_object_array_length(register_pairs);
+ for (int i = 0; i < num_pairs; i++) {
+ //Get the pair array item out.
+ json_object *register_pair =
+ json_object_array_get_idx(register_pairs, i);
- //Create the pair array.
- UINT64 pair[2];
- pair[0] = json_object_get_uint64(
- json_object_object_get(register_pair, "firstHalf"));
- pair[1] = json_object_get_uint64(
- json_object_object_get(register_pair, "secondHalf"));
+ //Create the pair array.
+ UINT64 pair[2];
+ pair[0] = json_object_get_uint64(json_object_object_get(
+ register_pair, "firstHalf"));
+ pair[1] = json_object_get_uint64(json_object_object_get(
+ register_pair, "secondHalf"));
- //Push to stream.
- fwrite(pair, sizeof(UINT64), 2, out);
- fflush(out);
+ //Push to stream.
+ fwrite(pair, sizeof(UINT64), 2, out);
+ fflush(out);
+ }
}
}