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