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)); 34a0865e38SLawrence Tang json_object_object_add(error_status_ir, "overflowNotLogged", 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. 703c43f743SLawrence Tang json_object* integer_to_readable_pair(int value, int len, int keys[], const char* values[], const char* default_value) 713c43f743SLawrence Tang { 723c43f743SLawrence Tang json_object* result = json_object_new_object(); 733c43f743SLawrence Tang json_object_object_add(result, "value", json_object_new_int(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 109794312c8SLawrence Tang //Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left. 1103d0e4f24SLawrence Tang json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[]) 111794312c8SLawrence Tang { 112794312c8SLawrence Tang json_object* result = json_object_new_object(); 113794312c8SLawrence Tang for (int i=0; i<num_fields; i++) 114794312c8SLawrence Tang { 1152800cd8eSLawrence Tang json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1)); 116794312c8SLawrence Tang } 117794312c8SLawrence Tang 118794312c8SLawrence Tang return result; 119794312c8SLawrence Tang } 120794312c8SLawrence Tang 121794312c8SLawrence Tang 1221b0b00e3SLawrence Tang //Converts a single UINT16 revision number into JSON IR representation. 1231b0b00e3SLawrence Tang json_object* revision_to_ir(UINT16 revision) 1241b0b00e3SLawrence Tang { 1251b0b00e3SLawrence Tang json_object* revision_info = json_object_new_object(); 1261b0b00e3SLawrence Tang json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8)); 1271b0b00e3SLawrence Tang json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF)); 1281b0b00e3SLawrence Tang return revision_info; 1291b0b00e3SLawrence Tang } 1301b0b00e3SLawrence Tang 1311b0b00e3SLawrence Tang //Returns the appropriate string for the given integer severity. 1321b0b00e3SLawrence Tang const char* severity_to_string(UINT8 severity) 1331b0b00e3SLawrence Tang { 1341b0b00e3SLawrence Tang return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown"; 1351b0b00e3SLawrence Tang } 1361b0b00e3SLawrence Tang 1371b0b00e3SLawrence Tang //Helper function to convert an EDK EFI GUID into a string for intermediate use. 1381b0b00e3SLawrence Tang void guid_to_string(char* out, EFI_GUID* guid) 1391b0b00e3SLawrence Tang { 1401b0b00e3SLawrence Tang sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 1411b0b00e3SLawrence Tang guid->Data1, 1421b0b00e3SLawrence Tang guid->Data2, 1431b0b00e3SLawrence Tang guid->Data3, 1441b0b00e3SLawrence Tang guid->Data4[0], 1451b0b00e3SLawrence Tang guid->Data4[1], 1461b0b00e3SLawrence Tang guid->Data4[2], 1471b0b00e3SLawrence Tang guid->Data4[3], 1481b0b00e3SLawrence Tang guid->Data4[4], 1491b0b00e3SLawrence Tang guid->Data4[5], 1501b0b00e3SLawrence Tang guid->Data4[6], 1511b0b00e3SLawrence Tang guid->Data4[7]); 1521b0b00e3SLawrence Tang } 1531b0b00e3SLawrence Tang 1541b0b00e3SLawrence Tang //Returns one if two EFI GUIDs are equal, zero otherwise. 1551b0b00e3SLawrence Tang int guid_equal(EFI_GUID* a, EFI_GUID* b) 1561b0b00e3SLawrence Tang { 1571b0b00e3SLawrence Tang //Check top base 3 components. 1581b0b00e3SLawrence Tang if (a->Data1 != b->Data1 1591b0b00e3SLawrence Tang || a->Data2 != b->Data2 1601b0b00e3SLawrence Tang || a->Data3 != b->Data3) 1611b0b00e3SLawrence Tang { 1621b0b00e3SLawrence Tang return 0; 1631b0b00e3SLawrence Tang } 1641b0b00e3SLawrence Tang 1651b0b00e3SLawrence Tang //Check Data4 array for equality. 1661b0b00e3SLawrence Tang for (int i=0; i<8; i++) 1671b0b00e3SLawrence Tang { 1681b0b00e3SLawrence Tang if (a->Data4[i] != b->Data4[i]) 1691b0b00e3SLawrence Tang return 0; 1701b0b00e3SLawrence Tang } 1711b0b00e3SLawrence Tang 1721b0b00e3SLawrence Tang return 1; 1731b0b00e3SLawrence Tang } 174*4dbe3d72SLawrence Tang 175*4dbe3d72SLawrence Tang //Converts the given BCD byte to a standard integer. 176*4dbe3d72SLawrence Tang int bcd_to_int(UINT8 bcd) 177*4dbe3d72SLawrence Tang { 178*4dbe3d72SLawrence Tang return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F); 179*4dbe3d72SLawrence Tang }