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( 17 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info); 18 json_object *cper_ia32x64_cache_tlb_check_to_ir( 19 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check); 20 json_object * 21 cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check); 22 json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check); 23 json_object *cper_ia32x64_processor_context_info_to_ir( 24 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos); 25 json_object * 26 cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers); 27 json_object * 28 cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers); 29 void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out); 30 void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out); 31 void ir_ia32x64_cache_tlb_check_error_to_cper( 32 json_object *check_info, 33 EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper); 34 void ir_ia32x64_bus_check_error_to_cper( 35 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper); 36 void ir_ia32x64_ms_check_error_to_cper( 37 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper); 38 void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out); 39 void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out); 40 41 ////////////////// 42 /// CPER TO IR /// 43 ////////////////// 44 45 //Converts the IA32/x64 error section described in the given descriptor into intermediate format. 46 json_object * 47 cper_section_ia32x64_to_ir(void *section, 48 EFI_ERROR_SECTION_DESCRIPTOR *descriptor) 49 { 50 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *record = 51 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)section; 52 json_object *record_ir = json_object_new_object(); 53 54 //Validation bits. 55 json_object *validationBits = json_object_new_object(); 56 json_object_object_add(validationBits, "localAPICIDValid", 57 json_object_new_boolean(record->ValidFields & 58 0b1)); 59 json_object_object_add( 60 validationBits, "cpuIDInfoValid", 61 json_object_new_boolean((record->ValidFields >> 1) & 0b1)); 62 int processor_error_info_num = (record->ValidFields >> 2) & 0b111111; 63 json_object_object_add(validationBits, "processorErrorInfoNum", 64 json_object_new_int(processor_error_info_num)); 65 int processor_context_info_num = (record->ValidFields >> 8) & 0b111111; 66 json_object_object_add(validationBits, "processorContextInfoNum", 67 json_object_new_int(processor_context_info_num)); 68 json_object_object_add(record_ir, "validationBits", validationBits); 69 70 //APIC ID. 71 json_object_object_add(record_ir, "localAPICID", 72 json_object_new_uint64(record->ApicId)); 73 74 //CPUID information. 75 json_object *cpuid_info_ir = json_object_new_object(); 76 EFI_IA32_X64_CPU_ID *cpuid_info = 77 (EFI_IA32_X64_CPU_ID *)record->CpuIdInfo; 78 json_object_object_add(cpuid_info_ir, "eax", 79 json_object_new_uint64(cpuid_info->Eax)); 80 json_object_object_add(cpuid_info_ir, "ebx", 81 json_object_new_uint64(cpuid_info->Ebx)); 82 json_object_object_add(cpuid_info_ir, "ecx", 83 json_object_new_uint64(cpuid_info->Ecx)); 84 json_object_object_add(cpuid_info_ir, "edx", 85 json_object_new_uint64(cpuid_info->Edx)); 86 json_object_object_add(record_ir, "cpuidInfo", cpuid_info_ir); 87 88 //Processor error information, of the amount described above. 89 EFI_IA32_X64_PROCESS_ERROR_INFO *current_error_info = 90 (EFI_IA32_X64_PROCESS_ERROR_INFO *)(record + 1); 91 json_object *error_info_array = json_object_new_array(); 92 for (int i = 0; i < processor_error_info_num; i++) { 93 json_object_array_add(error_info_array, 94 cper_ia32x64_processor_error_info_to_ir( 95 current_error_info)); 96 current_error_info++; 97 } 98 json_object_object_add(record_ir, "processorErrorInfo", 99 error_info_array); 100 101 //Processor context information, of the amount described above. 102 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *current_context_info = 103 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)current_error_info; 104 void *cur_pos = (void *)current_context_info; 105 json_object *context_info_array = json_object_new_array(); 106 for (int i = 0; i < processor_context_info_num; i++) { 107 json_object_array_add(context_info_array, 108 cper_ia32x64_processor_context_info_to_ir( 109 current_context_info, &cur_pos)); 110 current_context_info = 111 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)cur_pos; 112 //The context array is a non-fixed size, pointer is shifted within the above function. 113 } 114 json_object_object_add(record_ir, "processorContextInfo", 115 context_info_array); 116 117 return record_ir; 118 } 119 120 //Converts a single IA32/x64 processor error info block into JSON IR format. 121 json_object *cper_ia32x64_processor_error_info_to_ir( 122 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info) 123 { 124 json_object *error_info_ir = json_object_new_object(); 125 126 //Error structure type (as GUID). 127 char error_type[GUID_STRING_LENGTH]; 128 guid_to_string(error_type, &error_info->ErrorType); 129 json_object *type = json_object_new_object(); 130 json_object_object_add(type, "guid", 131 json_object_new_string(error_type)); 132 133 //Get the error structure type as a readable string. 134 const char *readable_type = "Unknown"; 135 if (guid_equal(&error_info->ErrorType, 136 &gEfiIa32x64ErrorTypeCacheCheckGuid)) 137 readable_type = "Cache Check Error"; 138 else if (guid_equal(&error_info->ErrorType, 139 &gEfiIa32x64ErrorTypeTlbCheckGuid)) 140 readable_type = "TLB Check Error"; 141 else if (guid_equal(&error_info->ErrorType, 142 &gEfiIa32x64ErrorTypeBusCheckGuid)) 143 readable_type = "Bus Check Error"; 144 else if (guid_equal(&error_info->ErrorType, 145 &gEfiIa32x64ErrorTypeMsCheckGuid)) 146 readable_type = "MS Check Error"; 147 json_object_object_add(type, "name", json_object_new_string(readable_type)); 148 json_object_object_add(error_info_ir, "type", type); 149 150 //Validation bits. 151 json_object *validation = 152 bitfield_to_ir(error_info->ValidFields, 5, 153 IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES); 154 json_object_object_add(error_info_ir, "validationBits", validation); 155 156 //Add the check information on a per-structure basis. 157 //Cache and TLB check information are identical, so can be equated. 158 json_object *check_information = NULL; 159 if (guid_equal(&error_info->ErrorType, 160 &gEfiIa32x64ErrorTypeCacheCheckGuid) || 161 guid_equal(&error_info->ErrorType, 162 &gEfiIa32x64ErrorTypeTlbCheckGuid)) { 163 check_information = cper_ia32x64_cache_tlb_check_to_ir( 164 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info->CheckInfo); 165 } else if (guid_equal(&error_info->ErrorType, 166 &gEfiIa32x64ErrorTypeBusCheckGuid)) { 167 check_information = cper_ia32x64_bus_check_to_ir( 168 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info->CheckInfo); 169 } else if (guid_equal(&error_info->ErrorType, 170 &gEfiIa32x64ErrorTypeMsCheckGuid)) { 171 check_information = cper_ia32x64_ms_check_to_ir( 172 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info->CheckInfo); 173 } else { 174 //Unknown check information. 175 printf("WARN: Invalid/unknown check information GUID found in IA32/x64 CPER section. Ignoring.\n"); 176 } 177 json_object_object_add(error_info_ir, "checkInfo", check_information); 178 179 //Target, requestor, and responder identifiers. 180 json_object_object_add(error_info_ir, "targetAddressID", 181 json_object_new_uint64(error_info->TargetId)); 182 json_object_object_add(error_info_ir, "requestorID", 183 json_object_new_uint64(error_info->RequestorId)); 184 json_object_object_add(error_info_ir, "responderID", 185 json_object_new_uint64(error_info->ResponderId)); 186 json_object_object_add( 187 error_info_ir, "instructionPointer", 188 json_object_new_uint64(error_info->InstructionIP)); 189 190 return error_info_ir; 191 } 192 193 //Converts a single IA32/x64 cache or TLB check check info block into JSON IR format. 194 json_object *cper_ia32x64_cache_tlb_check_to_ir( 195 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check) 196 { 197 json_object *cache_tlb_check_ir = json_object_new_object(); 198 199 //Validation bits. 200 json_object *validation = 201 bitfield_to_ir(cache_tlb_check->ValidFields, 8, 202 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 203 json_object_object_add(cache_tlb_check_ir, "validationBits", 204 validation); 205 206 //Transaction type. 207 json_object *transaction_type = integer_to_readable_pair( 208 cache_tlb_check->TransactionType, 3, 209 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS, 210 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES, 211 "Unknown (Reserved)"); 212 json_object_object_add(cache_tlb_check_ir, "transactionType", 213 transaction_type); 214 215 //Operation. 216 json_object *operation = integer_to_readable_pair( 217 cache_tlb_check->Operation, 9, 218 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS, 219 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES, 220 "Unknown (Reserved)"); 221 json_object_object_add(cache_tlb_check_ir, "operation", operation); 222 223 //Affected cache/TLB level. 224 json_object_object_add(cache_tlb_check_ir, "level", 225 json_object_new_uint64(cache_tlb_check->Level)); 226 227 //Miscellaneous boolean fields. 228 json_object_object_add( 229 cache_tlb_check_ir, "processorContextCorrupt", 230 json_object_new_boolean(cache_tlb_check->ContextCorrupt)); 231 json_object_object_add( 232 cache_tlb_check_ir, "uncorrected", 233 json_object_new_boolean(cache_tlb_check->ErrorUncorrected)); 234 json_object_object_add( 235 cache_tlb_check_ir, "preciseIP", 236 json_object_new_boolean(cache_tlb_check->PreciseIp)); 237 json_object_object_add( 238 cache_tlb_check_ir, "restartableIP", 239 json_object_new_boolean(cache_tlb_check->RestartableIp)); 240 json_object_object_add( 241 cache_tlb_check_ir, "overflow", 242 json_object_new_boolean(cache_tlb_check->Overflow)); 243 244 return cache_tlb_check_ir; 245 } 246 247 //Converts a single IA32/x64 bus check check info block into JSON IR format. 248 json_object * 249 cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check) 250 { 251 json_object *bus_check_ir = json_object_new_object(); 252 253 //Validation bits. 254 json_object *validation = 255 bitfield_to_ir(bus_check->ValidFields, 11, 256 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 257 json_object_object_add(bus_check_ir, "validationBits", validation); 258 259 //Transaction type. 260 json_object *transaction_type = integer_to_readable_pair( 261 bus_check->TransactionType, 3, 262 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS, 263 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES, 264 "Unknown (Reserved)"); 265 json_object_object_add(bus_check_ir, "transactionType", 266 transaction_type); 267 268 //Operation. 269 json_object *operation = integer_to_readable_pair( 270 bus_check->Operation, 9, 271 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS, 272 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES, 273 "Unknown (Reserved)"); 274 json_object_object_add(bus_check_ir, "operation", operation); 275 276 //Affected bus level. 277 json_object_object_add(bus_check_ir, "level", 278 json_object_new_uint64(bus_check->Level)); 279 280 //Miscellaneous boolean fields. 281 json_object_object_add( 282 bus_check_ir, "processorContextCorrupt", 283 json_object_new_boolean(bus_check->ContextCorrupt)); 284 json_object_object_add( 285 bus_check_ir, "uncorrected", 286 json_object_new_boolean(bus_check->ErrorUncorrected)); 287 json_object_object_add(bus_check_ir, "preciseIP", 288 json_object_new_boolean(bus_check->PreciseIp)); 289 json_object_object_add( 290 bus_check_ir, "restartableIP", 291 json_object_new_boolean(bus_check->RestartableIp)); 292 json_object_object_add(bus_check_ir, "overflow", 293 json_object_new_boolean(bus_check->Overflow)); 294 json_object_object_add(bus_check_ir, "timedOut", 295 json_object_new_boolean(bus_check->TimeOut)); 296 297 //Participation type. 298 json_object *participation_type = integer_to_readable_pair( 299 bus_check->ParticipationType, 4, 300 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_KEYS, 301 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_VALUES, "Unknown"); 302 json_object_object_add(bus_check_ir, "participationType", 303 participation_type); 304 305 //Address space. 306 json_object *address_space = integer_to_readable_pair( 307 bus_check->AddressSpace, 4, 308 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_KEYS, 309 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_VALUES, "Unknown"); 310 json_object_object_add(bus_check_ir, "addressSpace", address_space); 311 312 return bus_check_ir; 313 } 314 315 //Converts a single IA32/x64 MS check check info block into JSON IR format. 316 json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check) 317 { 318 json_object *ms_check_ir = json_object_new_object(); 319 320 //Validation bits. 321 json_object *validation = bitfield_to_ir( 322 ms_check->ValidFields, 6, 323 IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES); 324 json_object_object_add(ms_check_ir, "validationBits", validation); 325 326 //Error type (operation that caused the error). 327 json_object *error_type = integer_to_readable_pair( 328 ms_check->ErrorType, 4, IA32X64_MS_CHECK_INFO_ERROR_TYPES_KEYS, 329 IA32X64_MS_CHECK_INFO_ERROR_TYPES_VALUES, 330 "Unknown (Processor Specific)"); 331 json_object_object_add(ms_check_ir, "errorType", error_type); 332 333 //Miscellaneous fields. 334 json_object_object_add( 335 ms_check_ir, "processorContextCorrupt", 336 json_object_new_boolean(ms_check->ContextCorrupt)); 337 json_object_object_add( 338 ms_check_ir, "uncorrected", 339 json_object_new_boolean(ms_check->ErrorUncorrected)); 340 json_object_object_add(ms_check_ir, "preciseIP", 341 json_object_new_boolean(ms_check->PreciseIp)); 342 json_object_object_add( 343 ms_check_ir, "restartableIP", 344 json_object_new_boolean(ms_check->RestartableIp)); 345 json_object_object_add(ms_check_ir, "overflow", 346 json_object_new_boolean(ms_check->Overflow)); 347 348 return ms_check_ir; 349 } 350 351 //Converts a single IA32/x64 processor context info entry into JSON IR format. 352 json_object *cper_ia32x64_processor_context_info_to_ir( 353 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos) 354 { 355 json_object *context_info_ir = json_object_new_object(); 356 357 //Register context type. 358 json_object *context_type = integer_to_readable_pair( 359 context_info->RegisterType, 8, 360 IA32X64_REGISTER_CONTEXT_TYPES_KEYS, 361 IA32X64_REGISTER_CONTEXT_TYPES_VALUES, "Unknown (Reserved)"); 362 json_object_object_add(context_info_ir, "registerContextType", 363 context_type); 364 365 //Register array size, MSR and MM address. 366 json_object_object_add(context_info_ir, "registerArraySize", 367 json_object_new_uint64(context_info->ArraySize)); 368 json_object_object_add( 369 context_info_ir, "msrAddress", 370 json_object_new_uint64(context_info->MsrAddress)); 371 json_object_object_add( 372 context_info_ir, "mmRegisterAddress", 373 json_object_new_uint64(context_info->MmRegisterAddress)); 374 375 //Register array. 376 json_object *register_array = NULL; 377 if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) { 378 EFI_CONTEXT_IA32_REGISTER_STATE *register_state = 379 (EFI_CONTEXT_IA32_REGISTER_STATE *)(context_info + 1); 380 register_array = 381 cper_ia32x64_register_32bit_to_ir(register_state); 382 *cur_pos = (void *)(register_state + 1); 383 } else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) { 384 EFI_CONTEXT_X64_REGISTER_STATE *register_state = 385 (EFI_CONTEXT_X64_REGISTER_STATE *)(context_info + 1); 386 register_array = 387 cper_ia32x64_register_64bit_to_ir(register_state); 388 *cur_pos = (void *)(register_state + 1); 389 } else { 390 //No parseable data, just dump as base64 and shift the head to the next item. 391 *cur_pos = (void *)(context_info + 1); 392 393 char *encoded = b64_encode((unsigned char *)*cur_pos, 394 context_info->ArraySize); 395 register_array = json_object_new_object(); 396 json_object_object_add(register_array, "data", 397 json_object_new_string(encoded)); 398 free(encoded); 399 400 *cur_pos = 401 (void *)(((char *)*cur_pos) + context_info->ArraySize); 402 } 403 json_object_object_add(context_info_ir, "registerArray", 404 register_array); 405 406 return context_info_ir; 407 } 408 409 //Converts a single CPER IA32 register state into JSON IR format. 410 json_object * 411 cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers) 412 { 413 json_object *ia32_registers = json_object_new_object(); 414 json_object_object_add(ia32_registers, "eax", 415 json_object_new_uint64(registers->Eax)); 416 json_object_object_add(ia32_registers, "ebx", 417 json_object_new_uint64(registers->Ebx)); 418 json_object_object_add(ia32_registers, "ecx", 419 json_object_new_uint64(registers->Ecx)); 420 json_object_object_add(ia32_registers, "edx", 421 json_object_new_uint64(registers->Edx)); 422 json_object_object_add(ia32_registers, "esi", 423 json_object_new_uint64(registers->Esi)); 424 json_object_object_add(ia32_registers, "edi", 425 json_object_new_uint64(registers->Edi)); 426 json_object_object_add(ia32_registers, "ebp", 427 json_object_new_uint64(registers->Ebp)); 428 json_object_object_add(ia32_registers, "esp", 429 json_object_new_uint64(registers->Esp)); 430 json_object_object_add(ia32_registers, "cs", 431 json_object_new_uint64(registers->Cs)); 432 json_object_object_add(ia32_registers, "ds", 433 json_object_new_uint64(registers->Ds)); 434 json_object_object_add(ia32_registers, "ss", 435 json_object_new_uint64(registers->Ss)); 436 json_object_object_add(ia32_registers, "es", 437 json_object_new_uint64(registers->Es)); 438 json_object_object_add(ia32_registers, "fs", 439 json_object_new_uint64(registers->Fs)); 440 json_object_object_add(ia32_registers, "gs", 441 json_object_new_uint64(registers->Gs)); 442 json_object_object_add(ia32_registers, "eflags", 443 json_object_new_uint64(registers->Eflags)); 444 json_object_object_add(ia32_registers, "eip", 445 json_object_new_uint64(registers->Eip)); 446 json_object_object_add(ia32_registers, "cr0", 447 json_object_new_uint64(registers->Cr0)); 448 json_object_object_add(ia32_registers, "cr1", 449 json_object_new_uint64(registers->Cr1)); 450 json_object_object_add(ia32_registers, "cr2", 451 json_object_new_uint64(registers->Cr2)); 452 json_object_object_add(ia32_registers, "cr3", 453 json_object_new_uint64(registers->Cr3)); 454 json_object_object_add(ia32_registers, "cr4", 455 json_object_new_uint64(registers->Cr4)); 456 json_object_object_add( 457 ia32_registers, "gdtr", 458 json_object_new_uint64(registers->Gdtr[0] + 459 ((UINT64)registers->Gdtr[1] << 32))); 460 json_object_object_add( 461 ia32_registers, "idtr", 462 json_object_new_uint64(registers->Idtr[0] + 463 ((UINT64)registers->Idtr[1] << 32))); 464 json_object_object_add(ia32_registers, "ldtr", 465 json_object_new_uint64(registers->Ldtr)); 466 json_object_object_add(ia32_registers, "tr", 467 json_object_new_uint64(registers->Tr)); 468 469 return ia32_registers; 470 } 471 472 //Converts a single CPER x64 register state into JSON IR format. 473 json_object * 474 cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers) 475 { 476 json_object *x64_registers = json_object_new_object(); 477 json_object_object_add(x64_registers, "rax", 478 json_object_new_uint64(registers->Rax)); 479 json_object_object_add(x64_registers, "rbx", 480 json_object_new_uint64(registers->Rbx)); 481 json_object_object_add(x64_registers, "rcx", 482 json_object_new_uint64(registers->Rcx)); 483 json_object_object_add(x64_registers, "rdx", 484 json_object_new_uint64(registers->Rdx)); 485 json_object_object_add(x64_registers, "rsi", 486 json_object_new_uint64(registers->Rsi)); 487 json_object_object_add(x64_registers, "rdi", 488 json_object_new_uint64(registers->Rdi)); 489 json_object_object_add(x64_registers, "rbp", 490 json_object_new_uint64(registers->Rbp)); 491 json_object_object_add(x64_registers, "rsp", 492 json_object_new_uint64(registers->Rsp)); 493 json_object_object_add(x64_registers, "r8", 494 json_object_new_uint64(registers->R8)); 495 json_object_object_add(x64_registers, "r9", 496 json_object_new_uint64(registers->R9)); 497 json_object_object_add(x64_registers, "r10", 498 json_object_new_uint64(registers->R10)); 499 json_object_object_add(x64_registers, "r11", 500 json_object_new_uint64(registers->R11)); 501 json_object_object_add(x64_registers, "r12", 502 json_object_new_uint64(registers->R12)); 503 json_object_object_add(x64_registers, "r13", 504 json_object_new_uint64(registers->R13)); 505 json_object_object_add(x64_registers, "r14", 506 json_object_new_uint64(registers->R14)); 507 json_object_object_add(x64_registers, "r15", 508 json_object_new_uint64(registers->R15)); 509 json_object_object_add(x64_registers, "cs", 510 json_object_new_int(registers->Cs)); 511 json_object_object_add(x64_registers, "ds", 512 json_object_new_int(registers->Ds)); 513 json_object_object_add(x64_registers, "ss", 514 json_object_new_int(registers->Ss)); 515 json_object_object_add(x64_registers, "es", 516 json_object_new_int(registers->Es)); 517 json_object_object_add(x64_registers, "fs", 518 json_object_new_int(registers->Fs)); 519 json_object_object_add(x64_registers, "gs", 520 json_object_new_int(registers->Gs)); 521 json_object_object_add(x64_registers, "rflags", 522 json_object_new_uint64(registers->Rflags)); 523 json_object_object_add(x64_registers, "eip", 524 json_object_new_uint64(registers->Rip)); 525 json_object_object_add(x64_registers, "cr0", 526 json_object_new_uint64(registers->Cr0)); 527 json_object_object_add(x64_registers, "cr1", 528 json_object_new_uint64(registers->Cr1)); 529 json_object_object_add(x64_registers, "cr2", 530 json_object_new_uint64(registers->Cr2)); 531 json_object_object_add(x64_registers, "cr3", 532 json_object_new_uint64(registers->Cr3)); 533 json_object_object_add(x64_registers, "cr4", 534 json_object_new_uint64(registers->Cr4)); 535 json_object_object_add(x64_registers, "cr8", 536 json_object_new_uint64(registers->Cr8)); 537 json_object_object_add(x64_registers, "gdtr_0", 538 json_object_new_uint64(registers->Gdtr[0])); 539 json_object_object_add(x64_registers, "gdtr_1", 540 json_object_new_uint64(registers->Gdtr[1])); 541 json_object_object_add(x64_registers, "idtr_0", 542 json_object_new_uint64(registers->Idtr[0])); 543 json_object_object_add(x64_registers, "idtr_1", 544 json_object_new_uint64(registers->Idtr[1])); 545 json_object_object_add(x64_registers, "ldtr", 546 json_object_new_int(registers->Ldtr)); 547 json_object_object_add(x64_registers, "tr", 548 json_object_new_int(registers->Tr)); 549 550 return x64_registers; 551 } 552 553 ////////////////// 554 /// IR TO CPER /// 555 ////////////////// 556 557 //Converts a single IA32/x64 CPER-JSON section into CPER binary, outputting to the provided stream. 558 void ir_section_ia32x64_to_cper(json_object *section, FILE *out) 559 { 560 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *section_cper = 561 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)calloc( 562 1, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD)); 563 564 //Validation bits. 565 json_object *validation = 566 json_object_object_get(section, "validationBits"); 567 section_cper->ValidFields = 0x0; 568 section_cper->ValidFields |= json_object_get_boolean( 569 json_object_object_get(validation, "localAPICIDValid")); 570 section_cper->ValidFields |= 571 json_object_get_boolean( 572 json_object_object_get(validation, "cpuIDInfoValid")) 573 << 1; 574 int proc_error_info_num = 575 json_object_get_int(json_object_object_get( 576 validation, "processorErrorInfoNum")) & 577 0b111111; 578 int proc_ctx_info_num = 579 json_object_get_int(json_object_object_get( 580 validation, "processorContextInfoNum")) & 581 0b111111; 582 section_cper->ValidFields |= proc_error_info_num << 2; 583 section_cper->ValidFields |= proc_ctx_info_num << 8; 584 585 //Local APIC ID. 586 section_cper->ApicId = json_object_get_uint64( 587 json_object_object_get(section, "localAPICID")); 588 589 //CPUID info. 590 json_object *cpuid_info = json_object_object_get(section, "cpuidInfo"); 591 EFI_IA32_X64_CPU_ID *cpuid_info_cper = 592 (EFI_IA32_X64_CPU_ID *)section_cper->CpuIdInfo; 593 cpuid_info_cper->Eax = json_object_get_uint64( 594 json_object_object_get(cpuid_info, "eax")); 595 cpuid_info_cper->Ebx = json_object_get_uint64( 596 json_object_object_get(cpuid_info, "ebx")); 597 cpuid_info_cper->Ecx = json_object_get_uint64( 598 json_object_object_get(cpuid_info, "ecx")); 599 cpuid_info_cper->Edx = json_object_get_uint64( 600 json_object_object_get(cpuid_info, "edx")); 601 602 //Flush the header to file before dealing w/ info sections. 603 fwrite(section_cper, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD), 1, 604 out); 605 fflush(out); 606 free(section_cper); 607 608 //Iterate and deal with sections. 609 json_object *error_info = 610 json_object_object_get(section, "processorErrorInfo"); 611 json_object *context_info = 612 json_object_object_get(section, "processorContextInfo"); 613 for (int i = 0; i < proc_error_info_num; i++) 614 ir_ia32x64_error_info_to_cper( 615 json_object_array_get_idx(error_info, i), out); 616 for (int i = 0; i < proc_ctx_info_num; i++) 617 ir_ia32x64_context_info_to_cper( 618 json_object_array_get_idx(context_info, i), out); 619 } 620 621 //Converts a single CPER-JSON IA32/x64 error information structure into CPER binary, outputting to the 622 //provided stream. 623 void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out) 624 { 625 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info_cper = 626 (EFI_IA32_X64_PROCESS_ERROR_INFO *)calloc( 627 1, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO)); 628 629 //Error structure type. 630 json_object *type = json_object_object_get(error_info, "type"); 631 string_to_guid( 632 &error_info_cper->ErrorType, 633 json_object_get_string(json_object_object_get(type, "guid"))); 634 635 //Validation bits. 636 error_info_cper->ValidFields = ir_to_bitfield( 637 json_object_object_get(error_info, "validationBits"), 5, 638 IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES); 639 640 //Check information, parsed based on the error type. 641 json_object *check_info = 642 json_object_object_get(error_info, "checkInfo"); 643 if (guid_equal(&error_info_cper->ErrorType, 644 &gEfiIa32x64ErrorTypeCacheCheckGuid) || 645 guid_equal(&error_info_cper->ErrorType, 646 &gEfiIa32x64ErrorTypeTlbCheckGuid)) { 647 ir_ia32x64_cache_tlb_check_error_to_cper( 648 check_info, 649 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info_cper 650 ->CheckInfo); 651 } else if (guid_equal(&error_info_cper->ErrorType, 652 &gEfiIa32x64ErrorTypeBusCheckGuid)) 653 ir_ia32x64_bus_check_error_to_cper( 654 check_info, 655 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info_cper 656 ->CheckInfo); 657 else if (guid_equal(&error_info_cper->ErrorType, 658 &gEfiIa32x64ErrorTypeMsCheckGuid)) 659 ir_ia32x64_ms_check_error_to_cper( 660 check_info, 661 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info_cper 662 ->CheckInfo); 663 664 //Miscellaneous numeric fields. 665 error_info_cper->TargetId = json_object_get_uint64( 666 json_object_object_get(error_info, "targetAddressID")); 667 error_info_cper->RequestorId = json_object_get_uint64( 668 json_object_object_get(error_info, "requestorID")); 669 error_info_cper->ResponderId = json_object_get_uint64( 670 json_object_object_get(error_info, "responderID")); 671 error_info_cper->InstructionIP = json_object_get_uint64( 672 json_object_object_get(error_info, "instructionPointer")); 673 674 //Write out to stream, then free resources. 675 fwrite(error_info_cper, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO), 1, 676 out); 677 fflush(out); 678 free(error_info_cper); 679 } 680 681 //Converts a single CPER-JSON IA32/x64 cache/TLB check error info structure to CPER binary. 682 void ir_ia32x64_cache_tlb_check_error_to_cper( 683 json_object *check_info, EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper) 684 { 685 //Validation bits. 686 check_info_cper->ValidFields = ir_to_bitfield( 687 json_object_object_get(check_info, "validationBits"), 8, 688 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 689 690 //Transaction type, operation. 691 check_info_cper->TransactionType = readable_pair_to_integer( 692 json_object_object_get(check_info, "transactionType")); 693 check_info_cper->Operation = readable_pair_to_integer( 694 json_object_object_get(check_info, "operation")); 695 696 //Miscellaneous raw value fields. 697 check_info_cper->Level = json_object_get_uint64( 698 json_object_object_get(check_info, "level")); 699 check_info_cper->ContextCorrupt = json_object_get_boolean( 700 json_object_object_get(check_info, "processorContextCorrupt")); 701 check_info_cper->ErrorUncorrected = json_object_get_boolean( 702 json_object_object_get(check_info, "uncorrected")); 703 check_info_cper->PreciseIp = json_object_get_boolean( 704 json_object_object_get(check_info, "preciseIP")); 705 check_info_cper->RestartableIp = json_object_get_boolean( 706 json_object_object_get(check_info, "restartableIP")); 707 check_info_cper->Overflow = json_object_get_boolean( 708 json_object_object_get(check_info, "overflow")); 709 } 710 711 //Converts a single CPER-JSON IA32/x64 bus error info structure to CPER binary. 712 void ir_ia32x64_bus_check_error_to_cper( 713 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper) 714 { 715 //Validation bits. 716 check_info_cper->ValidFields = ir_to_bitfield( 717 json_object_object_get(check_info, "validationBits"), 11, 718 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 719 720 //Readable pair fields. 721 check_info_cper->TransactionType = readable_pair_to_integer( 722 json_object_object_get(check_info, "transactionType")); 723 check_info_cper->Operation = readable_pair_to_integer( 724 json_object_object_get(check_info, "operation")); 725 check_info_cper->ParticipationType = readable_pair_to_integer( 726 json_object_object_get(check_info, "participationType")); 727 check_info_cper->AddressSpace = readable_pair_to_integer( 728 json_object_object_get(check_info, "addressSpace")); 729 730 //Miscellaneous raw value fields. 731 check_info_cper->Level = json_object_get_uint64( 732 json_object_object_get(check_info, "level")); 733 check_info_cper->ContextCorrupt = json_object_get_boolean( 734 json_object_object_get(check_info, "processorContextCorrupt")); 735 check_info_cper->ErrorUncorrected = json_object_get_boolean( 736 json_object_object_get(check_info, "uncorrected")); 737 check_info_cper->PreciseIp = json_object_get_boolean( 738 json_object_object_get(check_info, "preciseIP")); 739 check_info_cper->RestartableIp = json_object_get_boolean( 740 json_object_object_get(check_info, "restartableIP")); 741 check_info_cper->Overflow = json_object_get_boolean( 742 json_object_object_get(check_info, "overflow")); 743 check_info_cper->TimeOut = json_object_get_boolean( 744 json_object_object_get(check_info, "timedOut")); 745 } 746 747 //Converts a single CPER-JSON IA32/x64 MS error info structure to CPER binary. 748 void ir_ia32x64_ms_check_error_to_cper( 749 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper) 750 { 751 //Validation bits. 752 check_info_cper->ValidFields = ir_to_bitfield( 753 json_object_object_get(check_info, "validationBits"), 6, 754 IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES); 755 756 //Type of MS check error. 757 check_info_cper->ErrorType = readable_pair_to_integer( 758 json_object_object_get(check_info, "errorType")); 759 760 //Miscellaneous raw value fields. 761 check_info_cper->ContextCorrupt = json_object_get_boolean( 762 json_object_object_get(check_info, "processorContextCorrupt")); 763 check_info_cper->ErrorUncorrected = json_object_get_boolean( 764 json_object_object_get(check_info, "uncorrected")); 765 check_info_cper->PreciseIp = json_object_get_boolean( 766 json_object_object_get(check_info, "preciseIP")); 767 check_info_cper->RestartableIp = json_object_get_boolean( 768 json_object_object_get(check_info, "restartableIP")); 769 check_info_cper->Overflow = json_object_get_boolean( 770 json_object_object_get(check_info, "overflow")); 771 } 772 773 //Converts a single CPER-JSON IA32/x64 context information structure into CPER binary, outputting to the 774 //provided stream. 775 void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out) 776 { 777 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info_cper = 778 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)calloc( 779 1, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO)); 780 781 //Register context type. 782 context_info_cper->RegisterType = (UINT16)readable_pair_to_integer( 783 json_object_object_get(context_info, "registerContextType")); 784 785 //Miscellaneous numeric fields. 786 context_info_cper->ArraySize = (UINT16)json_object_get_uint64( 787 json_object_object_get(context_info, "registerArraySize")); 788 context_info_cper->MsrAddress = (UINT32)json_object_get_uint64( 789 json_object_object_get(context_info, "msrAddress")); 790 context_info_cper->MmRegisterAddress = json_object_get_uint64( 791 json_object_object_get(context_info, "mmRegisterAddress")); 792 793 //Flush header to stream. 794 fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO), 795 1, out); 796 fflush(out); 797 798 //Handle the register array, depending on type provided. 799 json_object *register_array = 800 json_object_object_get(context_info, "registerArray"); 801 if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) { 802 ir_ia32x64_ia32_registers_to_cper(register_array, out); 803 } else if (context_info_cper->RegisterType == 804 EFI_REG_CONTEXT_TYPE_X64) { 805 ir_ia32x64_x64_registers_to_cper(register_array, out); 806 } else { 807 //Unknown/structure is not defined. 808 json_object *encoded = 809 json_object_object_get(register_array, "data"); 810 char *decoded = b64_decode(json_object_get_string(encoded), 811 json_object_get_string_len(encoded)); 812 fwrite(decoded, context_info_cper->ArraySize, 1, out); 813 fflush(out); 814 } 815 816 //Free remaining resources. 817 free(context_info_cper); 818 } 819 820 //Converts a single CPER-JSON IA32 register array into CPER binary, outputting to the given stream. 821 void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out) 822 { 823 EFI_CONTEXT_IA32_REGISTER_STATE register_state; 824 register_state.Eax = (UINT32)json_object_get_uint64( 825 json_object_object_get(registers, "eax")); 826 register_state.Ebx = (UINT32)json_object_get_uint64( 827 json_object_object_get(registers, "ebx")); 828 register_state.Ecx = (UINT32)json_object_get_uint64( 829 json_object_object_get(registers, "ecx")); 830 register_state.Edx = (UINT32)json_object_get_uint64( 831 json_object_object_get(registers, "edx")); 832 register_state.Esi = (UINT32)json_object_get_uint64( 833 json_object_object_get(registers, "esi")); 834 register_state.Edi = (UINT32)json_object_get_uint64( 835 json_object_object_get(registers, "edi")); 836 register_state.Ebp = (UINT32)json_object_get_uint64( 837 json_object_object_get(registers, "ebp")); 838 register_state.Esp = (UINT32)json_object_get_uint64( 839 json_object_object_get(registers, "esp")); 840 register_state.Cs = (UINT16)json_object_get_uint64( 841 json_object_object_get(registers, "cs")); 842 register_state.Ds = (UINT32)json_object_get_uint64( 843 json_object_object_get(registers, "ds")); 844 register_state.Ss = (UINT16)json_object_get_uint64( 845 json_object_object_get(registers, "ss")); 846 register_state.Es = (UINT16)json_object_get_uint64( 847 json_object_object_get(registers, "es")); 848 register_state.Fs = (UINT16)json_object_get_uint64( 849 json_object_object_get(registers, "fs")); 850 register_state.Gs = (UINT16)json_object_get_uint64( 851 json_object_object_get(registers, "gs")); 852 register_state.Eflags = (UINT32)json_object_get_uint64( 853 json_object_object_get(registers, "eflags")); 854 register_state.Eip = (UINT32)json_object_get_uint64( 855 json_object_object_get(registers, "eip")); 856 register_state.Cr0 = (UINT32)json_object_get_uint64( 857 json_object_object_get(registers, "cr0")); 858 register_state.Cr1 = (UINT32)json_object_get_uint64( 859 json_object_object_get(registers, "cr1")); 860 register_state.Cr2 = (UINT32)json_object_get_uint64( 861 json_object_object_get(registers, "cr2")); 862 register_state.Cr3 = (UINT32)json_object_get_uint64( 863 json_object_object_get(registers, "cr3")); 864 register_state.Cr4 = (UINT32)json_object_get_uint64( 865 json_object_object_get(registers, "cr4")); 866 867 //64-bit registers are split into two 32-bit parts. 868 UINT64 gdtr = json_object_get_uint64( 869 json_object_object_get(registers, "gdtr")); 870 register_state.Gdtr[0] = gdtr & 0xFFFFFFFF; 871 register_state.Gdtr[1] = gdtr >> 32; 872 UINT64 idtr = json_object_get_uint64( 873 json_object_object_get(registers, "idtr")); 874 register_state.Idtr[0] = idtr & 0xFFFFFFFF; 875 register_state.Idtr[1] = idtr >> 32; 876 877 //16-bit registers. 878 register_state.Ldtr = (UINT16)json_object_get_uint64( 879 json_object_object_get(registers, "ldtr")); 880 register_state.Tr = (UINT16)json_object_get_uint64( 881 json_object_object_get(registers, "tr")); 882 883 //Write out to stream. 884 fwrite(®ister_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1, 885 out); 886 fflush(out); 887 } 888 889 //Converts a single CPER-JSON x64 register array into CPER binary, outputting to the given stream. 890 void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out) 891 { 892 EFI_CONTEXT_X64_REGISTER_STATE register_state; 893 register_state.Rax = json_object_get_uint64( 894 json_object_object_get(registers, "rax")); 895 register_state.Rbx = json_object_get_uint64( 896 json_object_object_get(registers, "rbx")); 897 register_state.Rcx = json_object_get_uint64( 898 json_object_object_get(registers, "rcx")); 899 register_state.Rdx = json_object_get_uint64( 900 json_object_object_get(registers, "rdx")); 901 register_state.Rsi = json_object_get_uint64( 902 json_object_object_get(registers, "rsi")); 903 register_state.Rdi = json_object_get_uint64( 904 json_object_object_get(registers, "rdi")); 905 register_state.Rbp = json_object_get_uint64( 906 json_object_object_get(registers, "rbp")); 907 register_state.Rsp = json_object_get_uint64( 908 json_object_object_get(registers, "rsp")); 909 register_state.R8 = 910 json_object_get_uint64(json_object_object_get(registers, "r8")); 911 register_state.R9 = 912 json_object_get_uint64(json_object_object_get(registers, "r9")); 913 register_state.R10 = json_object_get_uint64( 914 json_object_object_get(registers, "r10")); 915 register_state.R11 = json_object_get_uint64( 916 json_object_object_get(registers, "r11")); 917 register_state.R12 = json_object_get_uint64( 918 json_object_object_get(registers, "r12")); 919 register_state.R13 = json_object_get_uint64( 920 json_object_object_get(registers, "r13")); 921 register_state.R14 = json_object_get_uint64( 922 json_object_object_get(registers, "r14")); 923 register_state.R15 = json_object_get_uint64( 924 json_object_object_get(registers, "r15")); 925 register_state.Cs = (UINT16)json_object_get_int( 926 json_object_object_get(registers, "cs")); 927 register_state.Ds = (UINT16)json_object_get_int( 928 json_object_object_get(registers, "ds")); 929 register_state.Ss = (UINT16)json_object_get_int( 930 json_object_object_get(registers, "ss")); 931 register_state.Es = (UINT16)json_object_get_int( 932 json_object_object_get(registers, "es")); 933 register_state.Fs = (UINT16)json_object_get_int( 934 json_object_object_get(registers, "fs")); 935 register_state.Gs = (UINT16)json_object_get_int( 936 json_object_object_get(registers, "gs")); 937 register_state.Resv1 = 0; 938 register_state.Rflags = json_object_get_uint64( 939 json_object_object_get(registers, "rflags")); 940 register_state.Rip = json_object_get_uint64( 941 json_object_object_get(registers, "eip")); 942 register_state.Cr0 = json_object_get_uint64( 943 json_object_object_get(registers, "cr0")); 944 register_state.Cr1 = json_object_get_uint64( 945 json_object_object_get(registers, "cr1")); 946 register_state.Cr2 = json_object_get_uint64( 947 json_object_object_get(registers, "cr2")); 948 register_state.Cr3 = json_object_get_uint64( 949 json_object_object_get(registers, "cr3")); 950 register_state.Cr4 = json_object_get_uint64( 951 json_object_object_get(registers, "cr4")); 952 register_state.Cr8 = json_object_get_uint64( 953 json_object_object_get(registers, "cr8")); 954 register_state.Gdtr[0] = json_object_get_uint64( 955 json_object_object_get(registers, "gdtr_0")); 956 register_state.Gdtr[1] = json_object_get_uint64( 957 json_object_object_get(registers, "gdtr_1")); 958 register_state.Idtr[0] = json_object_get_uint64( 959 json_object_object_get(registers, "idtr_0")); 960 register_state.Idtr[1] = json_object_get_uint64( 961 json_object_object_get(registers, "idtr_1")); 962 register_state.Ldtr = (UINT16)json_object_get_int( 963 json_object_object_get(registers, "ldtr")); 964 register_state.Tr = (UINT16)json_object_get_int( 965 json_object_object_get(registers, "tr")); 966 967 //Write out to stream. 968 fwrite(®ister_state, sizeof(EFI_CONTEXT_X64_REGISTER_STATE), 1, out); 969 fflush(out); 970 }