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