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