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 <string.h> 10 #include <json.h> 11 #include <libcper/base64.h> 12 #include <libcper/Cper.h> 13 #include <libcper/cper-utils.h> 14 #include <libcper/sections/cper-section-arm.h> 15 #include <libcper/log.h> 16 17 //Private pre-definitions. 18 json_object * 19 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info); 20 json_object * 21 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 22 const UINT8 **cur_pos, UINT32 *remaining_size); 23 json_object * 24 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 25 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info); 26 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error); 27 json_object *cper_arm_misc_register_array_to_ir( 28 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register); 29 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out); 30 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out); 31 void ir_arm_error_cache_tlb_info_to_cper( 32 json_object *error_information, 33 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper); 34 void ir_arm_error_bus_info_to_cper(json_object *error_information, 35 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper); 36 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out); 37 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out); 38 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out); 39 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out); 40 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out); 41 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out); 42 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out); 43 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out); 44 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out); 45 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out); 46 47 //Converts the given processor-generic CPER section into JSON IR. 48 json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size) 49 { 50 const UINT8 *cur_pos = section; 51 UINT32 remaining_size = size; 52 53 if (remaining_size < sizeof(EFI_ARM_ERROR_RECORD)) { 54 return NULL; 55 } 56 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)cur_pos; 57 cur_pos += sizeof(EFI_ARM_ERROR_RECORD); 58 remaining_size -= sizeof(EFI_ARM_ERROR_RECORD); 59 json_object *section_ir = json_object_new_object(); 60 61 //Length of ValidationBits from spec 62 ValidationTypes ui64Type = { UINT_64T, 63 .value.ui64 = record->ValidFields }; 64 65 //Number of error info and context info structures, and length. 66 json_object_object_add(section_ir, "errorInfoNum", 67 json_object_new_int(record->ErrInfoNum)); 68 json_object_object_add(section_ir, "contextInfoNum", 69 json_object_new_int(record->ContextInfoNum)); 70 json_object_object_add(section_ir, "sectionLength", 71 json_object_new_uint64(record->SectionLength)); 72 73 //Error affinity. 74 if (isvalid_prop_to_ir(&ui64Type, 1)) { 75 json_object *error_affinity = json_object_new_object(); 76 json_object_object_add( 77 error_affinity, "value", 78 json_object_new_int(record->ErrorAffinityLevel)); 79 json_object_object_add( 80 error_affinity, "type", 81 json_object_new_string(record->ErrorAffinityLevel < 4 ? 82 "Vendor Defined" : 83 "Reserved")); 84 json_object_object_add(section_ir, "errorAffinity", 85 error_affinity); 86 } 87 88 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1). 89 if (isvalid_prop_to_ir(&ui64Type, 0)) { 90 uint64_t mpidr_eli1 = record->MPIDR_EL1; 91 uint64_t sock; 92 json_object_object_add(section_ir, "mpidrEl1", 93 json_object_new_uint64(mpidr_eli1)); 94 95 //Arm Processor socket info dependes on mpidr_eli1 96 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32; 97 json_object_object_add(section_ir, "affinity3", 98 json_object_new_uint64(sock)); 99 } 100 101 json_object_object_add(section_ir, "midrEl1", 102 json_object_new_uint64(record->MIDR_EL1)); 103 104 if (isvalid_prop_to_ir(&ui64Type, 2)) { 105 //Whether the processor is running, and the state of it if so. 106 json_object_object_add( 107 section_ir, "running", 108 json_object_new_boolean(record->RunningState & 0x1)); 109 } 110 if (!(record->RunningState >> 31)) { 111 //Bit 32 of running state is on, so PSCI state information is included. 112 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format 113 //or the newer Extended StateID format. 114 json_object_object_add( 115 section_ir, "psciState", 116 json_object_new_uint64(record->PsciState)); 117 } 118 119 //Processor error structures. 120 json_object *error_info_array = json_object_new_array(); 121 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error = 122 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1); 123 if (remaining_size < 124 (record->ErrInfoNum * sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY))) { 125 json_object_put(error_info_array); 126 json_object_put(section_ir); 127 cper_print_log( 128 "Invalid CPER file: Invalid processor error info num.\n"); 129 return NULL; 130 } 131 for (int i = 0; i < record->ErrInfoNum; i++) { 132 json_object_array_add(error_info_array, 133 cper_arm_error_info_to_ir(cur_error)); 134 cur_error++; 135 } 136 137 cur_pos += (UINT32)(record->ErrInfoNum * 138 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY)); 139 remaining_size -= (UINT32)(record->ErrInfoNum * 140 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY)); 141 142 json_object_object_add(section_ir, "errorInfo", error_info_array); 143 144 //Processor context structures. 145 //The current position is moved within the processing, as it is a dynamic size structure. 146 json_object *context_info_array = json_object_new_array(); 147 for (int i = 0; i < record->ContextInfoNum; i++) { 148 if (remaining_size < 149 sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER)) { 150 json_object_put(context_info_array); 151 json_object_put(section_ir); 152 cper_print_log( 153 "Invalid CPER file: Invalid processor context info num.\n"); 154 return NULL; 155 } 156 EFI_ARM_CONTEXT_INFORMATION_HEADER *header = 157 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos; 158 159 cur_pos += sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER); 160 remaining_size -= sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER); 161 json_object *processor_context = 162 cper_arm_processor_context_to_ir(header, &cur_pos, 163 &remaining_size); 164 if (processor_context == NULL) { 165 json_object_put(context_info_array); 166 json_object_put(section_ir); 167 cper_print_log( 168 "Invalid CPER file: Invalid processor context info num.\n"); 169 return NULL; 170 } 171 json_object_array_add(context_info_array, processor_context); 172 } 173 json_object_object_add(section_ir, "contextInfo", context_info_array); 174 175 //Is there any vendor-specific information following? 176 if (isvalid_prop_to_ir(&ui64Type, 3)) { 177 if (cur_pos < (uint8_t *)section + record->SectionLength) { 178 json_object *vendor_specific = json_object_new_object(); 179 size_t input_size = (uint8_t *)section + 180 record->SectionLength - cur_pos; 181 if (remaining_size < input_size) { 182 json_object_put(vendor_specific); 183 json_object_put(section_ir); 184 cper_print_log( 185 "Invalid CPER file: Invalid vendor-specific info length.\n"); 186 return NULL; 187 } 188 int32_t encoded_len = 0; 189 char *encoded = base64_encode(cur_pos, input_size, 190 &encoded_len); 191 if (encoded == NULL) { 192 json_object_put(vendor_specific); 193 json_object_put(section_ir); 194 cper_print_log( 195 "base64 encode of vendorSpecificInfo failed\n"); 196 return NULL; 197 } 198 json_object_object_add(vendor_specific, "data", 199 json_object_new_string_len( 200 encoded, encoded_len)); 201 free(encoded); 202 203 json_object_object_add(section_ir, "vendorSpecificInfo", 204 vendor_specific); 205 } else { 206 cper_print_log( 207 "vendorSpecificInfo is marked valid but not present in binary\n"); 208 } 209 } 210 211 return section_ir; 212 } 213 214 //Converts a single ARM Process Error Information structure into JSON IR. 215 json_object * 216 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 217 { 218 json_object *error_info_ir = json_object_new_object(); 219 220 //Version, length. 221 json_object_object_add(error_info_ir, "version", 222 json_object_new_int(error_info->Version)); 223 json_object_object_add(error_info_ir, "length", 224 json_object_new_int(error_info->Length)); 225 226 //Validation bitfield. 227 ValidationTypes ui16Type = { UINT_16T, 228 .value.ui16 = error_info->ValidationBits }; 229 230 //The type of error information in this log. 231 json_object *error_type = integer_to_readable_pair( 232 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS, 233 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)"); 234 json_object_object_add(error_info_ir, "errorType", error_type); 235 236 //Multiple error count. 237 if (isvalid_prop_to_ir(&ui16Type, 0)) { 238 json_object *multiple_error = json_object_new_object(); 239 json_object_object_add( 240 multiple_error, "value", 241 json_object_new_int(error_info->MultipleError)); 242 json_object_object_add( 243 multiple_error, "type", 244 json_object_new_string(error_info->MultipleError < 1 ? 245 "Single Error" : 246 "Multiple Errors")); 247 json_object_object_add(error_info_ir, "multipleError", 248 multiple_error); 249 } 250 251 //Flags. 252 if (isvalid_prop_to_ir(&ui16Type, 1)) { 253 json_object *flags = bitfield_to_ir( 254 error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 255 json_object_object_add(error_info_ir, "flags", flags); 256 } 257 258 //Error information, split by type. 259 if (isvalid_prop_to_ir(&ui16Type, 2)) { 260 json_object *error_subinfo = NULL; 261 switch (error_info->Type) { 262 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache 263 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB 264 error_subinfo = cper_arm_cache_tlb_error_to_ir( 265 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info 266 ->ErrorInformation, 267 error_info); 268 break; 269 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus 270 error_subinfo = cper_arm_bus_error_to_ir( 271 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info 272 ->ErrorInformation); 273 break; 274 275 default: 276 //Unknown/microarch, will not support. 277 break; 278 } 279 if (error_subinfo != NULL) { 280 json_object_object_add(error_info_ir, 281 "errorInformation", 282 error_subinfo); 283 } 284 } 285 286 //Virtual fault address, physical fault address. 287 if (isvalid_prop_to_ir(&ui16Type, 3)) { 288 json_object_object_add( 289 error_info_ir, "virtualFaultAddress", 290 json_object_new_uint64( 291 error_info->VirtualFaultAddress)); 292 } 293 if (isvalid_prop_to_ir(&ui16Type, 4)) { 294 json_object_object_add( 295 error_info_ir, "physicalFaultAddress", 296 json_object_new_uint64( 297 error_info->PhysicalFaultAddress)); 298 } 299 300 return error_info_ir; 301 } 302 303 //Converts a single ARM cache/TLB error information structure into JSON IR format. 304 json_object * 305 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 306 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 307 { 308 json_object *cache_tlb_error_ir = json_object_new_object(); 309 json_object *cache_tlb_prop = json_object_new_object(); 310 char *cache_tlb_propname; 311 312 //Validation bitfield. 313 ValidationTypes ui64Type = { 314 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits 315 }; 316 317 //Transaction type. 318 if (isvalid_prop_to_ir(&ui64Type, 0)) { 319 json_object *transaction_type = integer_to_readable_pair( 320 cache_tlb_error->TransactionType, 3, 321 ARM_ERROR_TRANSACTION_TYPES_KEYS, 322 ARM_ERROR_TRANSACTION_TYPES_VALUES, 323 "Unknown (Reserved)"); 324 json_object_object_add(cache_tlb_error_ir, "transactionType", 325 transaction_type); 326 } 327 328 //Operation. 329 bool cacheErrorFlag = 1; 330 if (error_info->Type == 0) { 331 cache_tlb_propname = "cacheError"; 332 } else { 333 //TLB operation. 334 cache_tlb_propname = "tlbError"; 335 cacheErrorFlag = 0; 336 } 337 338 if (isvalid_prop_to_ir(&ui64Type, 1)) { 339 json_object *operation; 340 341 if (cacheErrorFlag) { 342 //Cache operation. 343 operation = integer_to_readable_pair( 344 cache_tlb_error->Operation, 11, 345 ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 346 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 347 "Unknown (Reserved)"); 348 } else { 349 operation = integer_to_readable_pair( 350 cache_tlb_error->Operation, 9, 351 ARM_TLB_OPERATION_TYPES_KEYS, 352 ARM_TLB_OPERATION_TYPES_VALUES, 353 "Unknown (Reserved)"); 354 } 355 json_object_object_add(cache_tlb_error_ir, "operation", 356 operation); 357 } 358 359 //Miscellaneous remaining fields. 360 if (isvalid_prop_to_ir(&ui64Type, 2)) { 361 json_object_object_add( 362 cache_tlb_error_ir, "level", 363 json_object_new_int(cache_tlb_error->Level)); 364 } 365 if (isvalid_prop_to_ir(&ui64Type, 3)) { 366 json_object_object_add( 367 cache_tlb_error_ir, "processorContextCorrupt", 368 json_object_new_boolean( 369 cache_tlb_error->ProcessorContextCorrupt)); 370 } 371 if (isvalid_prop_to_ir(&ui64Type, 4)) { 372 json_object_object_add( 373 cache_tlb_error_ir, "corrected", 374 json_object_new_boolean(cache_tlb_error->Corrected)); 375 } 376 if (isvalid_prop_to_ir(&ui64Type, 5)) { 377 json_object_object_add( 378 cache_tlb_error_ir, "precisePC", 379 json_object_new_boolean(cache_tlb_error->PrecisePC)); 380 } 381 if (isvalid_prop_to_ir(&ui64Type, 6)) { 382 json_object_object_add(cache_tlb_error_ir, "restartablePC", 383 json_object_new_boolean( 384 cache_tlb_error->RestartablePC)); 385 } 386 387 json_object_object_add(cache_tlb_prop, cache_tlb_propname, 388 cache_tlb_error_ir); 389 390 return cache_tlb_prop; 391 } 392 393 //Converts a single ARM bus error information structure into JSON IR format. 394 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error) 395 { 396 json_object *bus_error_ir = json_object_new_object(); 397 json_object *bus_prop = json_object_new_object(); 398 char *bus_propname = "busError"; 399 400 //Validation bits. 401 ValidationTypes ui64Type = { UINT_64T, 402 .value.ui64 = bus_error->ValidationBits }; 403 404 //Transaction type. 405 if (isvalid_prop_to_ir(&ui64Type, 0)) { 406 json_object *transaction_type = integer_to_readable_pair( 407 bus_error->TransactionType, 3, 408 ARM_ERROR_TRANSACTION_TYPES_KEYS, 409 ARM_ERROR_TRANSACTION_TYPES_VALUES, 410 "Unknown (Reserved)"); 411 json_object_object_add(bus_error_ir, "transactionType", 412 transaction_type); 413 } 414 415 //Operation. 416 if (isvalid_prop_to_ir(&ui64Type, 1)) { 417 json_object *operation = integer_to_readable_pair( 418 bus_error->Operation, 7, 419 ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 420 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 421 "Unknown (Reserved)"); 422 json_object_object_add(bus_error_ir, "operation", operation); 423 } 424 425 if (isvalid_prop_to_ir(&ui64Type, 2)) { 426 //Affinity level of bus error, + miscellaneous fields. 427 json_object_object_add(bus_error_ir, "level", 428 json_object_new_int(bus_error->Level)); 429 } 430 if (isvalid_prop_to_ir(&ui64Type, 3)) { 431 json_object_object_add( 432 bus_error_ir, "processorContextCorrupt", 433 json_object_new_boolean( 434 bus_error->ProcessorContextCorrupt)); 435 } 436 if (isvalid_prop_to_ir(&ui64Type, 4)) { 437 json_object_object_add( 438 bus_error_ir, "corrected", 439 json_object_new_boolean(bus_error->Corrected)); 440 } 441 if (isvalid_prop_to_ir(&ui64Type, 5)) { 442 json_object_object_add( 443 bus_error_ir, "precisePC", 444 json_object_new_boolean(bus_error->PrecisePC)); 445 } 446 if (isvalid_prop_to_ir(&ui64Type, 6)) { 447 json_object_object_add( 448 bus_error_ir, "restartablePC", 449 json_object_new_boolean(bus_error->RestartablePC)); 450 } 451 452 //Participation type. 453 if (isvalid_prop_to_ir(&ui64Type, 7)) { 454 json_object *participation_type = integer_to_readable_pair( 455 bus_error->ParticipationType, 4, 456 ARM_BUS_PARTICIPATION_TYPES_KEYS, 457 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown"); 458 json_object_object_add(bus_error_ir, "participationType", 459 participation_type); 460 } 461 if (isvalid_prop_to_ir(&ui64Type, 8)) { 462 json_object_object_add( 463 bus_error_ir, "timedOut", 464 json_object_new_boolean(bus_error->TimeOut)); 465 } 466 467 //Address space. 468 if (isvalid_prop_to_ir(&ui64Type, 9)) { 469 json_object *address_space = integer_to_readable_pair( 470 bus_error->AddressSpace, 3, 471 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS, 472 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown"); 473 json_object_object_add(bus_error_ir, "addressSpace", 474 address_space); 475 } 476 477 //Memory access attributes. 478 //todo: find the specification of these in the ARM ARM 479 if (isvalid_prop_to_ir(&ui64Type, 10)) { 480 json_object_object_add( 481 bus_error_ir, "memoryAttributes", 482 json_object_new_int( 483 bus_error->MemoryAddressAttributes)); 484 } 485 486 //Access Mode 487 if (isvalid_prop_to_ir(&ui64Type, 8)) { 488 json_object *access_mode = json_object_new_object(); 489 json_object_object_add( 490 access_mode, "value", 491 json_object_new_int(bus_error->AccessMode)); 492 json_object_object_add( 493 access_mode, "name", 494 json_object_new_string(bus_error->AccessMode == 0 ? 495 "Secure" : 496 "Normal")); 497 json_object_object_add(bus_error_ir, "accessMode", access_mode); 498 } 499 json_object_object_add(bus_prop, bus_propname, bus_error_ir); 500 501 return bus_prop; 502 } 503 504 //Converts a single ARM processor context block into JSON IR. 505 json_object * 506 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 507 const UINT8 **cur_pos, UINT32 *remaining_size) 508 { 509 if (header->RegisterArraySize > *remaining_size) { 510 cper_print_log( 511 "Invalid CPER file: Invalid processor context info num.\n"); 512 return NULL; 513 } 514 515 json_object *context_ir = json_object_new_object(); 516 517 //Version. 518 json_object_object_add(context_ir, "version", 519 json_object_new_int(header->Version)); 520 521 //Add the context type. 522 json_object *context_type = integer_to_readable_pair( 523 header->RegisterContextType, 524 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_COUNT, 525 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS, 526 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES, 527 "Unknown (Reserved)"); 528 json_object_object_add(context_ir, "registerContextType", context_type); 529 530 //Register array size (bytes). 531 json_object_object_add( 532 context_ir, "registerArraySize", 533 json_object_new_uint64(header->RegisterArraySize)); 534 535 //The register array itself. 536 json_object *register_array = NULL; 537 switch (header->RegisterContextType) { 538 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 539 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH32_GPR)) { 540 cper_print_log( 541 "Invalid CPER file: Invalid processor context info num.\n"); 542 goto fail; 543 } 544 if (header->RegisterArraySize < 545 sizeof(EFI_ARM_V8_AARCH32_GPR)) { 546 cper_print_log( 547 "Invalid CPER file: Not enough bytes for aarch32 gpr\n"); 548 goto fail; 549 } 550 register_array = uniform_struct_to_ir( 551 (UINT32 *)*cur_pos, 552 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 553 ARM_AARCH32_GPR_NAMES); 554 break; 555 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 556 if (*remaining_size < 557 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) { 558 cper_print_log( 559 "Invalid CPER file: Invalid processor context info num.\n"); 560 goto fail; 561 } 562 if (header->RegisterArraySize < 563 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) { 564 cper_print_log( 565 "Invalid CPER file: Not enough bytes for aarch32 el1\n"); 566 goto fail; 567 } 568 register_array = uniform_struct_to_ir( 569 (UINT32 *)*cur_pos, 570 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 571 sizeof(UINT32), 572 ARM_AARCH32_EL1_REGISTER_NAMES); 573 break; 574 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 575 if (*remaining_size < 576 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) { 577 cper_print_log( 578 "Invalid CPER file: Invalid processor context info num.\n"); 579 goto fail; 580 } 581 if (header->RegisterArraySize < 582 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) { 583 cper_print_log( 584 "Invalid CPER file: Not enough bytes for aarch32 el2\n"); 585 goto fail; 586 } 587 register_array = uniform_struct_to_ir( 588 (UINT32 *)*cur_pos, 589 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 590 sizeof(UINT32), 591 ARM_AARCH32_EL2_REGISTER_NAMES); 592 593 break; 594 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 595 if (*remaining_size < 596 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) { 597 json_object_put(context_ir); 598 cper_print_log( 599 "Invalid CPER file: Invalid processor context info num.\n"); 600 return NULL; 601 } 602 if (header->RegisterArraySize < 603 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) { 604 cper_print_log( 605 "Invalid CPER file: Not enough bytes for aarch32 secure\n"); 606 goto fail; 607 } 608 register_array = uniform_struct_to_ir( 609 (UINT32 *)*cur_pos, 610 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 611 sizeof(UINT32), 612 ARM_AARCH32_SECURE_REGISTER_NAMES); 613 break; 614 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 615 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH64_GPR)) { 616 cper_print_log( 617 "Invalid CPER file: Invalid processor context info num.\n"); 618 goto fail; 619 } 620 if (header->RegisterArraySize < 621 sizeof(EFI_ARM_V8_AARCH64_GPR)) { 622 cper_print_log( 623 "Invalid CPER file: Not enough bytes for aarch64 gpr\n"); 624 goto fail; 625 } 626 register_array = uniform_struct64_to_ir( 627 (UINT64 *)*cur_pos, 628 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 629 ARM_AARCH64_GPR_NAMES); 630 break; 631 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 632 if (*remaining_size < 633 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) { 634 cper_print_log( 635 "Invalid CPER file: Invalid processor context info num.\n"); 636 goto fail; 637 } 638 if (header->RegisterArraySize < 639 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) { 640 cper_print_log( 641 "Invalid CPER file: Not enough bytes for aarch64 el1\n"); 642 goto fail; 643 } 644 register_array = uniform_struct64_to_ir( 645 (UINT64 *)*cur_pos, 646 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 647 sizeof(UINT64), 648 ARM_AARCH64_EL1_REGISTER_NAMES); 649 break; 650 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 651 if (*remaining_size < 652 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) { 653 cper_print_log( 654 "Invalid CPER file: Invalid processor context info num.\n"); 655 goto fail; 656 } 657 if (header->RegisterArraySize < 658 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) { 659 cper_print_log( 660 "Invalid CPER file: Not enough bytes for aarch64 el2\n"); 661 goto fail; 662 } 663 register_array = uniform_struct64_to_ir( 664 (UINT64 *)*cur_pos, 665 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 666 sizeof(UINT64), 667 ARM_AARCH64_EL2_REGISTER_NAMES); 668 break; 669 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 670 if (*remaining_size < 671 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) { 672 cper_print_log( 673 "Invalid CPER file: Invalid processor context info num.\n"); 674 goto fail; 675 } 676 if (header->RegisterArraySize < 677 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) { 678 cper_print_log( 679 "Invalid CPER file: Not enough bytes for aarch64 el3\n"); 680 goto fail; 681 } 682 register_array = uniform_struct64_to_ir( 683 (UINT64 *)*cur_pos, 684 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 685 sizeof(UINT64), 686 ARM_AARCH64_EL3_REGISTER_NAMES); 687 break; 688 case EFI_ARM_CONTEXT_TYPE_MISC: 689 if (*remaining_size < sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) { 690 cper_print_log( 691 "Invalid CPER file: Invalid processor context info num.\n"); 692 goto fail; 693 } 694 if (header->RegisterArraySize < 695 sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) { 696 cper_print_log( 697 "Invalid CPER file: Not enough bytes for misc\n"); 698 goto fail; 699 } 700 register_array = cper_arm_misc_register_array_to_ir( 701 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos); 702 break; 703 default: 704 if (*remaining_size < header->RegisterArraySize) { 705 cper_print_log( 706 "Invalid CPER file: Invalid processor context info num.\n"); 707 goto fail; 708 } 709 //Unknown register array type, add as base64 data instead. 710 int32_t encoded_len = 0; 711 char *encoded = base64_encode((UINT8 *)*cur_pos, 712 header->RegisterArraySize, 713 &encoded_len); 714 if (encoded == NULL) { 715 goto fail; 716 } 717 register_array = json_object_new_object(); 718 json_object_object_add(register_array, "data", 719 json_object_new_string_len(encoded, 720 encoded_len)); 721 free(encoded); 722 723 break; 724 } 725 json_object_object_add(context_ir, "registerArray", register_array); 726 727 //Set the current position to after the processor context structure. 728 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize; 729 *remaining_size -= header->RegisterArraySize; 730 731 return context_ir; 732 733 fail: 734 json_object_put(context_ir); 735 return NULL; 736 } 737 738 //Converts a single CPER ARM miscellaneous register array to JSON IR format. 739 json_object * 740 cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register) 741 { 742 json_object *register_array = json_object_new_object(); 743 json_object *mrs_encoding = json_object_new_object(); 744 json_object_object_add(mrs_encoding, "op2", 745 json_object_new_uint64(misc_register->MrsOp2)); 746 json_object_object_add(mrs_encoding, "crm", 747 json_object_new_uint64(misc_register->MrsCrm)); 748 json_object_object_add(mrs_encoding, "crn", 749 json_object_new_uint64(misc_register->MrsCrn)); 750 json_object_object_add(mrs_encoding, "op1", 751 json_object_new_uint64(misc_register->MrsOp1)); 752 json_object_object_add(mrs_encoding, "o0", 753 json_object_new_uint64(misc_register->MrsO0)); 754 json_object_object_add(register_array, "mrsEncoding", mrs_encoding); 755 json_object_object_add(register_array, "value", 756 json_object_new_uint64(misc_register->Value)); 757 758 return register_array; 759 } 760 761 //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream. 762 void ir_section_arm_to_cper(json_object *section, FILE *out) 763 { 764 EFI_ARM_ERROR_RECORD section_cper; 765 memset(§ion_cper, 0, sizeof(section_cper)); 766 767 //Validation bits. 768 struct json_object *obj = NULL; 769 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 }; 770 771 //Count of error/context info structures. 772 section_cper.ErrInfoNum = json_object_get_int( 773 json_object_object_get(section, "errorInfoNum")); 774 section_cper.ContextInfoNum = json_object_get_int( 775 json_object_object_get(section, "contextInfoNum")); 776 777 //Miscellaneous raw value fields. 778 section_cper.SectionLength = json_object_get_uint64( 779 json_object_object_get(section, "sectionLength")); 780 if (json_object_object_get_ex(section, "mpidrEl1", &obj)) { 781 section_cper.MPIDR_EL1 = json_object_get_uint64(obj); 782 add_to_valid_bitfield(&u32Type, 0); 783 } 784 if (json_object_object_get_ex(section, "errorAffinity", &obj)) { 785 section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj); 786 add_to_valid_bitfield(&u32Type, 1); 787 } 788 section_cper.MIDR_EL1 = json_object_get_uint64( 789 json_object_object_get(section, "midrEl1")); 790 if (json_object_object_get_ex(section, "running", &obj)) { 791 section_cper.RunningState = json_object_get_boolean(obj); 792 add_to_valid_bitfield(&u32Type, 2); 793 } 794 795 //Optional PSCI state. 796 json_object *psci_state = json_object_object_get(section, "psciState"); 797 if (psci_state != NULL) { 798 section_cper.PsciState = json_object_get_uint64(psci_state); 799 } 800 801 //Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo 802 bool vendorSpecificPresent = 803 json_object_object_get_ex(section, "vendorSpecificInfo", &obj); 804 json_object *vendor_specific_info = obj; 805 if (vendorSpecificPresent) { 806 add_to_valid_bitfield(&u32Type, 3); 807 } 808 809 section_cper.ValidFields = u32Type.value.ui32; 810 811 //Flush header to stream. 812 fwrite(§ion_cper, sizeof(section_cper), 1, out); 813 814 //Error info structure array. 815 816 json_object *error_info = json_object_object_get(section, "errorInfo"); 817 for (int i = 0; i < section_cper.ErrInfoNum; i++) { 818 ir_arm_error_info_to_cper( 819 json_object_array_get_idx(error_info, i), out); 820 } 821 822 //Context info structure array. 823 json_object *context_info = 824 json_object_object_get(section, "contextInfo"); 825 for (int i = 0; i < section_cper.ContextInfoNum; i++) { 826 ir_arm_context_info_to_cper( 827 json_object_array_get_idx(context_info, i), out); 828 } 829 830 //Vendor specific error info. 831 if (vendorSpecificPresent) { 832 json_object *vendor_info_string = 833 json_object_object_get(vendor_specific_info, "data"); 834 int vendor_specific_len = 835 json_object_get_string_len(vendor_info_string); 836 837 int32_t decoded_len = 0; 838 839 UINT8 *decoded = base64_decode( 840 json_object_get_string(vendor_info_string), 841 vendor_specific_len, &decoded_len); 842 843 //Write out to file. 844 fwrite(decoded, decoded_len, 1, out); 845 free(decoded); 846 } 847 848 fflush(out); 849 } 850 851 //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 852 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out) 853 { 854 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 855 memset(&error_info_cper, 0, sizeof(error_info_cper)); 856 struct json_object *obj = NULL; 857 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 }; 858 859 //Version, length. 860 error_info_cper.Version = json_object_get_int( 861 json_object_object_get(error_info, "version")); 862 error_info_cper.Length = json_object_get_int( 863 json_object_object_get(error_info, "length")); 864 865 //Type, multiple error. 866 error_info_cper.Type = (UINT8)readable_pair_to_integer( 867 json_object_object_get(error_info, "errorType")); 868 869 if (json_object_object_get_ex(error_info, "multipleError", &obj)) { 870 error_info_cper.MultipleError = 871 (UINT16)readable_pair_to_integer(obj); 872 add_to_valid_bitfield(&ui16Type, 0); 873 } else { 874 error_info_cper.MultipleError = 0; 875 } 876 877 //Flags object. 878 if (json_object_object_get_ex(error_info, "flags", &obj)) { 879 error_info_cper.Flags = (UINT8)ir_to_bitfield( 880 obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 881 add_to_valid_bitfield(&ui16Type, 1); 882 } else { 883 error_info_cper.Flags = 0; 884 } 885 886 //Error information. 887 if (json_object_object_get_ex(error_info, "errorInformation", &obj)) { 888 json_object *error_info_information = obj; 889 json_object *error_info_prop = NULL; 890 switch (error_info_cper.Type) { 891 case ARM_ERROR_INFORMATION_TYPE_CACHE: 892 error_info_cper.ErrorInformation.Value = 0; 893 error_info_prop = json_object_object_get( 894 error_info_information, "cacheError"); 895 ir_arm_error_cache_tlb_info_to_cper( 896 error_info_prop, 897 &error_info_cper.ErrorInformation.CacheError); 898 break; 899 case ARM_ERROR_INFORMATION_TYPE_TLB: 900 error_info_cper.ErrorInformation.Value = 0; 901 error_info_prop = json_object_object_get( 902 error_info_information, "tlbError"); 903 ir_arm_error_cache_tlb_info_to_cper( 904 error_info_prop, 905 &error_info_cper.ErrorInformation.CacheError); 906 break; 907 908 case ARM_ERROR_INFORMATION_TYPE_BUS: 909 error_info_cper.ErrorInformation.Value = 0; 910 error_info_prop = json_object_object_get( 911 error_info_information, "busError"); 912 ir_arm_error_bus_info_to_cper( 913 error_info_prop, 914 &error_info_cper.ErrorInformation.BusError); 915 break; 916 917 default: 918 //Unknown error information type. 919 break; 920 } 921 add_to_valid_bitfield(&ui16Type, 2); 922 } 923 924 //Virtual/physical fault address. 925 if (json_object_object_get_ex(error_info, "virtualFaultAddress", 926 &obj)) { 927 error_info_cper.VirtualFaultAddress = 928 json_object_get_uint64(obj); 929 add_to_valid_bitfield(&ui16Type, 3); 930 } else { 931 error_info_cper.VirtualFaultAddress = 0; 932 } 933 934 if (json_object_object_get_ex(error_info, "physicalFaultAddress", 935 &obj)) { 936 error_info_cper.PhysicalFaultAddress = 937 json_object_get_uint64(obj); 938 add_to_valid_bitfield(&ui16Type, 4); 939 } else { 940 error_info_cper.PhysicalFaultAddress = 0; 941 } 942 error_info_cper.ValidationBits = ui16Type.value.ui16; 943 944 //Write out to stream. 945 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, 946 out); 947 } 948 949 //Converts a single ARM cache/TLB error information structure into a CPER structure. 950 void ir_arm_error_cache_tlb_info_to_cper( 951 json_object *error_information, 952 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper) 953 { 954 // //Validation bits. 955 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; 956 struct json_object *obj = NULL; 957 958 //Miscellaneous value fields. 959 if (json_object_object_get_ex(error_information, "transactionType", 960 &obj)) { 961 error_info_cper->TransactionType = 962 readable_pair_to_integer(obj); 963 add_to_valid_bitfield(&ui64Type, 0); 964 } 965 if (json_object_object_get_ex(error_information, "operation", &obj)) { 966 error_info_cper->Operation = readable_pair_to_integer(obj); 967 add_to_valid_bitfield(&ui64Type, 1); 968 } 969 if (json_object_object_get_ex(error_information, "level", &obj)) { 970 error_info_cper->Level = json_object_get_uint64(obj); 971 add_to_valid_bitfield(&ui64Type, 2); 972 } 973 if (json_object_object_get_ex(error_information, 974 "processorContextCorrupt", &obj)) { 975 error_info_cper->ProcessorContextCorrupt = 976 json_object_get_boolean(obj); 977 add_to_valid_bitfield(&ui64Type, 3); 978 } 979 if (json_object_object_get_ex(error_information, "corrected", &obj)) { 980 error_info_cper->Corrected = json_object_get_boolean(obj); 981 add_to_valid_bitfield(&ui64Type, 4); 982 } 983 if (json_object_object_get_ex(error_information, "precisePC", &obj)) { 984 error_info_cper->PrecisePC = json_object_get_boolean(obj); 985 add_to_valid_bitfield(&ui64Type, 5); 986 } 987 if (json_object_object_get_ex(error_information, "restartablePC", 988 &obj)) { 989 error_info_cper->RestartablePC = json_object_get_boolean(obj); 990 add_to_valid_bitfield(&ui64Type, 6); 991 } 992 error_info_cper->Reserved = 0; 993 error_info_cper->ValidationBits = ui64Type.value.ui64; 994 } 995 996 //Converts a single ARM bus error information structure into a CPER structure. 997 void ir_arm_error_bus_info_to_cper(json_object *error_information, 998 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper) 999 { 1000 //Validation bits. 1001 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; 1002 struct json_object *obj = NULL; 1003 1004 memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE)); 1005 1006 //Miscellaneous value fields. 1007 if (json_object_object_get_ex(error_information, "transactionType", 1008 &obj)) { 1009 error_info_cper->TransactionType = 1010 readable_pair_to_integer(obj); 1011 add_to_valid_bitfield(&ui64Type, 0); 1012 } else { 1013 error_info_cper->TransactionType = 0; 1014 } 1015 if (json_object_object_get_ex(error_information, "operation", &obj)) { 1016 error_info_cper->Operation = readable_pair_to_integer(obj); 1017 add_to_valid_bitfield(&ui64Type, 1); 1018 } else { 1019 error_info_cper->Operation = 0; 1020 } 1021 if (json_object_object_get_ex(error_information, "level", &obj)) { 1022 error_info_cper->Level = json_object_get_uint64(obj); 1023 add_to_valid_bitfield(&ui64Type, 2); 1024 } else { 1025 error_info_cper->Level = 0; 1026 } 1027 if (json_object_object_get_ex(error_information, 1028 "processorContextCorrupt", &obj)) { 1029 error_info_cper->ProcessorContextCorrupt = 1030 json_object_get_boolean(obj); 1031 add_to_valid_bitfield(&ui64Type, 3); 1032 } else { 1033 error_info_cper->ProcessorContextCorrupt = 0; 1034 } 1035 if (json_object_object_get_ex(error_information, "corrected", &obj)) { 1036 error_info_cper->Corrected = json_object_get_boolean(obj); 1037 add_to_valid_bitfield(&ui64Type, 4); 1038 } else { 1039 error_info_cper->Corrected = 0; 1040 } 1041 if (json_object_object_get_ex(error_information, "precisePC", &obj)) { 1042 error_info_cper->PrecisePC = json_object_get_boolean(obj); 1043 add_to_valid_bitfield(&ui64Type, 5); 1044 } else { 1045 error_info_cper->PrecisePC = 0; 1046 } 1047 if (json_object_object_get_ex(error_information, "restartablePC", 1048 &obj)) { 1049 error_info_cper->RestartablePC = json_object_get_boolean(obj); 1050 add_to_valid_bitfield(&ui64Type, 6); 1051 } else { 1052 error_info_cper->RestartablePC = 0; 1053 } 1054 if (json_object_object_get_ex(error_information, "participationType", 1055 &obj)) { 1056 error_info_cper->ParticipationType = 1057 readable_pair_to_integer(obj); 1058 add_to_valid_bitfield(&ui64Type, 7); 1059 } else { 1060 error_info_cper->ParticipationType = 0; 1061 } 1062 if (json_object_object_get_ex(error_information, "timedOut", &obj)) { 1063 error_info_cper->TimeOut = json_object_get_boolean(obj); 1064 add_to_valid_bitfield(&ui64Type, 8); 1065 } else { 1066 error_info_cper->TimeOut = 0; 1067 } 1068 if (json_object_object_get_ex(error_information, "addressSpace", 1069 &obj)) { 1070 error_info_cper->AddressSpace = readable_pair_to_integer(obj); 1071 add_to_valid_bitfield(&ui64Type, 9); 1072 } else { 1073 error_info_cper->AddressSpace = 0; 1074 } 1075 if (json_object_object_get_ex(error_information, "accessMode", &obj)) { 1076 error_info_cper->AccessMode = readable_pair_to_integer(obj); 1077 add_to_valid_bitfield(&ui64Type, 11); 1078 } else { 1079 error_info_cper->AccessMode = 0; 1080 } 1081 if (json_object_object_get_ex(error_information, "memoryAttributes", 1082 &obj)) { 1083 error_info_cper->MemoryAddressAttributes = 1084 json_object_get_uint64(obj); 1085 add_to_valid_bitfield(&ui64Type, 10); 1086 } else { 1087 error_info_cper->MemoryAddressAttributes = 0; 1088 } 1089 error_info_cper->Reserved = 0; 1090 error_info_cper->ValidationBits = ui64Type.value.ui64; 1091 } 1092 1093 //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 1094 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out) 1095 { 1096 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 1097 1098 //Version, array size, context type. 1099 info_header.Version = json_object_get_int( 1100 json_object_object_get(context_info, "version")); 1101 info_header.RegisterArraySize = json_object_get_int( 1102 json_object_object_get(context_info, "registerArraySize")); 1103 info_header.RegisterContextType = readable_pair_to_integer( 1104 json_object_object_get(context_info, "registerContextType")); 1105 1106 //Flush to stream, write the register array itself. 1107 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, 1108 out); 1109 fflush(out); 1110 1111 json_object *register_array = 1112 json_object_object_get(context_info, "registerArray"); 1113 switch (info_header.RegisterContextType) { 1114 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 1115 ir_arm_aarch32_gpr_to_cper(register_array, out); 1116 break; 1117 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 1118 ir_arm_aarch32_el1_to_cper(register_array, out); 1119 break; 1120 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 1121 ir_arm_aarch32_el2_to_cper(register_array, out); 1122 break; 1123 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 1124 ir_arm_aarch32_secure_to_cper(register_array, out); 1125 break; 1126 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 1127 ir_arm_aarch64_gpr_to_cper(register_array, out); 1128 break; 1129 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 1130 ir_arm_aarch64_el1_to_cper(register_array, out); 1131 break; 1132 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 1133 ir_arm_aarch64_el2_to_cper(register_array, out); 1134 break; 1135 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 1136 ir_arm_aarch64_el3_to_cper(register_array, out); 1137 break; 1138 case EFI_ARM_CONTEXT_TYPE_MISC: 1139 ir_arm_misc_registers_to_cper(register_array, out); 1140 break; 1141 default: 1142 //Unknown register structure. 1143 ir_arm_unknown_register_to_cper(register_array, out); 1144 break; 1145 } 1146 } 1147 1148 //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 1149 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out) 1150 { 1151 //Get uniform register array. 1152 EFI_ARM_V8_AARCH32_GPR reg_array; 1153 ir_to_uniform_struct(registers, (UINT32 *)®_array, 1154 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 1155 ARM_AARCH32_GPR_NAMES); 1156 1157 //Flush to stream. 1158 fwrite(®_array, sizeof(reg_array), 1, out); 1159 fflush(out); 1160 } 1161 1162 //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 1163 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out) 1164 { 1165 //Get uniform register array. 1166 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 1167 ir_to_uniform_struct(registers, (UINT32 *)®_array, 1168 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 1169 sizeof(UINT32), 1170 ARM_AARCH32_EL1_REGISTER_NAMES); 1171 1172 //Flush to stream. 1173 fwrite(®_array, sizeof(reg_array), 1, out); 1174 fflush(out); 1175 } 1176 1177 //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 1178 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out) 1179 { 1180 //Get uniform register array. 1181 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 1182 ir_to_uniform_struct(registers, (UINT32 *)®_array, 1183 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 1184 sizeof(UINT32), 1185 ARM_AARCH32_EL2_REGISTER_NAMES); 1186 1187 //Flush to stream. 1188 fwrite(®_array, sizeof(reg_array), 1, out); 1189 fflush(out); 1190 } 1191 1192 //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 1193 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out) 1194 { 1195 //Get uniform register array. 1196 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 1197 ir_to_uniform_struct(registers, (UINT32 *)®_array, 1198 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 1199 sizeof(UINT32), 1200 ARM_AARCH32_SECURE_REGISTER_NAMES); 1201 1202 //Flush to stream. 1203 fwrite(®_array, sizeof(reg_array), 1, out); 1204 fflush(out); 1205 } 1206 1207 //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 1208 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out) 1209 { 1210 //Get uniform register array. 1211 EFI_ARM_V8_AARCH64_GPR reg_array; 1212 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 1213 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 1214 ARM_AARCH64_GPR_NAMES); 1215 1216 //Flush to stream. 1217 fwrite(®_array, sizeof(reg_array), 1, out); 1218 fflush(out); 1219 } 1220 1221 //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 1222 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out) 1223 { 1224 //Get uniform register array. 1225 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 1226 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 1227 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 1228 sizeof(UINT64), 1229 ARM_AARCH64_EL1_REGISTER_NAMES); 1230 1231 //Flush to stream. 1232 fwrite(®_array, sizeof(reg_array), 1, out); 1233 fflush(out); 1234 } 1235 1236 //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 1237 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out) 1238 { 1239 //Get uniform register array. 1240 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 1241 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 1242 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 1243 sizeof(UINT64), 1244 ARM_AARCH64_EL2_REGISTER_NAMES); 1245 1246 //Flush to stream. 1247 fwrite(®_array, sizeof(reg_array), 1, out); 1248 fflush(out); 1249 } 1250 1251 //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 1252 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out) 1253 { 1254 //Get uniform register array. 1255 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 1256 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 1257 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 1258 sizeof(UINT64), 1259 ARM_AARCH64_EL3_REGISTER_NAMES); 1260 1261 //Flush to stream. 1262 fwrite(®_array, sizeof(reg_array), 1, out); 1263 fflush(out); 1264 } 1265 1266 //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 1267 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out) 1268 { 1269 EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 1270 1271 //MRS encoding information. 1272 json_object *mrs_encoding = 1273 json_object_object_get(registers, "mrsEncoding"); 1274 reg_array.MrsOp2 = json_object_get_uint64( 1275 json_object_object_get(mrs_encoding, "op2")); 1276 reg_array.MrsCrm = json_object_get_uint64( 1277 json_object_object_get(mrs_encoding, "crm")); 1278 reg_array.MrsCrn = json_object_get_uint64( 1279 json_object_object_get(mrs_encoding, "crn")); 1280 reg_array.MrsOp1 = json_object_get_uint64( 1281 json_object_object_get(mrs_encoding, "op1")); 1282 reg_array.MrsO0 = json_object_get_uint64( 1283 json_object_object_get(mrs_encoding, "o0")); 1284 1285 //Actual register value. 1286 reg_array.Value = json_object_get_uint64( 1287 json_object_object_get(registers, "value")); 1288 1289 //Flush to stream. 1290 fwrite(®_array, sizeof(reg_array), 1, out); 1291 fflush(out); 1292 } 1293 1294 //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 1295 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out) 1296 { 1297 //Get base64 represented data. 1298 json_object *encoded = json_object_object_get(registers, "data"); 1299 1300 int32_t decoded_len = 0; 1301 1302 UINT8 *decoded = base64_decode(json_object_get_string(encoded), 1303 json_object_get_string_len(encoded), 1304 &decoded_len); 1305 1306 if (decoded == NULL) { 1307 cper_print_log("Failed to allocate decode output buffer. \n"); 1308 } else { 1309 //Flush out to stream. 1310 fwrite(&decoded, decoded_len, 1, out); 1311 fflush(out); 1312 free(decoded); 1313 } 1314 } 1315