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