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 122 //Converts a single UINT16 revision number into JSON IR representation. 123 json_object* revision_to_ir(UINT16 revision) 124 { 125 json_object* revision_info = json_object_new_object(); 126 json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8)); 127 json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF)); 128 return revision_info; 129 } 130 131 //Returns the appropriate string for the given integer severity. 132 const char* severity_to_string(UINT8 severity) 133 { 134 return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown"; 135 } 136 137 //Helper function to convert an EDK EFI GUID into a string for intermediate use. 138 void guid_to_string(char* out, EFI_GUID* guid) 139 { 140 sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 141 guid->Data1, 142 guid->Data2, 143 guid->Data3, 144 guid->Data4[0], 145 guid->Data4[1], 146 guid->Data4[2], 147 guid->Data4[3], 148 guid->Data4[4], 149 guid->Data4[5], 150 guid->Data4[6], 151 guid->Data4[7]); 152 } 153 154 //Returns one if two EFI GUIDs are equal, zero otherwise. 155 int guid_equal(EFI_GUID* a, EFI_GUID* b) 156 { 157 //Check top base 3 components. 158 if (a->Data1 != b->Data1 159 || a->Data2 != b->Data2 160 || a->Data3 != b->Data3) 161 { 162 return 0; 163 } 164 165 //Check Data4 array for equality. 166 for (int i=0; i<8; i++) 167 { 168 if (a->Data4[i] != b->Data4[i]) 169 return 0; 170 } 171 172 return 1; 173 }