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