1 /** 2 * Describes functions for converting processor-generic CPER sections from binary and JSON format 3 * into an intermediate format. 4 * 5 * Author: Lawrence.Tang@arm.com 6 **/ 7 8 #include <stdio.h> 9 #include <string.h> 10 #include <json.h> 11 #include <libcper/Cper.h> 12 #include <libcper/cper-utils.h> 13 #include <libcper/sections/cper-section-generic.h> 14 15 //Converts the given processor-generic CPER section into JSON IR. cper_section_generic_to_ir(void * section)16 json_object *cper_section_generic_to_ir(void *section) 17 { 18 EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic = 19 (EFI_PROCESSOR_GENERIC_ERROR_DATA *)section; 20 json_object *section_ir = json_object_new_object(); 21 22 ValidationTypes ui64Type = { 23 UINT_64T, .value.ui64 = section_generic->ValidFields 24 }; 25 26 if (isvalid_prop_to_ir(&ui64Type, 0)) { 27 //Processor type, with human readable name if possible. 28 json_object *processor_type = integer_to_readable_pair( 29 section_generic->Type, 30 sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int), 31 GENERIC_PROC_TYPES_KEYS, GENERIC_PROC_TYPES_VALUES, 32 "Unknown (Reserved)"); 33 json_object_object_add(section_ir, "processorType", 34 processor_type); 35 } 36 37 if (isvalid_prop_to_ir(&ui64Type, 1)) { 38 //Processor ISA, with human readable name if possible. 39 json_object *processor_isa = integer_to_readable_pair( 40 section_generic->Isa, 41 sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int), 42 GENERIC_ISA_TYPES_KEYS, GENERIC_ISA_TYPES_VALUES, 43 "Unknown (Reserved)"); 44 json_object_object_add(section_ir, "processorISA", 45 processor_isa); 46 } 47 48 if (isvalid_prop_to_ir(&ui64Type, 2)) { 49 //Processor error type, with human readable name if possible. 50 json_object *processor_error_type = integer_to_readable_pair( 51 section_generic->ErrorType, 52 sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int), 53 GENERIC_ERROR_TYPES_KEYS, GENERIC_ERROR_TYPES_VALUES, 54 "Unknown (Reserved)"); 55 json_object_object_add(section_ir, "errorType", 56 processor_error_type); 57 } 58 59 if (isvalid_prop_to_ir(&ui64Type, 3)) { 60 //The operation performed, with a human readable name if possible. 61 json_object *operation = integer_to_readable_pair( 62 section_generic->Operation, 63 sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int), 64 GENERIC_OPERATION_TYPES_KEYS, 65 GENERIC_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 66 json_object_object_add(section_ir, "operation", operation); 67 } 68 69 if (isvalid_prop_to_ir(&ui64Type, 4)) { 70 //Flags, additional information about the error. 71 json_object *flags = 72 bitfield_to_ir(section_generic->Flags, 4, 73 GENERIC_FLAGS_BITFIELD_NAMES); 74 json_object_object_add(section_ir, "flags", flags); 75 } 76 77 if (isvalid_prop_to_ir(&ui64Type, 5)) { 78 //The level of the error. 79 json_object_object_add( 80 section_ir, "level", 81 json_object_new_int(section_generic->Level)); 82 } 83 84 if (isvalid_prop_to_ir(&ui64Type, 6)) { 85 //CPU version information. 86 json_object_object_add( 87 section_ir, "cpuVersionInfo", 88 json_object_new_uint64(section_generic->VersionInfo)); 89 } 90 91 if (isvalid_prop_to_ir(&ui64Type, 7)) { 92 //CPU brand string. May not exist if on ARM. 93 json_object_object_add( 94 section_ir, "cpuBrandString", 95 json_object_new_string(section_generic->BrandString)); 96 } 97 98 if (isvalid_prop_to_ir(&ui64Type, 8)) { 99 //Remaining 64-bit fields. 100 json_object_object_add( 101 section_ir, "processorID", 102 json_object_new_uint64(section_generic->ApicId)); 103 } 104 105 if (isvalid_prop_to_ir(&ui64Type, 9)) { 106 json_object_object_add( 107 section_ir, "targetAddress", 108 json_object_new_uint64(section_generic->TargetAddr)); 109 } 110 111 if (isvalid_prop_to_ir(&ui64Type, 10)) { 112 json_object_object_add( 113 section_ir, "requestorID", 114 json_object_new_uint64(section_generic->RequestorId)); 115 } 116 117 if (isvalid_prop_to_ir(&ui64Type, 11)) { 118 json_object_object_add( 119 section_ir, "responderID", 120 json_object_new_uint64(section_generic->ResponderId)); 121 } 122 123 if (isvalid_prop_to_ir(&ui64Type, 12)) { 124 json_object_object_add( 125 section_ir, "instructionIP", 126 json_object_new_uint64(section_generic->InstructionIP)); 127 } 128 129 return section_ir; 130 } 131 132 //Converts the given CPER-JSON processor-generic error section into CPER binary, 133 //outputting to the provided stream. ir_section_generic_to_cper(json_object * section,FILE * out)134 void ir_section_generic_to_cper(json_object *section, FILE *out) 135 { 136 EFI_PROCESSOR_GENERIC_ERROR_DATA *section_cper = 137 (EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc( 138 1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA)); 139 140 //Validation bits. 141 //Remove 142 // section_cper->ValidFields = ir_to_bitfield( 143 // json_object_object_get(section, "validationBits"), 13, 144 // GENERIC_VALIDATION_BITFIELD_NAMES); 145 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; 146 struct json_object *obj = NULL; 147 //Various name/value pair fields. 148 if (json_object_object_get_ex(section, "processorType", &obj)) { 149 section_cper->Type = (UINT8)readable_pair_to_integer(obj); 150 add_to_valid_bitfield(&ui64Type, 0); 151 } 152 if (json_object_object_get_ex(section, "processorISA", &obj)) { 153 section_cper->Isa = (UINT8)readable_pair_to_integer(obj); 154 add_to_valid_bitfield(&ui64Type, 1); 155 } 156 if (json_object_object_get_ex(section, "errorType", &obj)) { 157 section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj); 158 add_to_valid_bitfield(&ui64Type, 2); 159 } 160 if (json_object_object_get_ex(section, "operation", &obj)) { 161 section_cper->Operation = (UINT8)readable_pair_to_integer(obj); 162 add_to_valid_bitfield(&ui64Type, 3); 163 } 164 //Flags. 165 if (json_object_object_get_ex(section, "flags", &obj)) { 166 section_cper->Flags = (UINT8)ir_to_bitfield( 167 obj, 4, GENERIC_FLAGS_BITFIELD_NAMES); 168 add_to_valid_bitfield(&ui64Type, 4); 169 } 170 171 //Various numeric/string fields. 172 if (json_object_object_get_ex(section, "level", &obj)) { 173 section_cper->Level = (UINT8)json_object_get_int(obj); 174 add_to_valid_bitfield(&ui64Type, 5); 175 } 176 if (json_object_object_get_ex(section, "cpuVersionInfo", &obj)) { 177 section_cper->VersionInfo = json_object_get_uint64(obj); 178 add_to_valid_bitfield(&ui64Type, 6); 179 } 180 if (json_object_object_get_ex(section, "processorID", &obj)) { 181 section_cper->ApicId = json_object_get_uint64(obj); 182 add_to_valid_bitfield(&ui64Type, 8); 183 } 184 if (json_object_object_get_ex(section, "targetAddress", &obj)) { 185 section_cper->TargetAddr = json_object_get_uint64(obj); 186 add_to_valid_bitfield(&ui64Type, 9); 187 } 188 if (json_object_object_get_ex(section, "requestorID", &obj)) { 189 section_cper->RequestorId = json_object_get_uint64(obj); 190 add_to_valid_bitfield(&ui64Type, 10); 191 } 192 if (json_object_object_get_ex(section, "responderID", &obj)) { 193 section_cper->ResponderId = json_object_get_uint64(obj); 194 add_to_valid_bitfield(&ui64Type, 11); 195 } 196 if (json_object_object_get_ex(section, "instructionIP", &obj)) { 197 section_cper->InstructionIP = json_object_get_uint64(obj); 198 add_to_valid_bitfield(&ui64Type, 12); 199 } 200 201 //CPU brand string. 202 if (json_object_object_get_ex(section, "cpuBrandString", &obj)) { 203 const char *brand_string = json_object_get_string(obj); 204 if (brand_string != NULL) { 205 strncpy(section_cper->BrandString, brand_string, 206 sizeof(section_cper->BrandString) - 1); 207 section_cper 208 ->BrandString[sizeof(section_cper->BrandString) - 209 1] = '\0'; 210 } 211 add_to_valid_bitfield(&ui64Type, 7); 212 } 213 section_cper->ValidFields = ui64Type.value.ui64; 214 215 //Write & flush out to file, free memory. 216 fwrite(section_cper, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA), 1, out); 217 fflush(out); 218 free(section_cper); 219 } 220