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 "libbase64.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 *cper_section_ia32x64_to_ir(void *section) 47 { 48 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *record = 49 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)section; 50 json_object *record_ir = json_object_new_object(); 51 52 //Validation bits. 53 json_object *validationBits = json_object_new_object(); 54 json_object_object_add(validationBits, "localAPICIDValid", 55 json_object_new_boolean(record->ValidFields & 56 0x1)); 57 json_object_object_add( 58 validationBits, "cpuIDInfoValid", 59 json_object_new_boolean((record->ValidFields >> 1) & 0x1)); 60 int processor_error_info_num = (record->ValidFields >> 2) & 0x3F; 61 json_object_object_add(validationBits, "processorErrorInfoNum", 62 json_object_new_int(processor_error_info_num)); 63 int processor_context_info_num = (record->ValidFields >> 8) & 0x3F; 64 json_object_object_add(validationBits, "processorContextInfoNum", 65 json_object_new_int(processor_context_info_num)); 66 json_object_object_add(record_ir, "validationBits", validationBits); 67 68 //APIC ID. 69 json_object_object_add(record_ir, "localAPICID", 70 json_object_new_uint64(record->ApicId)); 71 72 //CPUID information. 73 json_object *cpuid_info_ir = json_object_new_object(); 74 EFI_IA32_X64_CPU_ID *cpuid_info = 75 (EFI_IA32_X64_CPU_ID *)record->CpuIdInfo; 76 json_object_object_add(cpuid_info_ir, "eax", 77 json_object_new_uint64(cpuid_info->Eax)); 78 json_object_object_add(cpuid_info_ir, "ebx", 79 json_object_new_uint64(cpuid_info->Ebx)); 80 json_object_object_add(cpuid_info_ir, "ecx", 81 json_object_new_uint64(cpuid_info->Ecx)); 82 json_object_object_add(cpuid_info_ir, "edx", 83 json_object_new_uint64(cpuid_info->Edx)); 84 json_object_object_add(record_ir, "cpuidInfo", cpuid_info_ir); 85 86 //Processor error information, of the amount described above. 87 EFI_IA32_X64_PROCESS_ERROR_INFO *current_error_info = 88 (EFI_IA32_X64_PROCESS_ERROR_INFO *)(record + 1); 89 json_object *error_info_array = json_object_new_array(); 90 for (int i = 0; i < processor_error_info_num; i++) { 91 json_object_array_add(error_info_array, 92 cper_ia32x64_processor_error_info_to_ir( 93 current_error_info)); 94 current_error_info++; 95 } 96 json_object_object_add(record_ir, "processorErrorInfo", 97 error_info_array); 98 99 //Processor context information, of the amount described above. 100 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *current_context_info = 101 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)current_error_info; 102 void *cur_pos = (void *)current_context_info; 103 json_object *context_info_array = json_object_new_array(); 104 for (int i = 0; i < processor_context_info_num; i++) { 105 json_object_array_add(context_info_array, 106 cper_ia32x64_processor_context_info_to_ir( 107 current_context_info, &cur_pos)); 108 current_context_info = 109 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)cur_pos; 110 //The context array is a non-fixed size, pointer is shifted within the above function. 111 } 112 json_object_object_add(record_ir, "processorContextInfo", 113 context_info_array); 114 115 return record_ir; 116 } 117 118 //Converts a single IA32/x64 processor error info block into JSON IR format. 119 json_object *cper_ia32x64_processor_error_info_to_ir( 120 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info) 121 { 122 json_object *error_info_ir = json_object_new_object(); 123 124 //Error structure type (as GUID). 125 char error_type[GUID_STRING_LENGTH]; 126 guid_to_string(error_type, &error_info->ErrorType); 127 json_object *type = json_object_new_object(); 128 json_object_object_add(type, "guid", 129 json_object_new_string(error_type)); 130 131 //Get the error structure type as a readable string. 132 const char *readable_type = "Unknown"; 133 if (guid_equal(&error_info->ErrorType, 134 &gEfiIa32x64ErrorTypeCacheCheckGuid)) { 135 readable_type = "Cache Check Error"; 136 } else if (guid_equal(&error_info->ErrorType, 137 &gEfiIa32x64ErrorTypeTlbCheckGuid)) { 138 readable_type = "TLB Check Error"; 139 } else if (guid_equal(&error_info->ErrorType, 140 &gEfiIa32x64ErrorTypeBusCheckGuid)) { 141 readable_type = "Bus Check Error"; 142 } else if (guid_equal(&error_info->ErrorType, 143 &gEfiIa32x64ErrorTypeMsCheckGuid)) { 144 readable_type = "MS Check Error"; 145 } 146 json_object_object_add(type, "name", 147 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 = malloc(2 * context_info->ArraySize); 394 size_t encoded_len = 0; 395 if (!encoded) { 396 printf("Failed to allocate encode output buffer. \n"); 397 } else { 398 base64_encode((const char *)*cur_pos, 399 context_info->ArraySize, encoded, 400 &encoded_len, 0); 401 402 register_array = json_object_new_object(); 403 json_object_object_add(register_array, "data", 404 json_object_new_string_len( 405 encoded, encoded_len)); 406 free(encoded); 407 } 408 409 *cur_pos = 410 (void *)(((char *)*cur_pos) + context_info->ArraySize); 411 } 412 json_object_object_add(context_info_ir, "registerArray", 413 register_array); 414 415 return context_info_ir; 416 } 417 418 //Converts a single CPER IA32 register state into JSON IR format. 419 json_object * 420 cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers) 421 { 422 json_object *ia32_registers = json_object_new_object(); 423 json_object_object_add(ia32_registers, "eax", 424 json_object_new_uint64(registers->Eax)); 425 json_object_object_add(ia32_registers, "ebx", 426 json_object_new_uint64(registers->Ebx)); 427 json_object_object_add(ia32_registers, "ecx", 428 json_object_new_uint64(registers->Ecx)); 429 json_object_object_add(ia32_registers, "edx", 430 json_object_new_uint64(registers->Edx)); 431 json_object_object_add(ia32_registers, "esi", 432 json_object_new_uint64(registers->Esi)); 433 json_object_object_add(ia32_registers, "edi", 434 json_object_new_uint64(registers->Edi)); 435 json_object_object_add(ia32_registers, "ebp", 436 json_object_new_uint64(registers->Ebp)); 437 json_object_object_add(ia32_registers, "esp", 438 json_object_new_uint64(registers->Esp)); 439 json_object_object_add(ia32_registers, "cs", 440 json_object_new_uint64(registers->Cs)); 441 json_object_object_add(ia32_registers, "ds", 442 json_object_new_uint64(registers->Ds)); 443 json_object_object_add(ia32_registers, "ss", 444 json_object_new_uint64(registers->Ss)); 445 json_object_object_add(ia32_registers, "es", 446 json_object_new_uint64(registers->Es)); 447 json_object_object_add(ia32_registers, "fs", 448 json_object_new_uint64(registers->Fs)); 449 json_object_object_add(ia32_registers, "gs", 450 json_object_new_uint64(registers->Gs)); 451 json_object_object_add(ia32_registers, "eflags", 452 json_object_new_uint64(registers->Eflags)); 453 json_object_object_add(ia32_registers, "eip", 454 json_object_new_uint64(registers->Eip)); 455 json_object_object_add(ia32_registers, "cr0", 456 json_object_new_uint64(registers->Cr0)); 457 json_object_object_add(ia32_registers, "cr1", 458 json_object_new_uint64(registers->Cr1)); 459 json_object_object_add(ia32_registers, "cr2", 460 json_object_new_uint64(registers->Cr2)); 461 json_object_object_add(ia32_registers, "cr3", 462 json_object_new_uint64(registers->Cr3)); 463 json_object_object_add(ia32_registers, "cr4", 464 json_object_new_uint64(registers->Cr4)); 465 json_object_object_add( 466 ia32_registers, "gdtr", 467 json_object_new_uint64(registers->Gdtr[0] + 468 ((UINT64)registers->Gdtr[1] << 32))); 469 json_object_object_add( 470 ia32_registers, "idtr", 471 json_object_new_uint64(registers->Idtr[0] + 472 ((UINT64)registers->Idtr[1] << 32))); 473 json_object_object_add(ia32_registers, "ldtr", 474 json_object_new_uint64(registers->Ldtr)); 475 json_object_object_add(ia32_registers, "tr", 476 json_object_new_uint64(registers->Tr)); 477 478 return ia32_registers; 479 } 480 481 //Converts a single CPER x64 register state into JSON IR format. 482 json_object * 483 cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers) 484 { 485 json_object *x64_registers = json_object_new_object(); 486 json_object_object_add(x64_registers, "rax", 487 json_object_new_uint64(registers->Rax)); 488 json_object_object_add(x64_registers, "rbx", 489 json_object_new_uint64(registers->Rbx)); 490 json_object_object_add(x64_registers, "rcx", 491 json_object_new_uint64(registers->Rcx)); 492 json_object_object_add(x64_registers, "rdx", 493 json_object_new_uint64(registers->Rdx)); 494 json_object_object_add(x64_registers, "rsi", 495 json_object_new_uint64(registers->Rsi)); 496 json_object_object_add(x64_registers, "rdi", 497 json_object_new_uint64(registers->Rdi)); 498 json_object_object_add(x64_registers, "rbp", 499 json_object_new_uint64(registers->Rbp)); 500 json_object_object_add(x64_registers, "rsp", 501 json_object_new_uint64(registers->Rsp)); 502 json_object_object_add(x64_registers, "r8", 503 json_object_new_uint64(registers->R8)); 504 json_object_object_add(x64_registers, "r9", 505 json_object_new_uint64(registers->R9)); 506 json_object_object_add(x64_registers, "r10", 507 json_object_new_uint64(registers->R10)); 508 json_object_object_add(x64_registers, "r11", 509 json_object_new_uint64(registers->R11)); 510 json_object_object_add(x64_registers, "r12", 511 json_object_new_uint64(registers->R12)); 512 json_object_object_add(x64_registers, "r13", 513 json_object_new_uint64(registers->R13)); 514 json_object_object_add(x64_registers, "r14", 515 json_object_new_uint64(registers->R14)); 516 json_object_object_add(x64_registers, "r15", 517 json_object_new_uint64(registers->R15)); 518 json_object_object_add(x64_registers, "cs", 519 json_object_new_int(registers->Cs)); 520 json_object_object_add(x64_registers, "ds", 521 json_object_new_int(registers->Ds)); 522 json_object_object_add(x64_registers, "ss", 523 json_object_new_int(registers->Ss)); 524 json_object_object_add(x64_registers, "es", 525 json_object_new_int(registers->Es)); 526 json_object_object_add(x64_registers, "fs", 527 json_object_new_int(registers->Fs)); 528 json_object_object_add(x64_registers, "gs", 529 json_object_new_int(registers->Gs)); 530 json_object_object_add(x64_registers, "rflags", 531 json_object_new_uint64(registers->Rflags)); 532 json_object_object_add(x64_registers, "eip", 533 json_object_new_uint64(registers->Rip)); 534 json_object_object_add(x64_registers, "cr0", 535 json_object_new_uint64(registers->Cr0)); 536 json_object_object_add(x64_registers, "cr1", 537 json_object_new_uint64(registers->Cr1)); 538 json_object_object_add(x64_registers, "cr2", 539 json_object_new_uint64(registers->Cr2)); 540 json_object_object_add(x64_registers, "cr3", 541 json_object_new_uint64(registers->Cr3)); 542 json_object_object_add(x64_registers, "cr4", 543 json_object_new_uint64(registers->Cr4)); 544 json_object_object_add(x64_registers, "cr8", 545 json_object_new_uint64(registers->Cr8)); 546 json_object_object_add(x64_registers, "gdtr_0", 547 json_object_new_uint64(registers->Gdtr[0])); 548 json_object_object_add(x64_registers, "gdtr_1", 549 json_object_new_uint64(registers->Gdtr[1])); 550 json_object_object_add(x64_registers, "idtr_0", 551 json_object_new_uint64(registers->Idtr[0])); 552 json_object_object_add(x64_registers, "idtr_1", 553 json_object_new_uint64(registers->Idtr[1])); 554 json_object_object_add(x64_registers, "ldtr", 555 json_object_new_int(registers->Ldtr)); 556 json_object_object_add(x64_registers, "tr", 557 json_object_new_int(registers->Tr)); 558 559 return x64_registers; 560 } 561 562 ////////////////// 563 /// IR TO CPER /// 564 ////////////////// 565 566 //Converts a single IA32/x64 CPER-JSON section into CPER binary, outputting to the provided stream. 567 void ir_section_ia32x64_to_cper(json_object *section, FILE *out) 568 { 569 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *section_cper = 570 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)calloc( 571 1, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD)); 572 573 //Validation bits. 574 json_object *validation = 575 json_object_object_get(section, "validationBits"); 576 section_cper->ValidFields = 0x0; 577 section_cper->ValidFields |= json_object_get_boolean( 578 json_object_object_get(validation, "localAPICIDValid")); 579 section_cper->ValidFields |= 580 json_object_get_boolean( 581 json_object_object_get(validation, "cpuIDInfoValid")) 582 << 1; 583 int proc_error_info_num = 584 json_object_get_int(json_object_object_get( 585 validation, "processorErrorInfoNum")) & 586 0x3F; 587 int proc_ctx_info_num = 588 json_object_get_int(json_object_object_get( 589 validation, "processorContextInfoNum")) & 590 0x3F; 591 section_cper->ValidFields |= proc_error_info_num << 2; 592 section_cper->ValidFields |= proc_ctx_info_num << 8; 593 594 //Local APIC ID. 595 section_cper->ApicId = json_object_get_uint64( 596 json_object_object_get(section, "localAPICID")); 597 598 //CPUID info. 599 json_object *cpuid_info = json_object_object_get(section, "cpuidInfo"); 600 EFI_IA32_X64_CPU_ID *cpuid_info_cper = 601 (EFI_IA32_X64_CPU_ID *)section_cper->CpuIdInfo; 602 cpuid_info_cper->Eax = json_object_get_uint64( 603 json_object_object_get(cpuid_info, "eax")); 604 cpuid_info_cper->Ebx = json_object_get_uint64( 605 json_object_object_get(cpuid_info, "ebx")); 606 cpuid_info_cper->Ecx = json_object_get_uint64( 607 json_object_object_get(cpuid_info, "ecx")); 608 cpuid_info_cper->Edx = json_object_get_uint64( 609 json_object_object_get(cpuid_info, "edx")); 610 611 //Flush the header to file before dealing w/ info sections. 612 fwrite(section_cper, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD), 1, 613 out); 614 fflush(out); 615 free(section_cper); 616 617 //Iterate and deal with sections. 618 json_object *error_info = 619 json_object_object_get(section, "processorErrorInfo"); 620 json_object *context_info = 621 json_object_object_get(section, "processorContextInfo"); 622 for (int i = 0; i < proc_error_info_num; i++) { 623 ir_ia32x64_error_info_to_cper( 624 json_object_array_get_idx(error_info, i), out); 625 } 626 for (int i = 0; i < proc_ctx_info_num; i++) { 627 ir_ia32x64_context_info_to_cper( 628 json_object_array_get_idx(context_info, i), out); 629 } 630 } 631 632 //Converts a single CPER-JSON IA32/x64 error information structure into CPER binary, outputting to the 633 //provided stream. 634 void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out) 635 { 636 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info_cper = 637 (EFI_IA32_X64_PROCESS_ERROR_INFO *)calloc( 638 1, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO)); 639 640 //Error structure type. 641 json_object *type = json_object_object_get(error_info, "type"); 642 string_to_guid( 643 &error_info_cper->ErrorType, 644 json_object_get_string(json_object_object_get(type, "guid"))); 645 646 //Validation bits. 647 error_info_cper->ValidFields = ir_to_bitfield( 648 json_object_object_get(error_info, "validationBits"), 5, 649 IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES); 650 651 //Check information, parsed based on the error type. 652 json_object *check_info = 653 json_object_object_get(error_info, "checkInfo"); 654 if (guid_equal(&error_info_cper->ErrorType, 655 &gEfiIa32x64ErrorTypeCacheCheckGuid) || 656 guid_equal(&error_info_cper->ErrorType, 657 &gEfiIa32x64ErrorTypeTlbCheckGuid)) { 658 ir_ia32x64_cache_tlb_check_error_to_cper( 659 check_info, 660 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info_cper 661 ->CheckInfo); 662 } else if (guid_equal(&error_info_cper->ErrorType, 663 &gEfiIa32x64ErrorTypeBusCheckGuid)) { 664 ir_ia32x64_bus_check_error_to_cper( 665 check_info, 666 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info_cper 667 ->CheckInfo); 668 } else if (guid_equal(&error_info_cper->ErrorType, 669 &gEfiIa32x64ErrorTypeMsCheckGuid)) { 670 ir_ia32x64_ms_check_error_to_cper( 671 check_info, 672 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info_cper 673 ->CheckInfo); 674 } 675 676 //Miscellaneous numeric fields. 677 error_info_cper->TargetId = json_object_get_uint64( 678 json_object_object_get(error_info, "targetAddressID")); 679 error_info_cper->RequestorId = json_object_get_uint64( 680 json_object_object_get(error_info, "requestorID")); 681 error_info_cper->ResponderId = json_object_get_uint64( 682 json_object_object_get(error_info, "responderID")); 683 error_info_cper->InstructionIP = json_object_get_uint64( 684 json_object_object_get(error_info, "instructionPointer")); 685 686 //Write out to stream, then free resources. 687 fwrite(error_info_cper, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO), 1, 688 out); 689 fflush(out); 690 free(error_info_cper); 691 } 692 693 //Converts a single CPER-JSON IA32/x64 cache/TLB check error info structure to CPER binary. 694 void ir_ia32x64_cache_tlb_check_error_to_cper( 695 json_object *check_info, EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper) 696 { 697 //Validation bits. 698 check_info_cper->ValidFields = ir_to_bitfield( 699 json_object_object_get(check_info, "validationBits"), 8, 700 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 701 702 //Transaction type, operation. 703 check_info_cper->TransactionType = readable_pair_to_integer( 704 json_object_object_get(check_info, "transactionType")); 705 check_info_cper->Operation = readable_pair_to_integer( 706 json_object_object_get(check_info, "operation")); 707 708 //Miscellaneous raw value fields. 709 check_info_cper->Level = json_object_get_uint64( 710 json_object_object_get(check_info, "level")); 711 check_info_cper->ContextCorrupt = json_object_get_boolean( 712 json_object_object_get(check_info, "processorContextCorrupt")); 713 check_info_cper->ErrorUncorrected = json_object_get_boolean( 714 json_object_object_get(check_info, "uncorrected")); 715 check_info_cper->PreciseIp = json_object_get_boolean( 716 json_object_object_get(check_info, "preciseIP")); 717 check_info_cper->RestartableIp = json_object_get_boolean( 718 json_object_object_get(check_info, "restartableIP")); 719 check_info_cper->Overflow = json_object_get_boolean( 720 json_object_object_get(check_info, "overflow")); 721 } 722 723 //Converts a single CPER-JSON IA32/x64 bus error info structure to CPER binary. 724 void ir_ia32x64_bus_check_error_to_cper( 725 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper) 726 { 727 //Validation bits. 728 check_info_cper->ValidFields = ir_to_bitfield( 729 json_object_object_get(check_info, "validationBits"), 11, 730 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 731 732 //Readable pair fields. 733 check_info_cper->TransactionType = readable_pair_to_integer( 734 json_object_object_get(check_info, "transactionType")); 735 check_info_cper->Operation = readable_pair_to_integer( 736 json_object_object_get(check_info, "operation")); 737 check_info_cper->ParticipationType = readable_pair_to_integer( 738 json_object_object_get(check_info, "participationType")); 739 check_info_cper->AddressSpace = readable_pair_to_integer( 740 json_object_object_get(check_info, "addressSpace")); 741 742 //Miscellaneous raw value fields. 743 check_info_cper->Level = json_object_get_uint64( 744 json_object_object_get(check_info, "level")); 745 check_info_cper->ContextCorrupt = json_object_get_boolean( 746 json_object_object_get(check_info, "processorContextCorrupt")); 747 check_info_cper->ErrorUncorrected = json_object_get_boolean( 748 json_object_object_get(check_info, "uncorrected")); 749 check_info_cper->PreciseIp = json_object_get_boolean( 750 json_object_object_get(check_info, "preciseIP")); 751 check_info_cper->RestartableIp = json_object_get_boolean( 752 json_object_object_get(check_info, "restartableIP")); 753 check_info_cper->Overflow = json_object_get_boolean( 754 json_object_object_get(check_info, "overflow")); 755 check_info_cper->TimeOut = json_object_get_boolean( 756 json_object_object_get(check_info, "timedOut")); 757 } 758 759 //Converts a single CPER-JSON IA32/x64 MS error info structure to CPER binary. 760 void ir_ia32x64_ms_check_error_to_cper( 761 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper) 762 { 763 //Validation bits. 764 check_info_cper->ValidFields = ir_to_bitfield( 765 json_object_object_get(check_info, "validationBits"), 6, 766 IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES); 767 768 //Type of MS check error. 769 check_info_cper->ErrorType = readable_pair_to_integer( 770 json_object_object_get(check_info, "errorType")); 771 772 //Miscellaneous raw value fields. 773 check_info_cper->ContextCorrupt = json_object_get_boolean( 774 json_object_object_get(check_info, "processorContextCorrupt")); 775 check_info_cper->ErrorUncorrected = json_object_get_boolean( 776 json_object_object_get(check_info, "uncorrected")); 777 check_info_cper->PreciseIp = json_object_get_boolean( 778 json_object_object_get(check_info, "preciseIP")); 779 check_info_cper->RestartableIp = json_object_get_boolean( 780 json_object_object_get(check_info, "restartableIP")); 781 check_info_cper->Overflow = json_object_get_boolean( 782 json_object_object_get(check_info, "overflow")); 783 } 784 785 //Converts a single CPER-JSON IA32/x64 context information structure into CPER binary, outputting to the 786 //provided stream. 787 void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out) 788 { 789 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info_cper = 790 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)calloc( 791 1, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO)); 792 793 //Register context type. 794 context_info_cper->RegisterType = (UINT16)readable_pair_to_integer( 795 json_object_object_get(context_info, "registerContextType")); 796 797 //Miscellaneous numeric fields. 798 context_info_cper->ArraySize = (UINT16)json_object_get_uint64( 799 json_object_object_get(context_info, "registerArraySize")); 800 context_info_cper->MsrAddress = (UINT32)json_object_get_uint64( 801 json_object_object_get(context_info, "msrAddress")); 802 context_info_cper->MmRegisterAddress = json_object_get_uint64( 803 json_object_object_get(context_info, "mmRegisterAddress")); 804 805 //Flush header to stream. 806 fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO), 807 1, out); 808 fflush(out); 809 810 //Handle the register array, depending on type provided. 811 json_object *register_array = 812 json_object_object_get(context_info, "registerArray"); 813 if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) { 814 ir_ia32x64_ia32_registers_to_cper(register_array, out); 815 } else if (context_info_cper->RegisterType == 816 EFI_REG_CONTEXT_TYPE_X64) { 817 ir_ia32x64_x64_registers_to_cper(register_array, out); 818 } else { 819 //Unknown/structure is not defined. 820 json_object *encoded = 821 json_object_object_get(register_array, "data"); 822 char *decoded = malloc(json_object_get_string_len(encoded)); 823 size_t decoded_len = 0; 824 if (!decoded) { 825 printf("Failed to allocate decode output buffer. \n"); 826 } else { 827 base64_decode(json_object_get_string(encoded), 828 json_object_get_string_len(encoded), 829 decoded, &decoded_len, 0); 830 fwrite(decoded, decoded_len, 1, out); 831 fflush(out); 832 free(decoded); 833 } 834 } 835 836 //Free remaining resources. 837 free(context_info_cper); 838 } 839 840 //Converts a single CPER-JSON IA32 register array into CPER binary, outputting to the given stream. 841 void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out) 842 { 843 EFI_CONTEXT_IA32_REGISTER_STATE register_state; 844 register_state.Eax = (UINT32)json_object_get_uint64( 845 json_object_object_get(registers, "eax")); 846 register_state.Ebx = (UINT32)json_object_get_uint64( 847 json_object_object_get(registers, "ebx")); 848 register_state.Ecx = (UINT32)json_object_get_uint64( 849 json_object_object_get(registers, "ecx")); 850 register_state.Edx = (UINT32)json_object_get_uint64( 851 json_object_object_get(registers, "edx")); 852 register_state.Esi = (UINT32)json_object_get_uint64( 853 json_object_object_get(registers, "esi")); 854 register_state.Edi = (UINT32)json_object_get_uint64( 855 json_object_object_get(registers, "edi")); 856 register_state.Ebp = (UINT32)json_object_get_uint64( 857 json_object_object_get(registers, "ebp")); 858 register_state.Esp = (UINT32)json_object_get_uint64( 859 json_object_object_get(registers, "esp")); 860 register_state.Cs = (UINT16)json_object_get_uint64( 861 json_object_object_get(registers, "cs")); 862 register_state.Ds = (UINT32)json_object_get_uint64( 863 json_object_object_get(registers, "ds")); 864 register_state.Ss = (UINT16)json_object_get_uint64( 865 json_object_object_get(registers, "ss")); 866 register_state.Es = (UINT16)json_object_get_uint64( 867 json_object_object_get(registers, "es")); 868 register_state.Fs = (UINT16)json_object_get_uint64( 869 json_object_object_get(registers, "fs")); 870 register_state.Gs = (UINT16)json_object_get_uint64( 871 json_object_object_get(registers, "gs")); 872 register_state.Eflags = (UINT32)json_object_get_uint64( 873 json_object_object_get(registers, "eflags")); 874 register_state.Eip = (UINT32)json_object_get_uint64( 875 json_object_object_get(registers, "eip")); 876 register_state.Cr0 = (UINT32)json_object_get_uint64( 877 json_object_object_get(registers, "cr0")); 878 register_state.Cr1 = (UINT32)json_object_get_uint64( 879 json_object_object_get(registers, "cr1")); 880 register_state.Cr2 = (UINT32)json_object_get_uint64( 881 json_object_object_get(registers, "cr2")); 882 register_state.Cr3 = (UINT32)json_object_get_uint64( 883 json_object_object_get(registers, "cr3")); 884 register_state.Cr4 = (UINT32)json_object_get_uint64( 885 json_object_object_get(registers, "cr4")); 886 887 //64-bit registers are split into two 32-bit parts. 888 UINT64 gdtr = json_object_get_uint64( 889 json_object_object_get(registers, "gdtr")); 890 register_state.Gdtr[0] = gdtr & 0xFFFFFFFF; 891 register_state.Gdtr[1] = gdtr >> 32; 892 UINT64 idtr = json_object_get_uint64( 893 json_object_object_get(registers, "idtr")); 894 register_state.Idtr[0] = idtr & 0xFFFFFFFF; 895 register_state.Idtr[1] = idtr >> 32; 896 897 //16-bit registers. 898 register_state.Ldtr = (UINT16)json_object_get_uint64( 899 json_object_object_get(registers, "ldtr")); 900 register_state.Tr = (UINT16)json_object_get_uint64( 901 json_object_object_get(registers, "tr")); 902 903 //Write out to stream. 904 fwrite(®ister_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1, 905 out); 906 fflush(out); 907 } 908 909 //Converts a single CPER-JSON x64 register array into CPER binary, outputting to the given stream. 910 void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out) 911 { 912 EFI_CONTEXT_X64_REGISTER_STATE register_state; 913 register_state.Rax = json_object_get_uint64( 914 json_object_object_get(registers, "rax")); 915 register_state.Rbx = json_object_get_uint64( 916 json_object_object_get(registers, "rbx")); 917 register_state.Rcx = json_object_get_uint64( 918 json_object_object_get(registers, "rcx")); 919 register_state.Rdx = json_object_get_uint64( 920 json_object_object_get(registers, "rdx")); 921 register_state.Rsi = json_object_get_uint64( 922 json_object_object_get(registers, "rsi")); 923 register_state.Rdi = json_object_get_uint64( 924 json_object_object_get(registers, "rdi")); 925 register_state.Rbp = json_object_get_uint64( 926 json_object_object_get(registers, "rbp")); 927 register_state.Rsp = json_object_get_uint64( 928 json_object_object_get(registers, "rsp")); 929 register_state.R8 = 930 json_object_get_uint64(json_object_object_get(registers, "r8")); 931 register_state.R9 = 932 json_object_get_uint64(json_object_object_get(registers, "r9")); 933 register_state.R10 = json_object_get_uint64( 934 json_object_object_get(registers, "r10")); 935 register_state.R11 = json_object_get_uint64( 936 json_object_object_get(registers, "r11")); 937 register_state.R12 = json_object_get_uint64( 938 json_object_object_get(registers, "r12")); 939 register_state.R13 = json_object_get_uint64( 940 json_object_object_get(registers, "r13")); 941 register_state.R14 = json_object_get_uint64( 942 json_object_object_get(registers, "r14")); 943 register_state.R15 = json_object_get_uint64( 944 json_object_object_get(registers, "r15")); 945 register_state.Cs = (UINT16)json_object_get_int( 946 json_object_object_get(registers, "cs")); 947 register_state.Ds = (UINT16)json_object_get_int( 948 json_object_object_get(registers, "ds")); 949 register_state.Ss = (UINT16)json_object_get_int( 950 json_object_object_get(registers, "ss")); 951 register_state.Es = (UINT16)json_object_get_int( 952 json_object_object_get(registers, "es")); 953 register_state.Fs = (UINT16)json_object_get_int( 954 json_object_object_get(registers, "fs")); 955 register_state.Gs = (UINT16)json_object_get_int( 956 json_object_object_get(registers, "gs")); 957 register_state.Resv1 = 0; 958 register_state.Rflags = json_object_get_uint64( 959 json_object_object_get(registers, "rflags")); 960 register_state.Rip = json_object_get_uint64( 961 json_object_object_get(registers, "eip")); 962 register_state.Cr0 = json_object_get_uint64( 963 json_object_object_get(registers, "cr0")); 964 register_state.Cr1 = json_object_get_uint64( 965 json_object_object_get(registers, "cr1")); 966 register_state.Cr2 = json_object_get_uint64( 967 json_object_object_get(registers, "cr2")); 968 register_state.Cr3 = json_object_get_uint64( 969 json_object_object_get(registers, "cr3")); 970 register_state.Cr4 = json_object_get_uint64( 971 json_object_object_get(registers, "cr4")); 972 register_state.Cr8 = json_object_get_uint64( 973 json_object_object_get(registers, "cr8")); 974 register_state.Gdtr[0] = json_object_get_uint64( 975 json_object_object_get(registers, "gdtr_0")); 976 register_state.Gdtr[1] = json_object_get_uint64( 977 json_object_object_get(registers, "gdtr_1")); 978 register_state.Idtr[0] = json_object_get_uint64( 979 json_object_object_get(registers, "idtr_0")); 980 register_state.Idtr[1] = json_object_get_uint64( 981 json_object_object_get(registers, "idtr_1")); 982 register_state.Ldtr = (UINT16)json_object_get_int( 983 json_object_object_get(registers, "ldtr")); 984 register_state.Tr = (UINT16)json_object_get_int( 985 json_object_object_get(registers, "tr")); 986 987 //Write out to stream. 988 fwrite(®ister_state, sizeof(EFI_CONTEXT_X64_REGISTER_STATE), 1, out); 989 fflush(out); 990 } 991