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