1 /** 2 * Describes functions for converting IA32/x64 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 "json.h" 10 #include "b64.h" 11 #include "../edk/Cper.h" 12 #include "../cper-utils.h" 13 #include "cper-section-ia32x64.h" 14 15 //Private pre-definitions. 16 json_object* cper_ia32x64_processor_error_info_to_ir(EFI_IA32_X64_PROCESS_ERROR_INFO* error_info); 17 json_object* cper_ia32x64_cache_tlb_check_to_ir(EFI_IA32_X64_CACHE_CHECK_INFO* cache_tlb_check); 18 json_object* cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO* bus_check); 19 json_object* cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO* ms_check); 20 json_object* cper_ia32x64_processor_context_info_to_ir(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* context_info, void** cur_pos); 21 json_object* cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE* registers); 22 json_object* cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE* registers); 23 void ir_ia32x64_error_info_to_cper(json_object* error_info, FILE* out); 24 void ir_ia32x64_context_info_to_cper(json_object* context_info, FILE* out); 25 void ir_ia32x64_cache_tlb_check_error_to_cper(json_object* check_info, EFI_IA32_X64_CACHE_CHECK_INFO* check_info_cper); 26 void ir_ia32x64_bus_check_error_to_cper(json_object* check_info, EFI_IA32_X64_BUS_CHECK_INFO* check_info_cper); 27 void ir_ia32x64_ms_check_error_to_cper(json_object* check_info, EFI_IA32_X64_MS_CHECK_INFO* check_info_cper); 28 void ir_ia32x64_ia32_registers_to_cper(json_object* registers, FILE* out); 29 void ir_ia32x64_x64_registers_to_cper(json_object* registers, FILE* out); 30 31 ////////////////// 32 /// CPER TO IR /// 33 ////////////////// 34 35 //Converts the IA32/x64 error section described in the given descriptor into intermediate format. 36 json_object* cper_section_ia32x64_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor) 37 { 38 EFI_IA32_X64_PROCESSOR_ERROR_RECORD* record = (EFI_IA32_X64_PROCESSOR_ERROR_RECORD*)section; 39 json_object* record_ir = json_object_new_object(); 40 41 //Validation bits. 42 json_object* validationBits = json_object_new_object(); 43 json_object_object_add(validationBits, "localAPICIDValid", json_object_new_boolean(record->ValidFields & 0b1)); 44 json_object_object_add(validationBits, "cpuIDInfoValid", json_object_new_boolean((record->ValidFields >> 1) & 0b1)); 45 int processor_error_info_num = (record->ValidFields >> 2) & 0b111111; 46 json_object_object_add(validationBits, "processorErrorInfoNum", json_object_new_int(processor_error_info_num)); 47 int processor_context_info_num = (record->ValidFields >> 8) & 0b111111; 48 json_object_object_add(validationBits, "processorContextInfoNum", json_object_new_int(processor_context_info_num)); 49 json_object_object_add(record_ir, "validationBits", validationBits); 50 51 //APIC ID. 52 json_object_object_add(record_ir, "localAPICID", json_object_new_uint64(record->ApicId)); 53 54 //CPUID information. 55 json_object* cpuid_info_ir = json_object_new_object(); 56 EFI_IA32_X64_CPU_ID* cpuid_info = (EFI_IA32_X64_CPU_ID*)record->CpuIdInfo; 57 json_object_object_add(cpuid_info_ir, "eax", json_object_new_uint64(cpuid_info->Eax)); 58 json_object_object_add(cpuid_info_ir, "ebx", json_object_new_uint64(cpuid_info->Ebx)); 59 json_object_object_add(cpuid_info_ir, "ecx", json_object_new_uint64(cpuid_info->Ecx)); 60 json_object_object_add(cpuid_info_ir, "edx", json_object_new_uint64(cpuid_info->Edx)); 61 json_object_object_add(record_ir, "cpuidInfo", cpuid_info_ir); 62 63 //Processor error information, of the amount described above. 64 EFI_IA32_X64_PROCESS_ERROR_INFO* current_error_info = (EFI_IA32_X64_PROCESS_ERROR_INFO*)(record + 1); 65 json_object* error_info_array = json_object_new_array(); 66 for (int i=0; i<processor_error_info_num; i++) 67 { 68 json_object_array_add(error_info_array, cper_ia32x64_processor_error_info_to_ir(current_error_info)); 69 current_error_info++; 70 } 71 json_object_object_add(record_ir, "processorErrorInfo", error_info_array); 72 73 //Processor context information, of the amount described above. 74 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* current_context_info = (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO*)(current_error_info + 1); 75 json_object* context_info_array = json_object_new_array(); 76 for (int i=0; i<processor_context_info_num; i++) 77 { 78 json_object_array_add(context_info_array, cper_ia32x64_processor_context_info_to_ir(current_context_info, (void**)¤t_context_info)); 79 //The context array is a non-fixed size, pointer is shifted within the above function. 80 } 81 json_object_object_add(record_ir, "processorContextInfo", context_info_array); 82 83 return record_ir; 84 } 85 86 //Converts a single IA32/x64 processor error info block into JSON IR format. 87 json_object* cper_ia32x64_processor_error_info_to_ir(EFI_IA32_X64_PROCESS_ERROR_INFO* error_info) 88 { 89 json_object* error_info_ir = json_object_new_object(); 90 91 //Error structure type (as GUID). 92 char error_type[GUID_STRING_LENGTH]; 93 guid_to_string(error_type, &error_info->ErrorType); 94 json_object_object_add(error_info_ir, "type", json_object_new_string(error_type)); 95 96 //Validation bits. 97 json_object* validation = bitfield_to_ir(error_info->ValidFields, 5, IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES); 98 json_object_object_add(error_info_ir, "validationBits", validation); 99 100 //Add the check information on a per-structure basis. 101 //Cache and TLB check information are identical, so can be equated. 102 json_object* check_information = NULL; 103 if (guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeCacheCheckGuid) 104 || guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeTlbCheckGuid)) 105 { 106 check_information = cper_ia32x64_cache_tlb_check_to_ir((EFI_IA32_X64_CACHE_CHECK_INFO*)&error_info->CheckInfo); 107 } 108 else if (guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeBusCheckGuid)) 109 { 110 check_information = cper_ia32x64_bus_check_to_ir((EFI_IA32_X64_BUS_CHECK_INFO*)&error_info->CheckInfo); 111 } 112 else if (guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeMsCheckGuid)) 113 { 114 check_information = cper_ia32x64_ms_check_to_ir((EFI_IA32_X64_MS_CHECK_INFO*)&error_info->CheckInfo); 115 } 116 else 117 { 118 //Unknown check information. 119 printf("WARN: Invalid/unknown check information GUID found in IA32/x64 CPER section. Ignoring.\n"); 120 } 121 json_object_object_add(error_info_ir, "checkInfo", check_information); 122 123 //Target, requestor, and responder identifiers. 124 json_object_object_add(error_info_ir, "targetAddressID", json_object_new_uint64(error_info->TargetId)); 125 json_object_object_add(error_info_ir, "requestorID", json_object_new_uint64(error_info->RequestorId)); 126 json_object_object_add(error_info_ir, "responderID", json_object_new_uint64(error_info->ResponderId)); 127 json_object_object_add(error_info_ir, "instructionPointer", json_object_new_uint64(error_info->InstructionIP)); 128 129 return error_info_ir; 130 } 131 132 //Converts a single IA32/x64 cache or TLB check check info block into JSON IR format. 133 json_object* cper_ia32x64_cache_tlb_check_to_ir(EFI_IA32_X64_CACHE_CHECK_INFO* cache_tlb_check) 134 { 135 json_object* cache_tlb_check_ir = json_object_new_object(); 136 137 //Validation bits. 138 json_object* validation = bitfield_to_ir(cache_tlb_check->ValidFields, 8, IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 139 json_object_object_add(cache_tlb_check_ir, "validationBits", validation); 140 141 //Transaction type. 142 json_object* transaction_type = integer_to_readable_pair(cache_tlb_check->TransactionType, 3, 143 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS, 144 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES, 145 "Unknown (Reserved)"); 146 json_object_object_add(cache_tlb_check_ir, "transactionType", transaction_type); 147 148 //Operation. 149 json_object* operation = integer_to_readable_pair(cache_tlb_check->Operation, 9, 150 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS, 151 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES, 152 "Unknown (Reserved)"); 153 json_object_object_add(cache_tlb_check_ir, "operation", operation); 154 155 //Affected cache/TLB level. 156 json_object_object_add(cache_tlb_check_ir, "level", json_object_new_uint64(cache_tlb_check->Level)); 157 158 //Miscellaneous boolean fields. 159 json_object_object_add(cache_tlb_check_ir, "processorContextCorrupt", json_object_new_boolean(cache_tlb_check->ContextCorrupt)); 160 json_object_object_add(cache_tlb_check_ir, "uncorrected", json_object_new_boolean(cache_tlb_check->ErrorUncorrected)); 161 json_object_object_add(cache_tlb_check_ir, "preciseIP", json_object_new_boolean(cache_tlb_check->PreciseIp)); 162 json_object_object_add(cache_tlb_check_ir, "restartableIP", json_object_new_boolean(cache_tlb_check->RestartableIp)); 163 json_object_object_add(cache_tlb_check_ir, "overflow", json_object_new_boolean(cache_tlb_check->Overflow)); 164 165 return cache_tlb_check_ir; 166 } 167 168 //Converts a single IA32/x64 bus check check info block into JSON IR format. 169 json_object* cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO* bus_check) 170 { 171 json_object* bus_check_ir = json_object_new_object(); 172 173 //Validation bits. 174 json_object* validation = bitfield_to_ir(bus_check->ValidFields, 11, IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 175 json_object_object_add(bus_check_ir, "validationBits", validation); 176 177 //Transaction type. 178 json_object* transaction_type = integer_to_readable_pair(bus_check->TransactionType, 3, 179 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS, 180 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES, 181 "Unknown (Reserved)"); 182 json_object_object_add(bus_check_ir, "transactionType", transaction_type); 183 184 //Operation. 185 json_object* operation = integer_to_readable_pair(bus_check->Operation, 9, 186 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS, 187 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES, 188 "Unknown (Reserved)"); 189 json_object_object_add(bus_check_ir, "operation", operation); 190 191 //Affected bus level. 192 json_object_object_add(bus_check_ir, "level", json_object_new_uint64(bus_check->Level)); 193 194 //Miscellaneous boolean fields. 195 json_object_object_add(bus_check_ir, "processorContextCorrupt", json_object_new_boolean(bus_check->ContextCorrupt)); 196 json_object_object_add(bus_check_ir, "uncorrected", json_object_new_boolean(bus_check->ErrorUncorrected)); 197 json_object_object_add(bus_check_ir, "preciseIP", json_object_new_boolean(bus_check->PreciseIp)); 198 json_object_object_add(bus_check_ir, "restartableIP", json_object_new_boolean(bus_check->RestartableIp)); 199 json_object_object_add(bus_check_ir, "overflow", json_object_new_boolean(bus_check->Overflow)); 200 json_object_object_add(bus_check_ir, "timedOut", json_object_new_boolean(bus_check->TimeOut)); 201 202 //Participation type. 203 json_object* participation_type = integer_to_readable_pair(bus_check->ParticipationType, 4, 204 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_KEYS, 205 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_VALUES, 206 "Unknown"); 207 json_object_object_add(bus_check_ir, "participationType", participation_type); 208 209 //Address space. 210 json_object* address_space = integer_to_readable_pair(bus_check->AddressSpace, 4, 211 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_KEYS, 212 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_VALUES, 213 "Unknown"); 214 json_object_object_add(bus_check_ir, "addressSpace", address_space); 215 216 return bus_check_ir; 217 } 218 219 //Converts a single IA32/x64 MS check check info block into JSON IR format. 220 json_object* cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO* ms_check) 221 { 222 json_object* ms_check_ir = json_object_new_object(); 223 224 //Validation bits. 225 json_object* validation = bitfield_to_ir(ms_check->ValidFields, 6, IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES); 226 json_object_object_add(ms_check_ir, "validationBits", validation); 227 228 //Error type (operation that caused the error). 229 json_object* error_type = integer_to_readable_pair(ms_check->ErrorType, 4, 230 IA32X64_MS_CHECK_INFO_ERROR_TYPES_KEYS, 231 IA32X64_MS_CHECK_INFO_ERROR_TYPES_VALUES, 232 "Unknown (Processor Specific)"); 233 json_object_object_add(ms_check_ir, "errorType", error_type); 234 235 //Miscellaneous fields. 236 json_object_object_add(ms_check_ir, "processorContextCorrupt", json_object_new_boolean(ms_check->ContextCorrupt)); 237 json_object_object_add(ms_check_ir, "uncorrected", json_object_new_boolean(ms_check->ErrorUncorrected)); 238 json_object_object_add(ms_check_ir, "preciseIP", json_object_new_boolean(ms_check->PreciseIp)); 239 json_object_object_add(ms_check_ir, "restartableIP", json_object_new_boolean(ms_check->RestartableIp)); 240 json_object_object_add(ms_check_ir, "overflow", json_object_new_boolean(ms_check->Overflow)); 241 242 return ms_check_ir; 243 } 244 245 //Converts a single IA32/x64 processor context info entry into JSON IR format. 246 json_object* cper_ia32x64_processor_context_info_to_ir(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* context_info, void** cur_pos) 247 { 248 json_object* context_info_ir = json_object_new_object(); 249 250 //Register context type. 251 json_object* context_type = integer_to_readable_pair(context_info->RegisterType, 8, 252 IA32X64_REGISTER_CONTEXT_TYPES_KEYS, 253 IA32X64_REGISTER_CONTEXT_TYPES_VALUES, 254 "Unknown (Reserved)"); 255 json_object_object_add(context_info_ir, "registerContextType", context_type); 256 257 //Register array size, MSR and MM address. 258 json_object_object_add(context_info_ir, "registerArraySize", json_object_new_uint64(context_info->ArraySize)); 259 json_object_object_add(context_info_ir, "msrAddress", json_object_new_uint64(context_info->MsrAddress)); 260 json_object_object_add(context_info_ir, "mmRegisterAddress", json_object_new_uint64(context_info->MmRegisterAddress)); 261 262 //Register array. 263 json_object* register_array = NULL; 264 if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) 265 { 266 EFI_CONTEXT_IA32_REGISTER_STATE* register_state = (EFI_CONTEXT_IA32_REGISTER_STATE*)(context_info + 1); 267 register_array = cper_ia32x64_register_32bit_to_ir(register_state); 268 *cur_pos = (void*)(register_state + 1); 269 } 270 else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) 271 { 272 EFI_CONTEXT_X64_REGISTER_STATE* register_state = (EFI_CONTEXT_X64_REGISTER_STATE*)(context_info + 1); 273 register_array = cper_ia32x64_register_64bit_to_ir(register_state); 274 *cur_pos = (void*)(register_state + 1); 275 } 276 else 277 { 278 //No parseable data, just dump as base64 and shift the head to the next item. 279 *cur_pos = (void*)(context_info + 1); 280 281 char* encoded = b64_encode((unsigned char*)*cur_pos, context_info->ArraySize); 282 register_array = json_object_new_object(); 283 json_object_object_add(register_array, "data", json_object_new_string(encoded)); 284 free(encoded); 285 286 *cur_pos = (void*)(((char*)*cur_pos) + context_info->ArraySize); 287 } 288 json_object_object_add(context_info_ir, "registerArray", register_array); 289 290 return context_info_ir; 291 } 292 293 //Converts a single CPER IA32 register state into JSON IR format. 294 json_object* cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE* registers) 295 { 296 json_object* ia32_registers = json_object_new_object(); 297 json_object_object_add(ia32_registers, "eax", json_object_new_uint64(registers->Eax)); 298 json_object_object_add(ia32_registers, "ebx", json_object_new_uint64(registers->Ebx)); 299 json_object_object_add(ia32_registers, "ecx", json_object_new_uint64(registers->Ecx)); 300 json_object_object_add(ia32_registers, "edx", json_object_new_uint64(registers->Edx)); 301 json_object_object_add(ia32_registers, "esi", json_object_new_uint64(registers->Esi)); 302 json_object_object_add(ia32_registers, "edi", json_object_new_uint64(registers->Edi)); 303 json_object_object_add(ia32_registers, "ebp", json_object_new_uint64(registers->Ebp)); 304 json_object_object_add(ia32_registers, "esp", json_object_new_uint64(registers->Esp)); 305 json_object_object_add(ia32_registers, "cs", json_object_new_uint64(registers->Cs)); 306 json_object_object_add(ia32_registers, "ds", json_object_new_uint64(registers->Ds)); 307 json_object_object_add(ia32_registers, "ss", json_object_new_uint64(registers->Ss)); 308 json_object_object_add(ia32_registers, "es", json_object_new_uint64(registers->Es)); 309 json_object_object_add(ia32_registers, "fs", json_object_new_uint64(registers->Fs)); 310 json_object_object_add(ia32_registers, "gs", json_object_new_uint64(registers->Gs)); 311 json_object_object_add(ia32_registers, "eflags", json_object_new_uint64(registers->Eflags)); 312 json_object_object_add(ia32_registers, "eip", json_object_new_uint64(registers->Eip)); 313 json_object_object_add(ia32_registers, "cr0", json_object_new_uint64(registers->Cr0)); 314 json_object_object_add(ia32_registers, "cr1", json_object_new_uint64(registers->Cr1)); 315 json_object_object_add(ia32_registers, "cr2", json_object_new_uint64(registers->Cr2)); 316 json_object_object_add(ia32_registers, "cr3", json_object_new_uint64(registers->Cr3)); 317 json_object_object_add(ia32_registers, "cr4", json_object_new_uint64(registers->Cr4)); 318 json_object_object_add(ia32_registers, "gdtr", json_object_new_uint64(registers->Gdtr[0] + ((UINT64)registers->Gdtr[1] << 32))); 319 json_object_object_add(ia32_registers, "idtr", json_object_new_uint64(registers->Idtr[0] + ((UINT64)registers->Idtr[1] << 32))); 320 json_object_object_add(ia32_registers, "ldtr", json_object_new_uint64(registers->Ldtr)); 321 json_object_object_add(ia32_registers, "tr", json_object_new_uint64(registers->Tr)); 322 323 return ia32_registers; 324 } 325 326 //Converts a single CPER x64 register state into JSON IR format. 327 json_object* cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE* registers) 328 { 329 json_object* x64_registers = json_object_new_object(); 330 json_object_object_add(x64_registers, "rax", json_object_new_uint64(registers->Rax)); 331 json_object_object_add(x64_registers, "rbx", json_object_new_uint64(registers->Rbx)); 332 json_object_object_add(x64_registers, "rcx", json_object_new_uint64(registers->Rcx)); 333 json_object_object_add(x64_registers, "rdx", json_object_new_uint64(registers->Rdx)); 334 json_object_object_add(x64_registers, "rsi", json_object_new_uint64(registers->Rsi)); 335 json_object_object_add(x64_registers, "rdi", json_object_new_uint64(registers->Rdi)); 336 json_object_object_add(x64_registers, "rbp", json_object_new_uint64(registers->Rbp)); 337 json_object_object_add(x64_registers, "rsp", json_object_new_uint64(registers->Rsp)); 338 json_object_object_add(x64_registers, "r8", json_object_new_uint64(registers->R8)); 339 json_object_object_add(x64_registers, "r9", json_object_new_uint64(registers->R9)); 340 json_object_object_add(x64_registers, "r10", json_object_new_uint64(registers->R10)); 341 json_object_object_add(x64_registers, "r11", json_object_new_uint64(registers->R11)); 342 json_object_object_add(x64_registers, "r12", json_object_new_uint64(registers->R12)); 343 json_object_object_add(x64_registers, "r13", json_object_new_uint64(registers->R13)); 344 json_object_object_add(x64_registers, "r14", json_object_new_uint64(registers->R14)); 345 json_object_object_add(x64_registers, "r15", json_object_new_uint64(registers->R15)); 346 json_object_object_add(x64_registers, "cs", json_object_new_int(registers->Cs)); 347 json_object_object_add(x64_registers, "ds", json_object_new_int(registers->Ds)); 348 json_object_object_add(x64_registers, "ss", json_object_new_int(registers->Ss)); 349 json_object_object_add(x64_registers, "es", json_object_new_int(registers->Es)); 350 json_object_object_add(x64_registers, "fs", json_object_new_int(registers->Fs)); 351 json_object_object_add(x64_registers, "gs", json_object_new_int(registers->Gs)); 352 json_object_object_add(x64_registers, "rflags", json_object_new_uint64(registers->Rflags)); 353 json_object_object_add(x64_registers, "eip", json_object_new_uint64(registers->Rip)); 354 json_object_object_add(x64_registers, "cr0", json_object_new_uint64(registers->Cr0)); 355 json_object_object_add(x64_registers, "cr1", json_object_new_uint64(registers->Cr1)); 356 json_object_object_add(x64_registers, "cr2", json_object_new_uint64(registers->Cr2)); 357 json_object_object_add(x64_registers, "cr3", json_object_new_uint64(registers->Cr3)); 358 json_object_object_add(x64_registers, "cr4", json_object_new_uint64(registers->Cr4)); 359 json_object_object_add(x64_registers, "cr8", json_object_new_uint64(registers->Cr8)); 360 json_object_object_add(x64_registers, "gdtr_0", json_object_new_uint64(registers->Gdtr[0])); 361 json_object_object_add(x64_registers, "gdtr_1", json_object_new_uint64(registers->Gdtr[1])); 362 json_object_object_add(x64_registers, "idtr_0", json_object_new_uint64(registers->Idtr[0])); 363 json_object_object_add(x64_registers, "idtr_1", json_object_new_uint64(registers->Idtr[1])); 364 json_object_object_add(x64_registers, "ldtr", json_object_new_int(registers->Ldtr)); 365 json_object_object_add(x64_registers, "tr", json_object_new_int(registers->Tr)); 366 367 return x64_registers; 368 } 369 370 ////////////////// 371 /// IR TO CPER /// 372 ////////////////// 373 374 //Converts a single IA32/x64 CPER-JSON section into CPER binary, outputting to the provided stream. 375 void ir_section_ia32x64_to_cper(json_object* section, FILE* out) 376 { 377 EFI_IA32_X64_PROCESSOR_ERROR_RECORD* section_cper = 378 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD*)calloc(1, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD)); 379 380 //Validation bits. 381 json_object* validation = json_object_object_get(section, "validationBits"); 382 section_cper->ValidFields = 0x0; 383 section_cper->ValidFields |= json_object_get_boolean(json_object_object_get(validation, "localAPICIDValid")); 384 section_cper->ValidFields |= json_object_get_boolean(json_object_object_get(validation, "cpuIDInfoValid")) << 1; 385 int proc_error_info_num = json_object_get_int(json_object_object_get(validation, "processorErrorInfoNum")) & 0b111111; 386 int proc_ctx_info_num = json_object_get_int(json_object_object_get(validation, "processorContextInfoNum")) & 0b111111; 387 section_cper->ValidFields |= proc_error_info_num << 2; 388 section_cper->ValidFields |= proc_ctx_info_num << 8; 389 390 //Local APIC ID. 391 section_cper->ApicId = json_object_get_uint64(json_object_object_get(section, "localAPICID")); 392 393 //CPUID info. 394 json_object* cpuid_info = json_object_object_get(section, "cpuidInfo"); 395 EFI_IA32_X64_CPU_ID* cpuid_info_cper = (EFI_IA32_X64_CPU_ID*)section_cper->CpuIdInfo; 396 cpuid_info_cper->Eax = json_object_get_uint64(json_object_object_get(cpuid_info, "eax")); 397 cpuid_info_cper->Ebx = json_object_get_uint64(json_object_object_get(cpuid_info, "ebx")); 398 cpuid_info_cper->Ecx = json_object_get_uint64(json_object_object_get(cpuid_info, "ecx")); 399 cpuid_info_cper->Edx = json_object_get_uint64(json_object_object_get(cpuid_info, "edx")); 400 401 //Flush the header to file before dealing w/ info sections. 402 fwrite(section_cper, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD), 1, out); 403 fflush(out); 404 free(section_cper); 405 406 //Iterate and deal with sections. 407 json_object* error_info = json_object_object_get(section, "processorErrorInfo"); 408 json_object* context_info = json_object_object_get(section, "processorContextInfo"); 409 for (int i=0; i<proc_error_info_num; i++) 410 ir_ia32x64_error_info_to_cper(json_object_array_get_idx(error_info, i), out); 411 for (int i=0; i<proc_ctx_info_num; i++) 412 ir_ia32x64_context_info_to_cper(json_object_array_get_idx(context_info, i), out); 413 } 414 415 //Converts a single CPER-JSON IA32/x64 error information structure into CPER binary, outputting to the 416 //provided stream. 417 void ir_ia32x64_error_info_to_cper(json_object* error_info, FILE* out) 418 { 419 EFI_IA32_X64_PROCESS_ERROR_INFO* error_info_cper = 420 (EFI_IA32_X64_PROCESS_ERROR_INFO*)calloc(1, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO)); 421 422 //Error structure type. 423 string_to_guid(&error_info_cper->ErrorType, json_object_get_string(json_object_object_get(error_info, "type"))); 424 425 //Validation bits. 426 error_info_cper->ValidFields = ir_to_bitfield(json_object_object_get(error_info, "validationBits"), 427 5, IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES); 428 429 //Check information, parsed based on the error type. 430 json_object* check_info = json_object_object_get(error_info, "checkInfo"); 431 if (guid_equal(&error_info_cper->ErrorType, &gEfiIa32x64ErrorTypeCacheCheckGuid) 432 || guid_equal(&error_info_cper->ErrorType, &gEfiIa32x64ErrorTypeTlbCheckGuid)) 433 { 434 ir_ia32x64_cache_tlb_check_error_to_cper(check_info, (EFI_IA32_X64_CACHE_CHECK_INFO*)&error_info_cper->CheckInfo); 435 } 436 else if (guid_equal(&error_info_cper->ErrorType, &gEfiIa32x64ErrorTypeBusCheckGuid)) 437 ir_ia32x64_bus_check_error_to_cper(check_info, (EFI_IA32_X64_BUS_CHECK_INFO*)&error_info_cper->CheckInfo); 438 else if (guid_equal(&error_info_cper->ErrorType, &gEfiIa32x64ErrorTypeMsCheckGuid)) 439 ir_ia32x64_ms_check_error_to_cper(check_info, (EFI_IA32_X64_MS_CHECK_INFO*)&error_info_cper->CheckInfo); 440 441 //Miscellaneous numeric fields. 442 error_info_cper->TargetId = json_object_get_uint64(json_object_object_get(error_info, "targetAddressID")); 443 error_info_cper->RequestorId = json_object_get_uint64(json_object_object_get(error_info, "requestorID")); 444 error_info_cper->ResponderId = json_object_get_uint64(json_object_object_get(error_info, "responderID")); 445 error_info_cper->InstructionIP = json_object_get_uint64(json_object_object_get(error_info, "instructionPointer")); 446 447 //Write out to stream, then free resources. 448 fwrite(error_info_cper, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO), 1, out); 449 fflush(out); 450 free(error_info_cper); 451 } 452 453 //Converts a single CPER-JSON IA32/x64 cache/TLB check error info structure to CPER binary. 454 void ir_ia32x64_cache_tlb_check_error_to_cper(json_object* check_info, EFI_IA32_X64_CACHE_CHECK_INFO* check_info_cper) 455 { 456 //Validation bits. 457 check_info_cper->ValidFields = ir_to_bitfield(json_object_object_get(check_info, "validationBits"), 458 8, IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 459 460 //Transaction type, operation. 461 check_info_cper->TransactionType = readable_pair_to_integer(json_object_object_get(check_info, "transactionType")); 462 check_info_cper->Operation = readable_pair_to_integer(json_object_object_get(check_info, "operation")); 463 464 //Miscellaneous raw value fields. 465 check_info_cper->Level = json_object_get_uint64(json_object_object_get(check_info, "level")); 466 check_info_cper->ContextCorrupt = json_object_get_boolean(json_object_object_get(check_info, "processorContextCorrupt")); 467 check_info_cper->ErrorUncorrected = json_object_get_boolean(json_object_object_get(check_info, "uncorrected")); 468 check_info_cper->PreciseIp = json_object_get_boolean(json_object_object_get(check_info, "preciseIP")); 469 check_info_cper->RestartableIp = json_object_get_boolean(json_object_object_get(check_info, "restartableIP")); 470 check_info_cper->Overflow = json_object_get_boolean(json_object_object_get(check_info, "overflow")); 471 } 472 473 //Converts a single CPER-JSON IA32/x64 bus error info structure to CPER binary. 474 void ir_ia32x64_bus_check_error_to_cper(json_object* check_info, EFI_IA32_X64_BUS_CHECK_INFO* check_info_cper) 475 { 476 //Validation bits. 477 check_info_cper->ValidFields = ir_to_bitfield(json_object_object_get(check_info, "validationBits"), 478 11, IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 479 480 //Readable pair fields. 481 check_info_cper->TransactionType = readable_pair_to_integer(json_object_object_get(check_info, "transactionType")); 482 check_info_cper->Operation = readable_pair_to_integer(json_object_object_get(check_info, "operation")); 483 check_info_cper->ParticipationType = readable_pair_to_integer(json_object_object_get(check_info, "participationType")); 484 check_info_cper->AddressSpace = readable_pair_to_integer(json_object_object_get(check_info, "addressSpace")); 485 486 //Miscellaneous raw value fields. 487 check_info_cper->Level = json_object_get_uint64(json_object_object_get(check_info, "level")); 488 check_info_cper->ContextCorrupt = json_object_get_boolean(json_object_object_get(check_info, "processorContextCorrupt")); 489 check_info_cper->ErrorUncorrected = json_object_get_boolean(json_object_object_get(check_info, "uncorrected")); 490 check_info_cper->PreciseIp = json_object_get_boolean(json_object_object_get(check_info, "preciseIP")); 491 check_info_cper->RestartableIp = json_object_get_boolean(json_object_object_get(check_info, "restartableIP")); 492 check_info_cper->Overflow = json_object_get_boolean(json_object_object_get(check_info, "overflow")); 493 check_info_cper->TimeOut = json_object_get_boolean(json_object_object_get(check_info, "timedOut")); 494 } 495 496 //Converts a single CPER-JSON IA32/x64 MS error info structure to CPER binary. 497 void ir_ia32x64_ms_check_error_to_cper(json_object* check_info, EFI_IA32_X64_MS_CHECK_INFO* check_info_cper) 498 { 499 //Validation bits. 500 check_info_cper->ValidFields = ir_to_bitfield(json_object_object_get(check_info, "validationBits"), 501 6, IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES); 502 503 //Type of MS check error. 504 check_info_cper->ErrorType = readable_pair_to_integer(json_object_object_get(check_info, "errorType")); 505 506 //Miscellaneous raw value fields. 507 check_info_cper->ContextCorrupt = json_object_get_boolean(json_object_object_get(check_info, "processorContextCorrupt")); 508 check_info_cper->ErrorUncorrected = json_object_get_boolean(json_object_object_get(check_info, "uncorrected")); 509 check_info_cper->PreciseIp = json_object_get_boolean(json_object_object_get(check_info, "preciseIP")); 510 check_info_cper->RestartableIp = json_object_get_boolean(json_object_object_get(check_info, "restartableIP")); 511 check_info_cper->Overflow = json_object_get_boolean(json_object_object_get(check_info, "overflow")); 512 } 513 514 //Converts a single CPER-JSON IA32/x64 context information structure into CPER binary, outputting to the 515 //provided stream. 516 void ir_ia32x64_context_info_to_cper(json_object* context_info, FILE* out) 517 { 518 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* context_info_cper = 519 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO*)calloc(1, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO)); 520 521 //Register context type. 522 context_info_cper->RegisterType = (UINT16)readable_pair_to_integer(json_object_object_get(context_info, "registerContextType")); 523 524 //Miscellaneous numeric fields. 525 context_info_cper->ArraySize = (UINT16)json_object_get_uint64(json_object_object_get(context_info, "registerArraySize")); 526 context_info_cper->MsrAddress = (UINT16)json_object_get_uint64(json_object_object_get(context_info, "msrAddress")); 527 context_info_cper->MmRegisterAddress = (UINT16)json_object_get_uint64(json_object_object_get(context_info, "mmRegisterAddress")); 528 529 //Flush header to stream. 530 fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO), 1, out); 531 fflush(out); 532 533 //Handle the register array, depending on type provided. 534 json_object* register_array = json_object_object_get(context_info, "registerArray"); 535 switch (context_info_cper->RegisterType) 536 { 537 case EFI_REG_CONTEXT_TYPE_IA32: 538 ir_ia32x64_ia32_registers_to_cper(register_array, out); 539 break; 540 case EFI_REG_CONTEXT_TYPE_X64: 541 ir_ia32x64_ia32_registers_to_cper(register_array, out); 542 break; 543 default: 544 //Unknown/undefined. 545 break; 546 } 547 548 //Free remaining resources. 549 free(context_info_cper); 550 } 551 552 //Converts a single CPER-JSON IA32 register array into CPER binary, outputting to the given stream. 553 void ir_ia32x64_ia32_registers_to_cper(json_object* registers, FILE* out) 554 { 555 EFI_CONTEXT_IA32_REGISTER_STATE register_state; 556 register_state.Eax = (UINT32)json_object_get_uint64(json_object_object_get(registers, "eax")); 557 register_state.Ebx = (UINT32)json_object_get_uint64(json_object_object_get(registers, "ebx")); 558 register_state.Ecx = (UINT32)json_object_get_uint64(json_object_object_get(registers, "ecx")); 559 register_state.Edx = (UINT32)json_object_get_uint64(json_object_object_get(registers, "edx")); 560 register_state.Esi = (UINT32)json_object_get_uint64(json_object_object_get(registers, "esi")); 561 register_state.Edi = (UINT32)json_object_get_uint64(json_object_object_get(registers, "edi")); 562 register_state.Ebp = (UINT32)json_object_get_uint64(json_object_object_get(registers, "ebp")); 563 register_state.Esp = (UINT32)json_object_get_uint64(json_object_object_get(registers, "esp")); 564 register_state.Cs = (UINT32)json_object_get_uint64(json_object_object_get(registers, "cs")); 565 register_state.Ds = (UINT32)json_object_get_uint64(json_object_object_get(registers, "ds")); 566 register_state.Ss = (UINT32)json_object_get_uint64(json_object_object_get(registers, "ss")); 567 register_state.Es = (UINT32)json_object_get_uint64(json_object_object_get(registers, "es")); 568 register_state.Fs = (UINT32)json_object_get_uint64(json_object_object_get(registers, "fs")); 569 register_state.Gs = (UINT32)json_object_get_uint64(json_object_object_get(registers, "gs")); 570 register_state.Eflags = (UINT32)json_object_get_uint64(json_object_object_get(registers, "eflags")); 571 register_state.Eip = (UINT32)json_object_get_uint64(json_object_object_get(registers, "eip")); 572 register_state.Cr0 = (UINT32)json_object_get_uint64(json_object_object_get(registers, "cr0")); 573 register_state.Cr1 = (UINT32)json_object_get_uint64(json_object_object_get(registers, "cr1")); 574 register_state.Cr2 = (UINT32)json_object_get_uint64(json_object_object_get(registers, "cr2")); 575 register_state.Cr3 = (UINT32)json_object_get_uint64(json_object_object_get(registers, "cr3")); 576 register_state.Cr4 = (UINT32)json_object_get_uint64(json_object_object_get(registers, "cr4")); 577 578 //64-bit registers are split into two 32-bit parts. 579 UINT64 gdtr = json_object_get_uint64(json_object_object_get(registers, "gdtr")); 580 register_state.Gdtr[0] = gdtr >> 32; 581 register_state.Gdtr[1] = gdtr & 0xFFFFFFFF; 582 UINT64 idtr = json_object_get_uint64(json_object_object_get(registers, "idtr")); 583 register_state.Idtr[0] = idtr >> 32; 584 register_state.Idtr[1] = idtr & 0xFFFFFFFF; 585 586 //16-bit registers. 587 register_state.Ldtr = (UINT16)json_object_get_uint64(json_object_object_get(registers, "ldtr")); 588 register_state.Tr = (UINT16)json_object_get_uint64(json_object_object_get(registers, "tr")); 589 590 //Write out to stream. 591 fwrite(®ister_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1, out); 592 fflush(out); 593 } 594 595 //Converts a single CPER-JSON x64 register array into CPER binary, outputting to the given stream. 596 void ir_ia32x64_x64_registers_to_cper(json_object* registers, FILE* out) 597 { 598 EFI_CONTEXT_X64_REGISTER_STATE register_state; 599 register_state.Rax = json_object_get_uint64(json_object_object_get(registers, "rax")); 600 register_state.Rbx = json_object_get_uint64(json_object_object_get(registers, "rbx")); 601 register_state.Rcx = json_object_get_uint64(json_object_object_get(registers, "rcx")); 602 register_state.Rdx = json_object_get_uint64(json_object_object_get(registers, "rdx")); 603 register_state.Rsi = json_object_get_uint64(json_object_object_get(registers, "rsi")); 604 register_state.Rdi = json_object_get_uint64(json_object_object_get(registers, "rdi")); 605 register_state.Rbp = json_object_get_uint64(json_object_object_get(registers, "rbp")); 606 register_state.Rsp = json_object_get_uint64(json_object_object_get(registers, "rsp")); 607 register_state.R8 = json_object_get_uint64(json_object_object_get(registers, "r8")); 608 register_state.R9 = json_object_get_uint64(json_object_object_get(registers, "r9")); 609 register_state.R10 = json_object_get_uint64(json_object_object_get(registers, "r10")); 610 register_state.R11 = json_object_get_uint64(json_object_object_get(registers, "r11")); 611 register_state.R12 = json_object_get_uint64(json_object_object_get(registers, "r12")); 612 register_state.R13 = json_object_get_uint64(json_object_object_get(registers, "r13")); 613 register_state.R14 = json_object_get_uint64(json_object_object_get(registers, "r14")); 614 register_state.R15 = json_object_get_uint64(json_object_object_get(registers, "r15")); 615 register_state.Cs = json_object_get_uint64(json_object_object_get(registers, "cs")); 616 register_state.Ds = json_object_get_uint64(json_object_object_get(registers, "ds")); 617 register_state.Ss = json_object_get_uint64(json_object_object_get(registers, "ss")); 618 register_state.Es = json_object_get_uint64(json_object_object_get(registers, "es")); 619 register_state.Fs = json_object_get_uint64(json_object_object_get(registers, "fs")); 620 register_state.Gs = json_object_get_uint64(json_object_object_get(registers, "gs")); 621 register_state.Rflags = json_object_get_uint64(json_object_object_get(registers, "rflags")); 622 register_state.Rip = json_object_get_uint64(json_object_object_get(registers, "eip")); 623 register_state.Cr0 = json_object_get_uint64(json_object_object_get(registers, "cr0")); 624 register_state.Cr1 = json_object_get_uint64(json_object_object_get(registers, "cr1")); 625 register_state.Cr2 = json_object_get_uint64(json_object_object_get(registers, "cr2")); 626 register_state.Cr3 = json_object_get_uint64(json_object_object_get(registers, "cr3")); 627 register_state.Cr4 = json_object_get_uint64(json_object_object_get(registers, "cr4")); 628 register_state.Cr8 = json_object_get_uint64(json_object_object_get(registers, "cr8")); 629 register_state.Gdtr[0] = json_object_get_uint64(json_object_object_get(registers, "gdtr_0")); 630 register_state.Gdtr[1] = json_object_get_uint64(json_object_object_get(registers, "gdtr_1")); 631 register_state.Idtr[0] = json_object_get_uint64(json_object_object_get(registers, "idtr_0")); 632 register_state.Idtr[1] = json_object_get_uint64(json_object_object_get(registers, "idtr_1")); 633 register_state.Ldtr = (UINT16)json_object_get_uint64(json_object_object_get(registers, "ldtr")); 634 register_state.Tr = (UINT16)json_object_get_uint64(json_object_object_get(registers, "tr")); 635 636 //Write out to stream. 637 fwrite(®ister_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1, out); 638 fflush(out); 639 }