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