1 /** 2 * Describes functions for converting ARM CPER sections from binary and JSON format 3 * into an intermediate format. 4 * 5 * Author: Lawrence.Tang@arm.com 6 **/ 7 8 #include <stdio.h> 9 #include <json.h> 10 #include <libcper/base64.h> 11 #include <libcper/Cper.h> 12 #include <libcper/cper-utils.h> 13 #include <libcper/sections/cper-section-arm.h> 14 15 //Private pre-definitions. 16 json_object * 17 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info); 18 json_object * 19 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 20 void **cur_pos); 21 json_object * 22 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 23 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info); 24 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error); 25 json_object *cper_arm_misc_register_array_to_ir( 26 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register); 27 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out); 28 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out); 29 void ir_arm_error_cache_tlb_info_to_cper( 30 json_object *error_information, 31 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper); 32 void ir_arm_error_bus_info_to_cper(json_object *error_information, 33 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper); 34 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out); 35 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out); 36 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out); 37 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out); 38 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out); 39 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out); 40 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out); 41 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out); 42 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out); 43 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out); 44 45 //Converts the given processor-generic CPER section into JSON IR. 46 json_object *cper_section_arm_to_ir(void *section) 47 { 48 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section; 49 json_object *section_ir = json_object_new_object(); 50 51 //Validation bits. 52 json_object *validation = bitfield_to_ir( 53 record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES); 54 json_object_object_add(section_ir, "validationBits", validation); 55 56 //Number of error info and context info structures, and length. 57 json_object_object_add(section_ir, "errorInfoNum", 58 json_object_new_int(record->ErrInfoNum)); 59 json_object_object_add(section_ir, "contextInfoNum", 60 json_object_new_int(record->ContextInfoNum)); 61 json_object_object_add(section_ir, "sectionLength", 62 json_object_new_uint64(record->SectionLength)); 63 64 //Error affinity. 65 json_object *error_affinity = json_object_new_object(); 66 json_object_object_add(error_affinity, "value", 67 json_object_new_int(record->ErrorAffinityLevel)); 68 json_object_object_add( 69 error_affinity, "type", 70 json_object_new_string(record->ErrorAffinityLevel < 4 ? 71 "Vendor Defined" : 72 "Reserved")); 73 json_object_object_add(section_ir, "errorAffinity", error_affinity); 74 75 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1). 76 uint64_t sock; 77 uint64_t mpidr_eli1 = record->MPIDR_EL1; 78 json_object_object_add(section_ir, "mpidrEl1", 79 json_object_new_uint64(mpidr_eli1)); 80 //Arm Processor socket info 81 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32; 82 json_object_object_add(section_ir, "affinity3", 83 json_object_new_uint64(sock)); 84 85 json_object_object_add(section_ir, "midrEl1", 86 json_object_new_uint64(record->MIDR_EL1)); 87 88 //Whether the processor is running, and the state of it if so. 89 json_object_object_add(section_ir, "running", 90 json_object_new_boolean(record->RunningState & 91 0x1)); 92 if (!(record->RunningState >> 31)) { 93 //Bit 32 of running state is on, so PSCI state information is included. 94 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format 95 //or the newer Extended StateID format. 96 json_object_object_add( 97 section_ir, "psciState", 98 json_object_new_uint64(record->PsciState)); 99 } 100 101 //Processor error structures. 102 json_object *error_info_array = json_object_new_array(); 103 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error = 104 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1); 105 for (int i = 0; i < record->ErrInfoNum; i++) { 106 json_object_array_add(error_info_array, 107 cper_arm_error_info_to_ir(cur_error)); 108 cur_error++; 109 } 110 json_object_object_add(section_ir, "errorInfo", error_info_array); 111 112 //Processor context structures. 113 //The current position is moved within the processing, as it is a dynamic size structure. 114 uint8_t *cur_pos = (uint8_t *)cur_error; 115 json_object *context_info_array = json_object_new_array(); 116 for (int i = 0; i < record->ContextInfoNum; i++) { 117 EFI_ARM_CONTEXT_INFORMATION_HEADER *header = 118 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos; 119 json_object *processor_context = 120 cper_arm_processor_context_to_ir(header, 121 (void **)&cur_pos); 122 json_object_array_add(context_info_array, processor_context); 123 } 124 json_object_object_add(section_ir, "contextInfo", context_info_array); 125 126 //Is there any vendor-specific information following? 127 if (cur_pos < (uint8_t *)section + record->SectionLength) { 128 json_object *vendor_specific = json_object_new_object(); 129 size_t input_size = 130 (uint8_t *)section + record->SectionLength - cur_pos; 131 int32_t encoded_len = 0; 132 char *encoded = 133 base64_encode(cur_pos, input_size, &encoded_len); 134 if (encoded == NULL) { 135 return NULL; 136 } 137 json_object_object_add(vendor_specific, "data", 138 json_object_new_string_len(encoded, 139 encoded_len)); 140 free(encoded); 141 142 json_object_object_add(section_ir, "vendorSpecificInfo", 143 vendor_specific); 144 } 145 146 return section_ir; 147 } 148 149 //Converts a single ARM Process Error Information structure into JSON IR. 150 json_object * 151 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 152 { 153 json_object *error_info_ir = json_object_new_object(); 154 155 //Version, length. 156 json_object_object_add(error_info_ir, "version", 157 json_object_new_int(error_info->Version)); 158 json_object_object_add(error_info_ir, "length", 159 json_object_new_int(error_info->Length)); 160 161 //Validation bitfield. 162 json_object *validation = 163 bitfield_to_ir(error_info->ValidationBits, 5, 164 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 165 json_object_object_add(error_info_ir, "validationBits", validation); 166 167 //The type of error information in this log. 168 json_object *error_type = integer_to_readable_pair( 169 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS, 170 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)"); 171 json_object_object_add(error_info_ir, "errorType", error_type); 172 173 //Multiple error count. 174 json_object *multiple_error = json_object_new_object(); 175 json_object_object_add(multiple_error, "value", 176 json_object_new_int(error_info->MultipleError)); 177 json_object_object_add( 178 multiple_error, "type", 179 json_object_new_string(error_info->MultipleError < 1 ? 180 "Single Error" : 181 "Multiple Errors")); 182 json_object_object_add(error_info_ir, "multipleError", multiple_error); 183 184 //Flags. 185 json_object *flags = bitfield_to_ir(error_info->Flags, 4, 186 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 187 json_object_object_add(error_info_ir, "flags", flags); 188 189 //Error information, split by type. 190 json_object *error_subinfo = NULL; 191 switch (error_info->Type) { 192 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache 193 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB 194 error_subinfo = cper_arm_cache_tlb_error_to_ir( 195 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info 196 ->ErrorInformation, 197 error_info); 198 break; 199 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus 200 error_subinfo = cper_arm_bus_error_to_ir( 201 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info 202 ->ErrorInformation); 203 break; 204 205 default: 206 //Unknown/microarch, will not support. 207 break; 208 } 209 json_object_object_add(error_info_ir, "errorInformation", 210 error_subinfo); 211 212 //Virtual fault address, physical fault address. 213 json_object_object_add( 214 error_info_ir, "virtualFaultAddress", 215 json_object_new_uint64(error_info->VirtualFaultAddress)); 216 json_object_object_add( 217 error_info_ir, "physicalFaultAddress", 218 json_object_new_uint64(error_info->PhysicalFaultAddress)); 219 220 return error_info_ir; 221 } 222 223 //Converts a single ARM cache/TLB error information structure into JSON IR format. 224 json_object * 225 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 226 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 227 { 228 json_object *cache_tlb_error_ir = json_object_new_object(); 229 json_object *cache_tlb_prop = json_object_new_object(); 230 char *cache_tlb_propname; 231 232 //Validation bitfield. 233 json_object *validation = 234 bitfield_to_ir(cache_tlb_error->ValidationBits, 7, 235 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 236 json_object_object_add(cache_tlb_error_ir, "validationBits", 237 validation); 238 239 //Transaction type. 240 json_object *transaction_type = integer_to_readable_pair( 241 cache_tlb_error->TransactionType, 3, 242 ARM_ERROR_TRANSACTION_TYPES_KEYS, 243 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 244 json_object_object_add(cache_tlb_error_ir, "transactionType", 245 transaction_type); 246 247 //Operation. 248 json_object *operation; 249 if (error_info->Type == 0) { 250 //Cache operation. 251 operation = integer_to_readable_pair( 252 cache_tlb_error->Operation, 11, 253 ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 254 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 255 "Unknown (Reserved)"); 256 cache_tlb_propname = "cacheError"; 257 } else { 258 //TLB operation. 259 operation = integer_to_readable_pair( 260 cache_tlb_error->Operation, 9, 261 ARM_TLB_OPERATION_TYPES_KEYS, 262 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 263 cache_tlb_propname = "tlbError"; 264 } 265 json_object_object_add(cache_tlb_error_ir, "operation", operation); 266 267 //Miscellaneous remaining fields. 268 json_object_object_add(cache_tlb_error_ir, "level", 269 json_object_new_int(cache_tlb_error->Level)); 270 json_object_object_add( 271 cache_tlb_error_ir, "processorContextCorrupt", 272 json_object_new_boolean( 273 cache_tlb_error->ProcessorContextCorrupt)); 274 json_object_object_add( 275 cache_tlb_error_ir, "corrected", 276 json_object_new_boolean(cache_tlb_error->Corrected)); 277 json_object_object_add( 278 cache_tlb_error_ir, "precisePC", 279 json_object_new_boolean(cache_tlb_error->PrecisePC)); 280 json_object_object_add( 281 cache_tlb_error_ir, "restartablePC", 282 json_object_new_boolean(cache_tlb_error->RestartablePC)); 283 284 json_object_object_add(cache_tlb_prop, cache_tlb_propname, 285 cache_tlb_error_ir); 286 return cache_tlb_prop; 287 } 288 289 //Converts a single ARM bus error information structure into JSON IR format. 290 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error) 291 { 292 json_object *bus_error_ir = json_object_new_object(); 293 294 //Validation bits. 295 json_object *validation = 296 bitfield_to_ir(bus_error->ValidationBits, 12, 297 ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 298 json_object_object_add(bus_error_ir, "validationBits", validation); 299 300 //Transaction type. 301 json_object *transaction_type = integer_to_readable_pair( 302 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS, 303 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 304 json_object_object_add(bus_error_ir, "transactionType", 305 transaction_type); 306 307 //Operation. 308 json_object *operation = integer_to_readable_pair( 309 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 310 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 311 json_object_object_add(bus_error_ir, "operation", operation); 312 313 //Affinity level of bus error, + miscellaneous fields. 314 json_object_object_add(bus_error_ir, "level", 315 json_object_new_int(bus_error->Level)); 316 json_object_object_add( 317 bus_error_ir, "processorContextCorrupt", 318 json_object_new_boolean(bus_error->ProcessorContextCorrupt)); 319 json_object_object_add(bus_error_ir, "corrected", 320 json_object_new_boolean(bus_error->Corrected)); 321 json_object_object_add(bus_error_ir, "precisePC", 322 json_object_new_boolean(bus_error->PrecisePC)); 323 json_object_object_add( 324 bus_error_ir, "restartablePC", 325 json_object_new_boolean(bus_error->RestartablePC)); 326 json_object_object_add(bus_error_ir, "timedOut", 327 json_object_new_boolean(bus_error->TimeOut)); 328 329 //Participation type. 330 json_object *participation_type = integer_to_readable_pair( 331 bus_error->ParticipationType, 4, 332 ARM_BUS_PARTICIPATION_TYPES_KEYS, 333 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown"); 334 json_object_object_add(bus_error_ir, "participationType", 335 participation_type); 336 337 //Address space. 338 json_object *address_space = integer_to_readable_pair( 339 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS, 340 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown"); 341 json_object_object_add(bus_error_ir, "addressSpace", address_space); 342 343 //Memory access attributes. 344 //todo: find the specification of these in the ARM ARM 345 json_object_object_add( 346 bus_error_ir, "memoryAttributes", 347 json_object_new_int(bus_error->MemoryAddressAttributes)); 348 349 //Access Mode 350 json_object *access_mode = json_object_new_object(); 351 json_object_object_add(access_mode, "value", 352 json_object_new_int(bus_error->AccessMode)); 353 json_object_object_add( 354 access_mode, "name", 355 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" : 356 "Normal")); 357 json_object_object_add(bus_error_ir, "accessMode", access_mode); 358 359 return bus_error_ir; 360 } 361 362 //Converts a single ARM processor context block into JSON IR. 363 json_object * 364 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 365 void **cur_pos) 366 { 367 json_object *context_ir = json_object_new_object(); 368 369 //Version. 370 json_object_object_add(context_ir, "version", 371 json_object_new_int(header->Version)); 372 373 //Add the context type. 374 json_object *context_type = integer_to_readable_pair( 375 header->RegisterContextType, 9, 376 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS, 377 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES, 378 "Unknown (Reserved)"); 379 json_object_object_add(context_ir, "registerContextType", context_type); 380 381 //Register array size (bytes). 382 json_object_object_add( 383 context_ir, "registerArraySize", 384 json_object_new_uint64(header->RegisterArraySize)); 385 386 //The register array itself. 387 *cur_pos = (void *)(header + 1); 388 json_object *register_array = NULL; 389 switch (header->RegisterContextType) { 390 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 391 register_array = uniform_struct_to_ir( 392 (UINT32 *)cur_pos, 393 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 394 ARM_AARCH32_GPR_NAMES); 395 break; 396 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 397 register_array = uniform_struct_to_ir( 398 (UINT32 *)cur_pos, 399 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 400 sizeof(UINT32), 401 ARM_AARCH32_EL1_REGISTER_NAMES); 402 break; 403 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 404 register_array = uniform_struct_to_ir( 405 (UINT32 *)cur_pos, 406 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 407 sizeof(UINT32), 408 ARM_AARCH32_EL2_REGISTER_NAMES); 409 break; 410 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 411 register_array = uniform_struct_to_ir( 412 (UINT32 *)cur_pos, 413 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 414 sizeof(UINT32), 415 ARM_AARCH32_SECURE_REGISTER_NAMES); 416 break; 417 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 418 register_array = uniform_struct64_to_ir( 419 (UINT64 *)cur_pos, 420 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 421 ARM_AARCH64_GPR_NAMES); 422 break; 423 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 424 register_array = uniform_struct64_to_ir( 425 (UINT64 *)cur_pos, 426 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 427 sizeof(UINT64), 428 ARM_AARCH64_EL1_REGISTER_NAMES); 429 break; 430 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 431 register_array = uniform_struct64_to_ir( 432 (UINT64 *)cur_pos, 433 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 434 sizeof(UINT64), 435 ARM_AARCH64_EL2_REGISTER_NAMES); 436 break; 437 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 438 register_array = uniform_struct64_to_ir( 439 (UINT64 *)cur_pos, 440 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 441 sizeof(UINT64), 442 ARM_AARCH64_EL3_REGISTER_NAMES); 443 break; 444 case EFI_ARM_CONTEXT_TYPE_MISC: 445 register_array = cper_arm_misc_register_array_to_ir( 446 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos); 447 break; 448 default: 449 //Unknown register array type, add as base64 data instead. 450 register_array = json_object_new_object(); 451 int32_t encoded_len = 0; 452 char *encoded = base64_encode((UINT8 *)cur_pos, 453 header->RegisterArraySize, 454 &encoded_len); 455 if (encoded == NULL) { 456 printf("Failed to allocate encode output buffer. \n"); 457 return NULL; 458 } 459 json_object_object_add(register_array, "data", 460 json_object_new_string_len(encoded, 461 encoded_len)); 462 free(encoded); 463 464 break; 465 } 466 json_object_object_add(context_ir, "registerArray", register_array); 467 468 //Set the current position to after the processor context structure. 469 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize; 470 471 return context_ir; 472 } 473 474 //Converts a single CPER ARM miscellaneous register array to JSON IR format. 475 json_object * 476 cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register) 477 { 478 json_object *register_array = json_object_new_object(); 479 json_object *mrs_encoding = json_object_new_object(); 480 json_object_object_add(mrs_encoding, "op2", 481 json_object_new_uint64(misc_register->MrsOp2)); 482 json_object_object_add(mrs_encoding, "crm", 483 json_object_new_uint64(misc_register->MrsCrm)); 484 json_object_object_add(mrs_encoding, "crn", 485 json_object_new_uint64(misc_register->MrsCrn)); 486 json_object_object_add(mrs_encoding, "op1", 487 json_object_new_uint64(misc_register->MrsOp1)); 488 json_object_object_add(mrs_encoding, "o0", 489 json_object_new_uint64(misc_register->MrsO0)); 490 json_object_object_add(register_array, "mrsEncoding", mrs_encoding); 491 json_object_object_add(register_array, "value", 492 json_object_new_uint64(misc_register->Value)); 493 494 return register_array; 495 } 496 497 //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream. 498 void ir_section_arm_to_cper(json_object *section, FILE *out) 499 { 500 EFI_ARM_ERROR_RECORD *section_cper = 501 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD)); 502 503 //Validation bits. 504 section_cper->ValidFields = ir_to_bitfield( 505 json_object_object_get(section, "validationBits"), 4, 506 ARM_ERROR_VALID_BITFIELD_NAMES); 507 508 //Count of error/context info structures. 509 section_cper->ErrInfoNum = json_object_get_int( 510 json_object_object_get(section, "errorInfoNum")); 511 section_cper->ContextInfoNum = json_object_get_int( 512 json_object_object_get(section, "contextInfoNum")); 513 514 //Miscellaneous raw value fields. 515 section_cper->SectionLength = json_object_get_uint64( 516 json_object_object_get(section, "sectionLength")); 517 section_cper->ErrorAffinityLevel = readable_pair_to_integer( 518 json_object_object_get(section, "errorAffinity")); 519 section_cper->MPIDR_EL1 = json_object_get_uint64( 520 json_object_object_get(section, "mpidrEl1")); 521 section_cper->MIDR_EL1 = json_object_get_uint64( 522 json_object_object_get(section, "midrEl1")); 523 section_cper->RunningState = json_object_get_boolean( 524 json_object_object_get(section, "running")); 525 526 //Optional PSCI state. 527 json_object *psci_state = json_object_object_get(section, "psciState"); 528 if (psci_state != NULL) { 529 section_cper->PsciState = json_object_get_uint64(psci_state); 530 } 531 532 //Flush header to stream. 533 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out); 534 fflush(out); 535 536 //Error info structure array. 537 json_object *error_info = json_object_object_get(section, "errorInfo"); 538 for (int i = 0; i < section_cper->ErrInfoNum; i++) { 539 ir_arm_error_info_to_cper( 540 json_object_array_get_idx(error_info, i), out); 541 } 542 543 //Context info structure array. 544 json_object *context_info = 545 json_object_object_get(section, "contextInfo"); 546 for (int i = 0; i < section_cper->ContextInfoNum; i++) { 547 ir_arm_context_info_to_cper( 548 json_object_array_get_idx(context_info, i), out); 549 } 550 551 //Vendor specific error info. 552 json_object *vendor_specific_info = 553 json_object_object_get(section, "vendorSpecificInfo"); 554 if (vendor_specific_info != NULL) { 555 json_object *vendor_info_string = 556 json_object_object_get(vendor_specific_info, "data"); 557 int vendor_specific_len = 558 json_object_get_string_len(vendor_info_string); 559 560 int32_t decoded_len = 0; 561 562 UINT8 *decoded = base64_decode( 563 json_object_get_string(vendor_info_string), 564 vendor_specific_len, &decoded_len); 565 566 //Write out to file. 567 fwrite(decoded, decoded_len, 1, out); 568 fflush(out); 569 free(decoded); 570 } 571 572 //Free remaining resources. 573 free(section_cper); 574 } 575 576 //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 577 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out) 578 { 579 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 580 581 //Version, length. 582 error_info_cper.Version = json_object_get_int( 583 json_object_object_get(error_info, "version")); 584 error_info_cper.Length = json_object_get_int( 585 json_object_object_get(error_info, "length")); 586 587 //Validation bits. 588 error_info_cper.ValidationBits = ir_to_bitfield( 589 json_object_object_get(error_info, "validationBits"), 5, 590 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 591 592 //Type, multiple error. 593 error_info_cper.Type = (UINT8)readable_pair_to_integer( 594 json_object_object_get(error_info, "type")); 595 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer( 596 json_object_object_get(error_info, "multipleError")); 597 598 //Flags object. 599 error_info_cper.Flags = (UINT8)ir_to_bitfield( 600 json_object_object_get(error_info, "flags"), 4, 601 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 602 603 //Error information. 604 json_object *error_info_information = 605 json_object_object_get(error_info, "errorInformation"); 606 json_object *error_info_prop = NULL; 607 608 switch (error_info_cper.Type) { 609 case ARM_ERROR_INFORMATION_TYPE_CACHE: 610 error_info_prop = json_object_object_get(error_info_information, 611 "cacheError"); 612 ir_arm_error_cache_tlb_info_to_cper( 613 error_info_prop, 614 &error_info_cper.ErrorInformation.CacheError); 615 break; 616 case ARM_ERROR_INFORMATION_TYPE_TLB: 617 error_info_prop = json_object_object_get(error_info_information, 618 "tlbError"); 619 ir_arm_error_cache_tlb_info_to_cper( 620 error_info_prop, 621 &error_info_cper.ErrorInformation.CacheError); 622 break; 623 624 case ARM_ERROR_INFORMATION_TYPE_BUS: 625 ir_arm_error_bus_info_to_cper( 626 error_info_information, 627 &error_info_cper.ErrorInformation.BusError); 628 break; 629 630 default: 631 //Unknown error information type. 632 break; 633 } 634 635 //Virtual/physical fault address. 636 error_info_cper.VirtualFaultAddress = json_object_get_uint64( 637 json_object_object_get(error_info, "virtualFaultAddress")); 638 error_info_cper.PhysicalFaultAddress = json_object_get_uint64( 639 json_object_object_get(error_info, "physicalFaultAddress")); 640 641 //Write out to stream. 642 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, 643 out); 644 fflush(out); 645 } 646 647 //Converts a single ARM cache/TLB error information structure into a CPER structure. 648 void ir_arm_error_cache_tlb_info_to_cper( 649 json_object *error_information, 650 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper) 651 { 652 //Validation bits. 653 error_info_cper->ValidationBits = ir_to_bitfield( 654 json_object_object_get(error_information, "validationBits"), 7, 655 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 656 657 //Miscellaneous value fields. 658 error_info_cper->TransactionType = readable_pair_to_integer( 659 json_object_object_get(error_information, "transactionType")); 660 error_info_cper->Operation = readable_pair_to_integer( 661 json_object_object_get(error_information, "operation")); 662 error_info_cper->Level = json_object_get_uint64( 663 json_object_object_get(error_information, "level")); 664 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 665 json_object_object_get(error_information, 666 "processorContextCorrupt")); 667 error_info_cper->Corrected = json_object_get_boolean( 668 json_object_object_get(error_information, "corrected")); 669 error_info_cper->PrecisePC = json_object_get_boolean( 670 json_object_object_get(error_information, "precisePC")); 671 error_info_cper->RestartablePC = json_object_get_boolean( 672 json_object_object_get(error_information, "restartablePC")); 673 error_info_cper->Reserved = 0; 674 } 675 676 //Converts a single ARM bus error information structure into a CPER structure. 677 void ir_arm_error_bus_info_to_cper(json_object *error_information, 678 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper) 679 { 680 //Validation bits. 681 error_info_cper->ValidationBits = ir_to_bitfield( 682 json_object_object_get(error_information, "validationBits"), 7, 683 ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 684 685 //Miscellaneous value fields. 686 error_info_cper->TransactionType = readable_pair_to_integer( 687 json_object_object_get(error_information, "transactionType")); 688 error_info_cper->Operation = readable_pair_to_integer( 689 json_object_object_get(error_information, "operation")); 690 error_info_cper->Level = json_object_get_uint64( 691 json_object_object_get(error_information, "level")); 692 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 693 json_object_object_get(error_information, 694 "processorContextCorrupt")); 695 error_info_cper->Corrected = json_object_get_boolean( 696 json_object_object_get(error_information, "corrected")); 697 error_info_cper->PrecisePC = json_object_get_boolean( 698 json_object_object_get(error_information, "precisePC")); 699 error_info_cper->RestartablePC = json_object_get_boolean( 700 json_object_object_get(error_information, "restartablePC")); 701 error_info_cper->ParticipationType = readable_pair_to_integer( 702 json_object_object_get(error_information, "participationType")); 703 error_info_cper->AddressSpace = readable_pair_to_integer( 704 json_object_object_get(error_information, "addressSpace")); 705 error_info_cper->AccessMode = readable_pair_to_integer( 706 json_object_object_get(error_information, "accessMode")); 707 error_info_cper->MemoryAddressAttributes = json_object_get_uint64( 708 json_object_object_get(error_information, "memoryAttributes")); 709 error_info_cper->Reserved = 0; 710 } 711 712 //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 713 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out) 714 { 715 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 716 717 //Version, array size, context type. 718 info_header.Version = json_object_get_int( 719 json_object_object_get(context_info, "version")); 720 info_header.RegisterArraySize = json_object_get_int( 721 json_object_object_get(context_info, "registerArraySize")); 722 info_header.RegisterContextType = readable_pair_to_integer( 723 json_object_object_get(context_info, "registerContextType")); 724 725 //Flush to stream, write the register array itself. 726 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, 727 out); 728 fflush(out); 729 730 json_object *register_array = 731 json_object_object_get(context_info, "registerArray"); 732 switch (info_header.RegisterContextType) { 733 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 734 ir_arm_aarch32_gpr_to_cper(register_array, out); 735 break; 736 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 737 ir_arm_aarch32_el1_to_cper(register_array, out); 738 break; 739 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 740 ir_arm_aarch32_el2_to_cper(register_array, out); 741 break; 742 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 743 ir_arm_aarch32_secure_to_cper(register_array, out); 744 break; 745 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 746 ir_arm_aarch64_gpr_to_cper(register_array, out); 747 break; 748 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 749 ir_arm_aarch64_el1_to_cper(register_array, out); 750 break; 751 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 752 ir_arm_aarch64_el2_to_cper(register_array, out); 753 break; 754 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 755 ir_arm_aarch64_el3_to_cper(register_array, out); 756 break; 757 case EFI_ARM_CONTEXT_TYPE_MISC: 758 ir_arm_misc_registers_to_cper(register_array, out); 759 break; 760 default: 761 //Unknown register structure. 762 ir_arm_unknown_register_to_cper(register_array, out); 763 break; 764 } 765 } 766 767 //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 768 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out) 769 { 770 //Get uniform register array. 771 EFI_ARM_V8_AARCH32_GPR reg_array; 772 ir_to_uniform_struct(registers, (UINT32 *)®_array, 773 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 774 ARM_AARCH32_GPR_NAMES); 775 776 //Flush to stream. 777 fwrite(®_array, sizeof(reg_array), 1, out); 778 fflush(out); 779 } 780 781 //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 782 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out) 783 { 784 //Get uniform register array. 785 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 786 ir_to_uniform_struct(registers, (UINT32 *)®_array, 787 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 788 sizeof(UINT32), 789 ARM_AARCH32_EL1_REGISTER_NAMES); 790 791 //Flush to stream. 792 fwrite(®_array, sizeof(reg_array), 1, out); 793 fflush(out); 794 } 795 796 //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 797 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out) 798 { 799 //Get uniform register array. 800 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 801 ir_to_uniform_struct(registers, (UINT32 *)®_array, 802 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 803 sizeof(UINT32), 804 ARM_AARCH32_EL2_REGISTER_NAMES); 805 806 //Flush to stream. 807 fwrite(®_array, sizeof(reg_array), 1, out); 808 fflush(out); 809 } 810 811 //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 812 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out) 813 { 814 //Get uniform register array. 815 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 816 ir_to_uniform_struct(registers, (UINT32 *)®_array, 817 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 818 sizeof(UINT32), 819 ARM_AARCH32_SECURE_REGISTER_NAMES); 820 821 //Flush to stream. 822 fwrite(®_array, sizeof(reg_array), 1, out); 823 fflush(out); 824 } 825 826 //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 827 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out) 828 { 829 //Get uniform register array. 830 EFI_ARM_V8_AARCH64_GPR reg_array; 831 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 832 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 833 ARM_AARCH64_GPR_NAMES); 834 835 //Flush to stream. 836 fwrite(®_array, sizeof(reg_array), 1, out); 837 fflush(out); 838 } 839 840 //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 841 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out) 842 { 843 //Get uniform register array. 844 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 845 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 846 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 847 sizeof(UINT64), 848 ARM_AARCH64_EL1_REGISTER_NAMES); 849 850 //Flush to stream. 851 fwrite(®_array, sizeof(reg_array), 1, out); 852 fflush(out); 853 } 854 855 //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 856 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out) 857 { 858 //Get uniform register array. 859 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 860 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 861 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 862 sizeof(UINT64), 863 ARM_AARCH64_EL2_REGISTER_NAMES); 864 865 //Flush to stream. 866 fwrite(®_array, sizeof(reg_array), 1, out); 867 fflush(out); 868 } 869 870 //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 871 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out) 872 { 873 //Get uniform register array. 874 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 875 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 876 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 877 sizeof(UINT64), 878 ARM_AARCH64_EL3_REGISTER_NAMES); 879 880 //Flush to stream. 881 fwrite(®_array, sizeof(reg_array), 1, out); 882 fflush(out); 883 } 884 885 //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 886 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out) 887 { 888 EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 889 890 //MRS encoding information. 891 json_object *mrs_encoding = 892 json_object_object_get(registers, "mrsEncoding"); 893 reg_array.MrsOp2 = json_object_get_uint64( 894 json_object_object_get(mrs_encoding, "op2")); 895 reg_array.MrsCrm = json_object_get_uint64( 896 json_object_object_get(mrs_encoding, "crm")); 897 reg_array.MrsCrn = json_object_get_uint64( 898 json_object_object_get(mrs_encoding, "crn")); 899 reg_array.MrsOp1 = json_object_get_uint64( 900 json_object_object_get(mrs_encoding, "op1")); 901 reg_array.MrsO0 = json_object_get_uint64( 902 json_object_object_get(mrs_encoding, "o0")); 903 904 //Actual register value. 905 reg_array.Value = json_object_get_uint64( 906 json_object_object_get(registers, "value")); 907 908 //Flush to stream. 909 fwrite(®_array, sizeof(reg_array), 1, out); 910 fflush(out); 911 } 912 913 //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 914 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out) 915 { 916 //Get base64 represented data. 917 json_object *encoded = json_object_object_get(registers, "data"); 918 919 int32_t decoded_len = 0; 920 921 UINT8 *decoded = base64_decode(json_object_get_string(encoded), 922 json_object_get_string_len(encoded), 923 &decoded_len); 924 925 if (decoded == NULL) { 926 printf("Failed to allocate decode output buffer. \n"); 927 } else { 928 //Flush out to stream. 929 fwrite(&decoded, decoded_len, 1, out); 930 fflush(out); 931 free(decoded); 932 } 933 } 934