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 693c43f743SLawrence Tang //Converts a single integer value to an object containing a value, and a readable name if possible. 703c878352SLawrence Tang json_object* integer_to_readable_pair(UINT64 value, int len, int keys[], const char* values[], const char* default_value) 713c43f743SLawrence Tang { 723c43f743SLawrence Tang json_object* result = json_object_new_object(); 733c878352SLawrence Tang json_object_object_add(result, "value", json_object_new_uint64(value)); 743c43f743SLawrence Tang 753c43f743SLawrence Tang //Search for human readable name, add. 76794312c8SLawrence Tang const char* name = default_value; 773c43f743SLawrence Tang for (int i=0; i<len; i++) 783c43f743SLawrence Tang { 793c43f743SLawrence Tang if (keys[i] == value) 803c43f743SLawrence Tang name = values[i]; 813c43f743SLawrence Tang } 823c43f743SLawrence Tang 833c43f743SLawrence Tang json_object_object_add(result, "name", json_object_new_string(name)); 843c43f743SLawrence Tang return result; 853c43f743SLawrence Tang } 863c43f743SLawrence Tang 877f21db6cSLawrence Tang //Converts a single integer value to an object containing a value, readable name and description if possible. 887f21db6cSLawrence Tang json_object* integer_to_readable_pair_with_desc(int value, int len, int keys[], const char* values[], 897f21db6cSLawrence Tang const char* descriptions[], const char* default_value) 907f21db6cSLawrence Tang { 917f21db6cSLawrence Tang json_object* result = json_object_new_object(); 927f21db6cSLawrence Tang json_object_object_add(result, "value", json_object_new_int(value)); 937f21db6cSLawrence Tang 947f21db6cSLawrence Tang //Search for human readable name, add. 957f21db6cSLawrence Tang const char* name = default_value; 967f21db6cSLawrence Tang for (int i=0; i<len; i++) 977f21db6cSLawrence Tang { 987f21db6cSLawrence Tang if (keys[i] == value) 997f21db6cSLawrence Tang { 1007f21db6cSLawrence Tang name = values[i]; 1017f21db6cSLawrence Tang json_object_object_add(result, "description", json_object_new_string(descriptions[i])); 1027f21db6cSLawrence Tang } 1037f21db6cSLawrence Tang } 1047f21db6cSLawrence Tang 1057f21db6cSLawrence Tang json_object_object_add(result, "name", json_object_new_string(name)); 1067f21db6cSLawrence Tang return result; 1077f21db6cSLawrence Tang } 1087f21db6cSLawrence Tang 109*b44314c7SLawrence Tang //Returns a single UINT64 value from the given readable pair object. 110*b44314c7SLawrence Tang //Assumes the integer value is held in the "value" field. 111*b44314c7SLawrence Tang UINT64 readable_pair_to_integer(json_object* pair) 112*b44314c7SLawrence Tang { 113*b44314c7SLawrence Tang return json_object_get_uint64(json_object_object_get(pair, "value")); 114*b44314c7SLawrence Tang } 115*b44314c7SLawrence Tang 116794312c8SLawrence Tang //Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left. 1173d0e4f24SLawrence Tang json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[]) 118794312c8SLawrence Tang { 119794312c8SLawrence Tang json_object* result = json_object_new_object(); 120794312c8SLawrence Tang for (int i=0; i<num_fields; i++) 121794312c8SLawrence Tang { 1222800cd8eSLawrence Tang json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1)); 123794312c8SLawrence Tang } 124794312c8SLawrence Tang 125794312c8SLawrence Tang return result; 126794312c8SLawrence Tang } 127794312c8SLawrence Tang 128*b44314c7SLawrence Tang //Converts the given IR bitfield into a standard UINT64 bitfield, with fields beginning from bit 0. 129*b44314c7SLawrence Tang UINT64 ir_to_bitfield(json_object* ir, int num_fields, const char* names[]) 130*b44314c7SLawrence Tang { 131*b44314c7SLawrence Tang UINT64 result = 0x0; 132*b44314c7SLawrence Tang for (int i=0; i<num_fields; i++) 133*b44314c7SLawrence Tang { 134*b44314c7SLawrence Tang if (json_object_get_boolean(json_object_object_get(ir, names[i]))) 135*b44314c7SLawrence Tang result |= (0x1 << i); 136*b44314c7SLawrence Tang } 137*b44314c7SLawrence Tang 138*b44314c7SLawrence Tang return result; 139*b44314c7SLawrence Tang } 140*b44314c7SLawrence Tang 141e18aaee9SLawrence Tang //Converts the given UINT64 array into a JSON IR array, given the length. 142e18aaee9SLawrence Tang json_object* uint64_array_to_ir_array(UINT64* array, int len) 143e18aaee9SLawrence Tang { 144e18aaee9SLawrence Tang json_object* array_ir = json_object_new_array(); 145e18aaee9SLawrence Tang for (int i=0; i<len; i++) 146e18aaee9SLawrence Tang json_object_array_add(array_ir, json_object_new_uint64(array[i])); 147e18aaee9SLawrence Tang return array_ir; 148e18aaee9SLawrence Tang } 149794312c8SLawrence Tang 1501b0b00e3SLawrence Tang //Converts a single UINT16 revision number into JSON IR representation. 1511b0b00e3SLawrence Tang json_object* revision_to_ir(UINT16 revision) 1521b0b00e3SLawrence Tang { 1531b0b00e3SLawrence Tang json_object* revision_info = json_object_new_object(); 1541b0b00e3SLawrence Tang json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8)); 1551b0b00e3SLawrence Tang json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF)); 1561b0b00e3SLawrence Tang return revision_info; 1571b0b00e3SLawrence Tang } 1581b0b00e3SLawrence Tang 1591b0b00e3SLawrence Tang //Returns the appropriate string for the given integer severity. 1601b0b00e3SLawrence Tang const char* severity_to_string(UINT8 severity) 1611b0b00e3SLawrence Tang { 1621b0b00e3SLawrence Tang return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown"; 1631b0b00e3SLawrence Tang } 1641b0b00e3SLawrence Tang 165*b44314c7SLawrence Tang //Converts a single EFI timestamp to string, at the given output. 166*b44314c7SLawrence Tang //Output must be at least TIMESTAMP_LENGTH bytes long. 167*b44314c7SLawrence Tang void timestamp_to_string(char* out, EFI_ERROR_TIME_STAMP* timestamp) 168*b44314c7SLawrence Tang { 169*b44314c7SLawrence Tang sprintf(out, "%02d%02d-%02d-%02dT%02d:%02d:%02d.000", 170*b44314c7SLawrence Tang timestamp->Century, 171*b44314c7SLawrence Tang timestamp->Year, 172*b44314c7SLawrence Tang timestamp->Month, 173*b44314c7SLawrence Tang timestamp->Day, 174*b44314c7SLawrence Tang timestamp->Hours, 175*b44314c7SLawrence Tang timestamp->Minutes, 176*b44314c7SLawrence Tang timestamp->Seconds); 177*b44314c7SLawrence Tang } 178*b44314c7SLawrence Tang 179*b44314c7SLawrence Tang //Converts a single timestamp string to an EFI timestamp. 180*b44314c7SLawrence Tang void string_to_timestamp(EFI_ERROR_TIME_STAMP* out, const char* timestamp) 181*b44314c7SLawrence Tang { 182*b44314c7SLawrence Tang sscanf(timestamp, "%02d%02d-%02d-%02dT%02d:%02d:%02d.000", 183*b44314c7SLawrence Tang &out->Century, 184*b44314c7SLawrence Tang &out->Year, 185*b44314c7SLawrence Tang &out->Month, 186*b44314c7SLawrence Tang &out->Day, 187*b44314c7SLawrence Tang &out->Hours, 188*b44314c7SLawrence Tang &out->Minutes, 189*b44314c7SLawrence Tang &out->Seconds); 190*b44314c7SLawrence Tang } 191*b44314c7SLawrence Tang 1921b0b00e3SLawrence Tang //Helper function to convert an EDK EFI GUID into a string for intermediate use. 1931b0b00e3SLawrence Tang void guid_to_string(char* out, EFI_GUID* guid) 1941b0b00e3SLawrence Tang { 1951b0b00e3SLawrence Tang sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 1961b0b00e3SLawrence Tang guid->Data1, 1971b0b00e3SLawrence Tang guid->Data2, 1981b0b00e3SLawrence Tang guid->Data3, 1991b0b00e3SLawrence Tang guid->Data4[0], 2001b0b00e3SLawrence Tang guid->Data4[1], 2011b0b00e3SLawrence Tang guid->Data4[2], 2021b0b00e3SLawrence Tang guid->Data4[3], 2031b0b00e3SLawrence Tang guid->Data4[4], 2041b0b00e3SLawrence Tang guid->Data4[5], 2051b0b00e3SLawrence Tang guid->Data4[6], 2061b0b00e3SLawrence Tang guid->Data4[7]); 2071b0b00e3SLawrence Tang } 2081b0b00e3SLawrence Tang 209*b44314c7SLawrence Tang //Helper function to convert a string into an EDK EFI GUID. 210*b44314c7SLawrence Tang void string_to_guid(EFI_GUID* out, const char* guid) 211*b44314c7SLawrence Tang { 212*b44314c7SLawrence Tang sscanf(guid, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 213*b44314c7SLawrence Tang &out->Data1, 214*b44314c7SLawrence Tang &out->Data2, 215*b44314c7SLawrence Tang &out->Data3, 216*b44314c7SLawrence Tang out->Data4, 217*b44314c7SLawrence Tang out->Data4 + 1, 218*b44314c7SLawrence Tang out->Data4 + 2, 219*b44314c7SLawrence Tang out->Data4 + 3, 220*b44314c7SLawrence Tang out->Data4 + 4, 221*b44314c7SLawrence Tang out->Data4 + 5, 222*b44314c7SLawrence Tang out->Data4 + 6, 223*b44314c7SLawrence Tang out->Data4 + 7); 224*b44314c7SLawrence Tang } 225*b44314c7SLawrence Tang 2261b0b00e3SLawrence Tang //Returns one if two EFI GUIDs are equal, zero otherwise. 2271b0b00e3SLawrence Tang int guid_equal(EFI_GUID* a, EFI_GUID* b) 2281b0b00e3SLawrence Tang { 2291b0b00e3SLawrence Tang //Check top base 3 components. 2301b0b00e3SLawrence Tang if (a->Data1 != b->Data1 2311b0b00e3SLawrence Tang || a->Data2 != b->Data2 2321b0b00e3SLawrence Tang || a->Data3 != b->Data3) 2331b0b00e3SLawrence Tang { 2341b0b00e3SLawrence Tang return 0; 2351b0b00e3SLawrence Tang } 2361b0b00e3SLawrence Tang 2371b0b00e3SLawrence Tang //Check Data4 array for equality. 2381b0b00e3SLawrence Tang for (int i=0; i<8; i++) 2391b0b00e3SLawrence Tang { 2401b0b00e3SLawrence Tang if (a->Data4[i] != b->Data4[i]) 2411b0b00e3SLawrence Tang return 0; 2421b0b00e3SLawrence Tang } 2431b0b00e3SLawrence Tang 2441b0b00e3SLawrence Tang return 1; 2451b0b00e3SLawrence Tang } 2464dbe3d72SLawrence Tang 2474dbe3d72SLawrence Tang //Converts the given BCD byte to a standard integer. 2484dbe3d72SLawrence Tang int bcd_to_int(UINT8 bcd) 2494dbe3d72SLawrence Tang { 2504dbe3d72SLawrence Tang return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F); 2514dbe3d72SLawrence Tang }