1 /** 2 * Describes utility functions for parsing CPER into JSON IR. 3 * 4 * Author: Lawrence.Tang@arm.com 5 **/ 6 7 #include <stdio.h> 8 #include "json.h" 9 #include "edk/Cper.h" 10 #include "cper-utils.h" 11 12 //The available severity types for CPER. 13 const char* CPER_SEVERITY_TYPES[4] = {"Recoverable", "Fatal", "Corrected", "Informational"}; 14 15 //Converts the given generic CPER error status to JSON IR. 16 json_object* cper_generic_error_status_to_ir(EFI_GENERIC_ERROR_STATUS* error_status) 17 { 18 json_object* error_status_ir = json_object_new_object(); 19 20 //Error type. 21 json_object_object_add(error_status_ir, "errorType", integer_to_readable_pair_with_desc(error_status->Type, 18, 22 CPER_GENERIC_ERROR_TYPES_KEYS, 23 CPER_GENERIC_ERROR_TYPES_VALUES, 24 CPER_GENERIC_ERROR_TYPES_DESCRIPTIONS, 25 "Unknown (Reserved)")); 26 27 //Boolean bit fields. 28 json_object_object_add(error_status_ir, "addressSignal", json_object_new_boolean(error_status->AddressSignal)); 29 json_object_object_add(error_status_ir, "controlSignal", json_object_new_boolean(error_status->ControlSignal)); 30 json_object_object_add(error_status_ir, "dataSignal", json_object_new_boolean(error_status->DataSignal)); 31 json_object_object_add(error_status_ir, "detectedByResponder", json_object_new_boolean(error_status->DetectedByResponder)); 32 json_object_object_add(error_status_ir, "detectedByRequester", json_object_new_boolean(error_status->DetectedByRequester)); 33 json_object_object_add(error_status_ir, "firstError", json_object_new_boolean(error_status->FirstError)); 34 json_object_object_add(error_status_ir, "overflowNotLogged", json_object_new_boolean(error_status->OverflowNotLogged)); 35 36 return error_status_ir; 37 } 38 39 //Converts a single uniform struct of UINT64s into intermediate JSON IR format, given names for each field in byte order. 40 json_object* uniform_struct64_to_ir(UINT64* start, int len, const char* names[]) 41 { 42 json_object* result = json_object_new_object(); 43 44 UINT64* cur = start; 45 for (int i=0; i<len; i++) 46 { 47 json_object_object_add(result, names[i], json_object_new_uint64(*cur)); 48 cur++; 49 } 50 51 return result; 52 } 53 54 //Converts a single uniform struct of UINT32s into intermediate JSON IR format, given names for each field in byte order. 55 json_object* uniform_struct_to_ir(UINT32* start, int len, const char* names[]) 56 { 57 json_object* result = json_object_new_object(); 58 59 UINT32* cur = start; 60 for (int i=0; i<len; i++) 61 { 62 json_object_object_add(result, names[i], json_object_new_uint64(*cur)); 63 cur++; 64 } 65 66 return result; 67 } 68 69 //Converts a single integer value to an object containing a value, and a readable name if possible. 70 json_object* integer_to_readable_pair(int value, int len, int keys[], const char* values[], const char* default_value) 71 { 72 json_object* result = json_object_new_object(); 73 json_object_object_add(result, "value", json_object_new_int(value)); 74 75 //Search for human readable name, add. 76 const char* name = default_value; 77 for (int i=0; i<len; i++) 78 { 79 if (keys[i] == value) 80 name = values[i]; 81 } 82 83 json_object_object_add(result, "name", json_object_new_string(name)); 84 return result; 85 } 86 87 //Converts a single integer value to an object containing a value, readable name and description if possible. 88 json_object* integer_to_readable_pair_with_desc(int value, int len, int keys[], const char* values[], 89 const char* descriptions[], const char* default_value) 90 { 91 json_object* result = json_object_new_object(); 92 json_object_object_add(result, "value", json_object_new_int(value)); 93 94 //Search for human readable name, add. 95 const char* name = default_value; 96 for (int i=0; i<len; i++) 97 { 98 if (keys[i] == value) 99 { 100 name = values[i]; 101 json_object_object_add(result, "description", json_object_new_string(descriptions[i])); 102 } 103 } 104 105 json_object_object_add(result, "name", json_object_new_string(name)); 106 return result; 107 } 108 109 //Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left. 110 json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[]) 111 { 112 json_object* result = json_object_new_object(); 113 for (int i=0; i<num_fields; i++) 114 { 115 json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1)); 116 } 117 118 return result; 119 } 120 121 //Converts the given UINT64 array into a JSON IR array, given the length. 122 json_object* uint64_array_to_ir_array(UINT64* array, int len) 123 { 124 json_object* array_ir = json_object_new_array(); 125 for (int i=0; i<len; i++) 126 json_object_array_add(array_ir, json_object_new_uint64(array[i])); 127 return array_ir; 128 } 129 130 //Converts a single UINT16 revision number into JSON IR representation. 131 json_object* revision_to_ir(UINT16 revision) 132 { 133 json_object* revision_info = json_object_new_object(); 134 json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8)); 135 json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF)); 136 return revision_info; 137 } 138 139 //Returns the appropriate string for the given integer severity. 140 const char* severity_to_string(UINT8 severity) 141 { 142 return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown"; 143 } 144 145 //Helper function to convert an EDK EFI GUID into a string for intermediate use. 146 void guid_to_string(char* out, EFI_GUID* guid) 147 { 148 sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 149 guid->Data1, 150 guid->Data2, 151 guid->Data3, 152 guid->Data4[0], 153 guid->Data4[1], 154 guid->Data4[2], 155 guid->Data4[3], 156 guid->Data4[4], 157 guid->Data4[5], 158 guid->Data4[6], 159 guid->Data4[7]); 160 } 161 162 //Returns one if two EFI GUIDs are equal, zero otherwise. 163 int guid_equal(EFI_GUID* a, EFI_GUID* b) 164 { 165 //Check top base 3 components. 166 if (a->Data1 != b->Data1 167 || a->Data2 != b->Data2 168 || a->Data3 != b->Data3) 169 { 170 return 0; 171 } 172 173 //Check Data4 array for equality. 174 for (int i=0; i<8; i++) 175 { 176 if (a->Data4[i] != b->Data4[i]) 177 return 0; 178 } 179 180 return 1; 181 } 182 183 //Converts the given BCD byte to a standard integer. 184 int bcd_to_int(UINT8 bcd) 185 { 186 return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F); 187 }