11b0b00e3SLawrence Tang /** 21b0b00e3SLawrence Tang * Describes utility functions for parsing CPER into JSON IR. 31b0b00e3SLawrence Tang * 41b0b00e3SLawrence Tang * Author: Lawrence.Tang@arm.com 51b0b00e3SLawrence Tang **/ 61b0b00e3SLawrence Tang 71b0b00e3SLawrence Tang #include <stdio.h> 81b0b00e3SLawrence Tang #include "json.h" 91b0b00e3SLawrence Tang #include "edk/Cper.h" 101b0b00e3SLawrence Tang #include "cper-utils.h" 111b0b00e3SLawrence Tang 121b0b00e3SLawrence Tang //The available severity types for CPER. 131b0b00e3SLawrence Tang const char* CPER_SEVERITY_TYPES[4] = {"Recoverable", "Fatal", "Corrected", "Informational"}; 141b0b00e3SLawrence Tang 15a0865e38SLawrence Tang //Converts the given generic CPER error status to JSON IR. 16a0865e38SLawrence Tang json_object* cper_generic_error_status_to_ir(EFI_GENERIC_ERROR_STATUS* error_status) 17a0865e38SLawrence Tang { 18a0865e38SLawrence Tang json_object* error_status_ir = json_object_new_object(); 19a0865e38SLawrence Tang 20a0865e38SLawrence Tang //Error type. 21a0865e38SLawrence Tang json_object_object_add(error_status_ir, "errorType", integer_to_readable_pair_with_desc(error_status->Type, 18, 22a0865e38SLawrence Tang CPER_GENERIC_ERROR_TYPES_KEYS, 23a0865e38SLawrence Tang CPER_GENERIC_ERROR_TYPES_VALUES, 24a0865e38SLawrence Tang CPER_GENERIC_ERROR_TYPES_DESCRIPTIONS, 25a0865e38SLawrence Tang "Unknown (Reserved)")); 26a0865e38SLawrence Tang 27a0865e38SLawrence Tang //Boolean bit fields. 28a0865e38SLawrence Tang json_object_object_add(error_status_ir, "addressSignal", json_object_new_boolean(error_status->AddressSignal)); 29a0865e38SLawrence Tang json_object_object_add(error_status_ir, "controlSignal", json_object_new_boolean(error_status->ControlSignal)); 30a0865e38SLawrence Tang json_object_object_add(error_status_ir, "dataSignal", json_object_new_boolean(error_status->DataSignal)); 31a0865e38SLawrence Tang json_object_object_add(error_status_ir, "detectedByResponder", json_object_new_boolean(error_status->DetectedByResponder)); 32a0865e38SLawrence Tang json_object_object_add(error_status_ir, "detectedByRequester", json_object_new_boolean(error_status->DetectedByRequester)); 33a0865e38SLawrence Tang json_object_object_add(error_status_ir, "firstError", json_object_new_boolean(error_status->FirstError)); 34583cdeeeSLawrence Tang json_object_object_add(error_status_ir, "overflowDroppedLogs", json_object_new_boolean(error_status->OverflowNotLogged)); 35a0865e38SLawrence Tang 36a0865e38SLawrence Tang return error_status_ir; 37a0865e38SLawrence Tang } 38a0865e38SLawrence Tang 397f21db6cSLawrence Tang //Converts a single uniform struct of UINT64s into intermediate JSON IR format, given names for each field in byte order. 407f21db6cSLawrence Tang json_object* uniform_struct64_to_ir(UINT64* start, int len, const char* names[]) 417f21db6cSLawrence Tang { 427f21db6cSLawrence Tang json_object* result = json_object_new_object(); 437f21db6cSLawrence Tang 447f21db6cSLawrence Tang UINT64* cur = start; 457f21db6cSLawrence Tang for (int i=0; i<len; i++) 467f21db6cSLawrence Tang { 477f21db6cSLawrence Tang json_object_object_add(result, names[i], json_object_new_uint64(*cur)); 487f21db6cSLawrence Tang cur++; 497f21db6cSLawrence Tang } 507f21db6cSLawrence Tang 517f21db6cSLawrence Tang return result; 527f21db6cSLawrence Tang } 537f21db6cSLawrence Tang 547f21db6cSLawrence Tang //Converts a single uniform struct of UINT32s into intermediate JSON IR format, given names for each field in byte order. 557f21db6cSLawrence Tang json_object* uniform_struct_to_ir(UINT32* start, int len, const char* names[]) 567f21db6cSLawrence Tang { 577f21db6cSLawrence Tang json_object* result = json_object_new_object(); 587f21db6cSLawrence Tang 597f21db6cSLawrence Tang UINT32* cur = start; 607f21db6cSLawrence Tang for (int i=0; i<len; i++) 617f21db6cSLawrence Tang { 627f21db6cSLawrence Tang json_object_object_add(result, names[i], json_object_new_uint64(*cur)); 637f21db6cSLawrence Tang cur++; 647f21db6cSLawrence Tang } 657f21db6cSLawrence Tang 667f21db6cSLawrence Tang return result; 677f21db6cSLawrence Tang } 687f21db6cSLawrence Tang 69*71570a2aSLawrence Tang //Converts a single object containing UINT32s into a uniform struct. 70*71570a2aSLawrence Tang void ir_to_uniform_struct64(json_object* ir, UINT64* start, int len, const char* names[]) 71*71570a2aSLawrence Tang { 72*71570a2aSLawrence Tang UINT64* cur = start; 73*71570a2aSLawrence Tang for (int i=0; i<len; i++) 74*71570a2aSLawrence Tang { 75*71570a2aSLawrence Tang *cur = json_object_get_uint64(json_object_object_get(ir, names[i])); 76*71570a2aSLawrence Tang cur++; 77*71570a2aSLawrence Tang } 78*71570a2aSLawrence Tang } 79*71570a2aSLawrence Tang 80*71570a2aSLawrence Tang //Converts a single object containing UINT32s into a uniform struct. 81*71570a2aSLawrence Tang void ir_to_uniform_struct(json_object* ir, UINT32* start, int len, const char* names[]) 82*71570a2aSLawrence Tang { 83*71570a2aSLawrence Tang UINT32* cur = start; 84*71570a2aSLawrence Tang for (int i=0; i<len; i++) 85*71570a2aSLawrence Tang { 86*71570a2aSLawrence Tang *cur = (UINT32)json_object_get_uint64(json_object_object_get(ir, names[i])); 87*71570a2aSLawrence Tang cur++; 88*71570a2aSLawrence Tang } 89*71570a2aSLawrence Tang } 90*71570a2aSLawrence Tang 913c43f743SLawrence Tang //Converts a single integer value to an object containing a value, and a readable name if possible. 923c878352SLawrence Tang json_object* integer_to_readable_pair(UINT64 value, int len, int keys[], const char* values[], const char* default_value) 933c43f743SLawrence Tang { 943c43f743SLawrence Tang json_object* result = json_object_new_object(); 953c878352SLawrence Tang json_object_object_add(result, "value", json_object_new_uint64(value)); 963c43f743SLawrence Tang 973c43f743SLawrence Tang //Search for human readable name, add. 98794312c8SLawrence Tang const char* name = default_value; 993c43f743SLawrence Tang for (int i=0; i<len; i++) 1003c43f743SLawrence Tang { 1013c43f743SLawrence Tang if (keys[i] == value) 1023c43f743SLawrence Tang name = values[i]; 1033c43f743SLawrence Tang } 1043c43f743SLawrence Tang 1053c43f743SLawrence Tang json_object_object_add(result, "name", json_object_new_string(name)); 1063c43f743SLawrence Tang return result; 1073c43f743SLawrence Tang } 1083c43f743SLawrence Tang 1097f21db6cSLawrence Tang //Converts a single integer value to an object containing a value, readable name and description if possible. 1107f21db6cSLawrence Tang json_object* integer_to_readable_pair_with_desc(int value, int len, int keys[], const char* values[], 1117f21db6cSLawrence Tang const char* descriptions[], const char* default_value) 1127f21db6cSLawrence Tang { 1137f21db6cSLawrence Tang json_object* result = json_object_new_object(); 1147f21db6cSLawrence Tang json_object_object_add(result, "value", json_object_new_int(value)); 1157f21db6cSLawrence Tang 1167f21db6cSLawrence Tang //Search for human readable name, add. 1177f21db6cSLawrence Tang const char* name = default_value; 1187f21db6cSLawrence Tang for (int i=0; i<len; i++) 1197f21db6cSLawrence Tang { 1207f21db6cSLawrence Tang if (keys[i] == value) 1217f21db6cSLawrence Tang { 1227f21db6cSLawrence Tang name = values[i]; 1237f21db6cSLawrence Tang json_object_object_add(result, "description", json_object_new_string(descriptions[i])); 1247f21db6cSLawrence Tang } 1257f21db6cSLawrence Tang } 1267f21db6cSLawrence Tang 1277f21db6cSLawrence Tang json_object_object_add(result, "name", json_object_new_string(name)); 1287f21db6cSLawrence Tang return result; 1297f21db6cSLawrence Tang } 1307f21db6cSLawrence Tang 131b44314c7SLawrence Tang //Returns a single UINT64 value from the given readable pair object. 132b44314c7SLawrence Tang //Assumes the integer value is held in the "value" field. 133b44314c7SLawrence Tang UINT64 readable_pair_to_integer(json_object* pair) 134b44314c7SLawrence Tang { 135b44314c7SLawrence Tang return json_object_get_uint64(json_object_object_get(pair, "value")); 136b44314c7SLawrence Tang } 137b44314c7SLawrence Tang 138794312c8SLawrence Tang //Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left. 1393d0e4f24SLawrence Tang json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[]) 140794312c8SLawrence Tang { 141794312c8SLawrence Tang json_object* result = json_object_new_object(); 142794312c8SLawrence Tang for (int i=0; i<num_fields; i++) 143794312c8SLawrence Tang { 1442800cd8eSLawrence Tang json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1)); 145794312c8SLawrence Tang } 146794312c8SLawrence Tang 147794312c8SLawrence Tang return result; 148794312c8SLawrence Tang } 149794312c8SLawrence Tang 150b44314c7SLawrence Tang //Converts the given IR bitfield into a standard UINT64 bitfield, with fields beginning from bit 0. 151b44314c7SLawrence Tang UINT64 ir_to_bitfield(json_object* ir, int num_fields, const char* names[]) 152b44314c7SLawrence Tang { 153b44314c7SLawrence Tang UINT64 result = 0x0; 154b44314c7SLawrence Tang for (int i=0; i<num_fields; i++) 155b44314c7SLawrence Tang { 156b44314c7SLawrence Tang if (json_object_get_boolean(json_object_object_get(ir, names[i]))) 157b44314c7SLawrence Tang result |= (0x1 << i); 158b44314c7SLawrence Tang } 159b44314c7SLawrence Tang 160b44314c7SLawrence Tang return result; 161b44314c7SLawrence Tang } 162b44314c7SLawrence Tang 163e18aaee9SLawrence Tang //Converts the given UINT64 array into a JSON IR array, given the length. 164e18aaee9SLawrence Tang json_object* uint64_array_to_ir_array(UINT64* array, int len) 165e18aaee9SLawrence Tang { 166e18aaee9SLawrence Tang json_object* array_ir = json_object_new_array(); 167e18aaee9SLawrence Tang for (int i=0; i<len; i++) 168e18aaee9SLawrence Tang json_object_array_add(array_ir, json_object_new_uint64(array[i])); 169e18aaee9SLawrence Tang return array_ir; 170e18aaee9SLawrence Tang } 171794312c8SLawrence Tang 1721b0b00e3SLawrence Tang //Converts a single UINT16 revision number into JSON IR representation. 1731b0b00e3SLawrence Tang json_object* revision_to_ir(UINT16 revision) 1741b0b00e3SLawrence Tang { 1751b0b00e3SLawrence Tang json_object* revision_info = json_object_new_object(); 1761b0b00e3SLawrence Tang json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8)); 1771b0b00e3SLawrence Tang json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF)); 1781b0b00e3SLawrence Tang return revision_info; 1791b0b00e3SLawrence Tang } 1801b0b00e3SLawrence Tang 1811b0b00e3SLawrence Tang //Returns the appropriate string for the given integer severity. 1821b0b00e3SLawrence Tang const char* severity_to_string(UINT8 severity) 1831b0b00e3SLawrence Tang { 1841b0b00e3SLawrence Tang return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown"; 1851b0b00e3SLawrence Tang } 1861b0b00e3SLawrence Tang 187b44314c7SLawrence Tang //Converts a single EFI timestamp to string, at the given output. 188b44314c7SLawrence Tang //Output must be at least TIMESTAMP_LENGTH bytes long. 189b44314c7SLawrence Tang void timestamp_to_string(char* out, EFI_ERROR_TIME_STAMP* timestamp) 190b44314c7SLawrence Tang { 191b44314c7SLawrence Tang sprintf(out, "%02d%02d-%02d-%02dT%02d:%02d:%02d.000", 192b44314c7SLawrence Tang timestamp->Century, 193b44314c7SLawrence Tang timestamp->Year, 194b44314c7SLawrence Tang timestamp->Month, 195b44314c7SLawrence Tang timestamp->Day, 196b44314c7SLawrence Tang timestamp->Hours, 197b44314c7SLawrence Tang timestamp->Minutes, 198b44314c7SLawrence Tang timestamp->Seconds); 199b44314c7SLawrence Tang } 200b44314c7SLawrence Tang 201b44314c7SLawrence Tang //Converts a single timestamp string to an EFI timestamp. 202b44314c7SLawrence Tang void string_to_timestamp(EFI_ERROR_TIME_STAMP* out, const char* timestamp) 203b44314c7SLawrence Tang { 2040cb33793SLawrence Tang //Ignore invalid timestamps. 2050cb33793SLawrence Tang if (timestamp == NULL) 2060cb33793SLawrence Tang return; 2070cb33793SLawrence Tang 2080cb33793SLawrence Tang sscanf(timestamp, "%02hhd%02hhd-%02hhd-%02hhdT%02hhd:%02hhd:%02hhd.000", 209b44314c7SLawrence Tang &out->Century, 210b44314c7SLawrence Tang &out->Year, 211b44314c7SLawrence Tang &out->Month, 212b44314c7SLawrence Tang &out->Day, 213b44314c7SLawrence Tang &out->Hours, 214b44314c7SLawrence Tang &out->Minutes, 215b44314c7SLawrence Tang &out->Seconds); 216b44314c7SLawrence Tang } 217b44314c7SLawrence Tang 2181b0b00e3SLawrence Tang //Helper function to convert an EDK EFI GUID into a string for intermediate use. 2191b0b00e3SLawrence Tang void guid_to_string(char* out, EFI_GUID* guid) 2201b0b00e3SLawrence Tang { 2211b0b00e3SLawrence Tang sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 2221b0b00e3SLawrence Tang guid->Data1, 2231b0b00e3SLawrence Tang guid->Data2, 2241b0b00e3SLawrence Tang guid->Data3, 2251b0b00e3SLawrence Tang guid->Data4[0], 2261b0b00e3SLawrence Tang guid->Data4[1], 2271b0b00e3SLawrence Tang guid->Data4[2], 2281b0b00e3SLawrence Tang guid->Data4[3], 2291b0b00e3SLawrence Tang guid->Data4[4], 2301b0b00e3SLawrence Tang guid->Data4[5], 2311b0b00e3SLawrence Tang guid->Data4[6], 2321b0b00e3SLawrence Tang guid->Data4[7]); 2331b0b00e3SLawrence Tang } 2341b0b00e3SLawrence Tang 235b44314c7SLawrence Tang //Helper function to convert a string into an EDK EFI GUID. 236b44314c7SLawrence Tang void string_to_guid(EFI_GUID* out, const char* guid) 237b44314c7SLawrence Tang { 2380cb33793SLawrence Tang //Ignore invalid GUIDs. 2390cb33793SLawrence Tang if (guid == NULL) 2400cb33793SLawrence Tang return; 2410cb33793SLawrence Tang 2420cb33793SLawrence Tang sscanf(guid, "%08x-%04hx-%04hx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", 243b44314c7SLawrence Tang &out->Data1, 244b44314c7SLawrence Tang &out->Data2, 245b44314c7SLawrence Tang &out->Data3, 246b44314c7SLawrence Tang out->Data4, 247b44314c7SLawrence Tang out->Data4 + 1, 248b44314c7SLawrence Tang out->Data4 + 2, 249b44314c7SLawrence Tang out->Data4 + 3, 250b44314c7SLawrence Tang out->Data4 + 4, 251b44314c7SLawrence Tang out->Data4 + 5, 252b44314c7SLawrence Tang out->Data4 + 6, 253b44314c7SLawrence Tang out->Data4 + 7); 254b44314c7SLawrence Tang } 255b44314c7SLawrence Tang 2561b0b00e3SLawrence Tang //Returns one if two EFI GUIDs are equal, zero otherwise. 2571b0b00e3SLawrence Tang int guid_equal(EFI_GUID* a, EFI_GUID* b) 2581b0b00e3SLawrence Tang { 2591b0b00e3SLawrence Tang //Check top base 3 components. 2601b0b00e3SLawrence Tang if (a->Data1 != b->Data1 2611b0b00e3SLawrence Tang || a->Data2 != b->Data2 2621b0b00e3SLawrence Tang || a->Data3 != b->Data3) 2631b0b00e3SLawrence Tang { 2641b0b00e3SLawrence Tang return 0; 2651b0b00e3SLawrence Tang } 2661b0b00e3SLawrence Tang 2671b0b00e3SLawrence Tang //Check Data4 array for equality. 2681b0b00e3SLawrence Tang for (int i=0; i<8; i++) 2691b0b00e3SLawrence Tang { 2701b0b00e3SLawrence Tang if (a->Data4[i] != b->Data4[i]) 2711b0b00e3SLawrence Tang return 0; 2721b0b00e3SLawrence Tang } 2731b0b00e3SLawrence Tang 2741b0b00e3SLawrence Tang return 1; 2751b0b00e3SLawrence Tang } 2764dbe3d72SLawrence Tang 2774dbe3d72SLawrence Tang //Converts the given BCD byte to a standard integer. 2784dbe3d72SLawrence Tang int bcd_to_int(UINT8 bcd) 2794dbe3d72SLawrence Tang { 2804dbe3d72SLawrence Tang return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F); 2814dbe3d72SLawrence Tang }