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 "../edk/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, so can't be made readable. Simply dump as a uint64 data object. 200 error_subinfo = json_object_new_object(); 201 json_object_object_add( 202 error_subinfo, "data", 203 json_object_new_uint64( 204 error_info->ErrorInformation.Value)); 205 break; 206 } 207 json_object_object_add(error_info_ir, "errorInformation", 208 error_subinfo); 209 210 //Virtual fault address, physical fault address. 211 json_object_object_add( 212 error_info_ir, "virtualFaultAddress", 213 json_object_new_uint64(error_info->VirtualFaultAddress)); 214 json_object_object_add( 215 error_info_ir, "physicalFaultAddress", 216 json_object_new_uint64(error_info->PhysicalFaultAddress)); 217 218 return error_info_ir; 219 } 220 221 //Converts a single ARM cache/TLB error information structure into JSON IR format. 222 json_object * 223 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 224 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 225 { 226 json_object *cache_tlb_error_ir = json_object_new_object(); 227 228 //Validation bitfield. 229 json_object *validation = 230 bitfield_to_ir(cache_tlb_error->ValidationBits, 7, 231 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 232 json_object_object_add(cache_tlb_error_ir, "validationBits", 233 validation); 234 235 //Transaction type. 236 json_object *transaction_type = integer_to_readable_pair( 237 cache_tlb_error->TransactionType, 3, 238 ARM_ERROR_TRANSACTION_TYPES_KEYS, 239 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 240 json_object_object_add(cache_tlb_error_ir, "transactionType", 241 transaction_type); 242 243 //Operation. 244 json_object *operation; 245 if (error_info->Type == 0) { 246 //Cache operation. 247 operation = integer_to_readable_pair( 248 cache_tlb_error->Operation, 11, 249 ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 250 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 251 "Unknown (Reserved)"); 252 } else { 253 //TLB operation. 254 operation = integer_to_readable_pair( 255 cache_tlb_error->Operation, 9, 256 ARM_TLB_OPERATION_TYPES_KEYS, 257 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 258 } 259 json_object_object_add(cache_tlb_error_ir, "operation", operation); 260 261 //Miscellaneous remaining fields. 262 json_object_object_add(cache_tlb_error_ir, "level", 263 json_object_new_int(cache_tlb_error->Level)); 264 json_object_object_add( 265 cache_tlb_error_ir, "processorContextCorrupt", 266 json_object_new_boolean( 267 cache_tlb_error->ProcessorContextCorrupt)); 268 json_object_object_add( 269 cache_tlb_error_ir, "corrected", 270 json_object_new_boolean(cache_tlb_error->Corrected)); 271 json_object_object_add( 272 cache_tlb_error_ir, "precisePC", 273 json_object_new_boolean(cache_tlb_error->PrecisePC)); 274 json_object_object_add( 275 cache_tlb_error_ir, "restartablePC", 276 json_object_new_boolean(cache_tlb_error->RestartablePC)); 277 return cache_tlb_error_ir; 278 } 279 280 //Converts a single ARM bus error information structure into JSON IR format. 281 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error) 282 { 283 json_object *bus_error_ir = json_object_new_object(); 284 285 //Validation bits. 286 json_object *validation = 287 bitfield_to_ir(bus_error->ValidationBits, 12, 288 ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 289 json_object_object_add(bus_error_ir, "validationBits", validation); 290 291 //Transaction type. 292 json_object *transaction_type = integer_to_readable_pair( 293 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS, 294 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 295 json_object_object_add(bus_error_ir, "transactionType", 296 transaction_type); 297 298 //Operation. 299 json_object *operation = integer_to_readable_pair( 300 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 301 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 302 json_object_object_add(bus_error_ir, "operation", operation); 303 304 //Affinity level of bus error, + miscellaneous fields. 305 json_object_object_add(bus_error_ir, "level", 306 json_object_new_int(bus_error->Level)); 307 json_object_object_add( 308 bus_error_ir, "processorContextCorrupt", 309 json_object_new_boolean(bus_error->ProcessorContextCorrupt)); 310 json_object_object_add(bus_error_ir, "corrected", 311 json_object_new_boolean(bus_error->Corrected)); 312 json_object_object_add(bus_error_ir, "precisePC", 313 json_object_new_boolean(bus_error->PrecisePC)); 314 json_object_object_add( 315 bus_error_ir, "restartablePC", 316 json_object_new_boolean(bus_error->RestartablePC)); 317 json_object_object_add(bus_error_ir, "timedOut", 318 json_object_new_boolean(bus_error->TimeOut)); 319 320 //Participation type. 321 json_object *participation_type = integer_to_readable_pair( 322 bus_error->ParticipationType, 4, 323 ARM_BUS_PARTICIPATION_TYPES_KEYS, 324 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown"); 325 json_object_object_add(bus_error_ir, "participationType", 326 participation_type); 327 328 //Address space. 329 json_object *address_space = integer_to_readable_pair( 330 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS, 331 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown"); 332 json_object_object_add(bus_error_ir, "addressSpace", address_space); 333 334 //Memory access attributes. 335 //todo: find the specification of these in the ARM ARM 336 json_object_object_add( 337 bus_error_ir, "memoryAttributes", 338 json_object_new_int(bus_error->MemoryAddressAttributes)); 339 340 //Access Mode 341 json_object *access_mode = json_object_new_object(); 342 json_object_object_add(access_mode, "value", 343 json_object_new_int(bus_error->AccessMode)); 344 json_object_object_add( 345 access_mode, "name", 346 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" : 347 "Normal")); 348 json_object_object_add(bus_error_ir, "accessMode", access_mode); 349 350 return bus_error_ir; 351 } 352 353 //Converts a single ARM processor context block into JSON IR. 354 json_object * 355 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 356 void **cur_pos) 357 { 358 json_object *context_ir = json_object_new_object(); 359 360 //Version. 361 json_object_object_add(context_ir, "version", 362 json_object_new_int(header->Version)); 363 364 //Add the context type. 365 json_object *context_type = integer_to_readable_pair( 366 header->RegisterContextType, 9, 367 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS, 368 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES, 369 "Unknown (Reserved)"); 370 json_object_object_add(context_ir, "registerContextType", context_type); 371 372 //Register array size (bytes). 373 json_object_object_add( 374 context_ir, "registerArraySize", 375 json_object_new_uint64(header->RegisterArraySize)); 376 377 //The register array itself. 378 *cur_pos = (void *)(header + 1); 379 json_object *register_array = NULL; 380 switch (header->RegisterContextType) { 381 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 382 register_array = uniform_struct_to_ir( 383 (UINT32 *)cur_pos, 384 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 385 ARM_AARCH32_GPR_NAMES); 386 break; 387 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 388 register_array = uniform_struct_to_ir( 389 (UINT32 *)cur_pos, 390 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 391 sizeof(UINT32), 392 ARM_AARCH32_EL1_REGISTER_NAMES); 393 break; 394 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 395 register_array = uniform_struct_to_ir( 396 (UINT32 *)cur_pos, 397 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 398 sizeof(UINT32), 399 ARM_AARCH32_EL2_REGISTER_NAMES); 400 break; 401 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 402 register_array = uniform_struct_to_ir( 403 (UINT32 *)cur_pos, 404 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 405 sizeof(UINT32), 406 ARM_AARCH32_SECURE_REGISTER_NAMES); 407 break; 408 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 409 register_array = uniform_struct64_to_ir( 410 (UINT64 *)cur_pos, 411 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 412 ARM_AARCH64_GPR_NAMES); 413 break; 414 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 415 register_array = uniform_struct64_to_ir( 416 (UINT64 *)cur_pos, 417 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 418 sizeof(UINT64), 419 ARM_AARCH64_EL1_REGISTER_NAMES); 420 break; 421 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 422 register_array = uniform_struct64_to_ir( 423 (UINT64 *)cur_pos, 424 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 425 sizeof(UINT64), 426 ARM_AARCH64_EL2_REGISTER_NAMES); 427 break; 428 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 429 register_array = uniform_struct64_to_ir( 430 (UINT64 *)cur_pos, 431 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 432 sizeof(UINT64), 433 ARM_AARCH64_EL3_REGISTER_NAMES); 434 break; 435 case EFI_ARM_CONTEXT_TYPE_MISC: 436 register_array = cper_arm_misc_register_array_to_ir( 437 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos); 438 break; 439 default: 440 //Unknown register array type, add as base64 data instead. 441 register_array = json_object_new_object(); 442 int32_t encoded_len = 0; 443 char *encoded = base64_encode((UINT8 *)cur_pos, 444 header->RegisterArraySize, 445 &encoded_len); 446 if (encoded == NULL) { 447 printf("Failed to allocate encode output buffer. \n"); 448 return NULL; 449 } 450 json_object_object_add(register_array, "data", 451 json_object_new_string_len(encoded, 452 encoded_len)); 453 free(encoded); 454 455 break; 456 } 457 json_object_object_add(context_ir, "registerArray", register_array); 458 459 //Set the current position to after the processor context structure. 460 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize; 461 462 return context_ir; 463 } 464 465 //Converts a single CPER ARM miscellaneous register array to JSON IR format. 466 json_object * 467 cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register) 468 { 469 json_object *register_array = json_object_new_object(); 470 json_object *mrs_encoding = json_object_new_object(); 471 json_object_object_add(mrs_encoding, "op2", 472 json_object_new_uint64(misc_register->MrsOp2)); 473 json_object_object_add(mrs_encoding, "crm", 474 json_object_new_uint64(misc_register->MrsCrm)); 475 json_object_object_add(mrs_encoding, "crn", 476 json_object_new_uint64(misc_register->MrsCrn)); 477 json_object_object_add(mrs_encoding, "op1", 478 json_object_new_uint64(misc_register->MrsOp1)); 479 json_object_object_add(mrs_encoding, "o0", 480 json_object_new_uint64(misc_register->MrsO0)); 481 json_object_object_add(register_array, "mrsEncoding", mrs_encoding); 482 json_object_object_add(register_array, "value", 483 json_object_new_uint64(misc_register->Value)); 484 485 return register_array; 486 } 487 488 //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream. 489 void ir_section_arm_to_cper(json_object *section, FILE *out) 490 { 491 EFI_ARM_ERROR_RECORD *section_cper = 492 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD)); 493 494 //Validation bits. 495 section_cper->ValidFields = ir_to_bitfield( 496 json_object_object_get(section, "validationBits"), 4, 497 ARM_ERROR_VALID_BITFIELD_NAMES); 498 499 //Count of error/context info structures. 500 section_cper->ErrInfoNum = json_object_get_int( 501 json_object_object_get(section, "errorInfoNum")); 502 section_cper->ContextInfoNum = json_object_get_int( 503 json_object_object_get(section, "contextInfoNum")); 504 505 //Miscellaneous raw value fields. 506 section_cper->SectionLength = json_object_get_uint64( 507 json_object_object_get(section, "sectionLength")); 508 section_cper->ErrorAffinityLevel = readable_pair_to_integer( 509 json_object_object_get(section, "errorAffinity")); 510 section_cper->MPIDR_EL1 = json_object_get_uint64( 511 json_object_object_get(section, "mpidrEl1")); 512 section_cper->MIDR_EL1 = json_object_get_uint64( 513 json_object_object_get(section, "midrEl1")); 514 section_cper->RunningState = json_object_get_boolean( 515 json_object_object_get(section, "running")); 516 517 //Optional PSCI state. 518 json_object *psci_state = json_object_object_get(section, "psciState"); 519 if (psci_state != NULL) { 520 section_cper->PsciState = json_object_get_uint64(psci_state); 521 } 522 523 //Flush header to stream. 524 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out); 525 fflush(out); 526 527 //Error info structure array. 528 json_object *error_info = json_object_object_get(section, "errorInfo"); 529 for (int i = 0; i < section_cper->ErrInfoNum; i++) { 530 ir_arm_error_info_to_cper( 531 json_object_array_get_idx(error_info, i), out); 532 } 533 534 //Context info structure array. 535 json_object *context_info = 536 json_object_object_get(section, "contextInfo"); 537 for (int i = 0; i < section_cper->ContextInfoNum; i++) { 538 ir_arm_context_info_to_cper( 539 json_object_array_get_idx(context_info, i), out); 540 } 541 542 //Vendor specific error info. 543 json_object *vendor_specific_info = 544 json_object_object_get(section, "vendorSpecificInfo"); 545 if (vendor_specific_info != NULL) { 546 json_object *vendor_info_string = 547 json_object_object_get(vendor_specific_info, "data"); 548 int vendor_specific_len = 549 json_object_get_string_len(vendor_info_string); 550 551 int32_t decoded_len = 0; 552 553 UINT8 *decoded = base64_decode( 554 json_object_get_string(vendor_info_string), 555 vendor_specific_len, &decoded_len); 556 557 //Write out to file. 558 fwrite(decoded, decoded_len, 1, out); 559 fflush(out); 560 free(decoded); 561 } 562 563 //Free remaining resources. 564 free(section_cper); 565 } 566 567 //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 568 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out) 569 { 570 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 571 572 //Version, length. 573 error_info_cper.Version = json_object_get_int( 574 json_object_object_get(error_info, "version")); 575 error_info_cper.Length = json_object_get_int( 576 json_object_object_get(error_info, "length")); 577 578 //Validation bits. 579 error_info_cper.ValidationBits = ir_to_bitfield( 580 json_object_object_get(error_info, "validationBits"), 5, 581 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 582 583 //Type, multiple error. 584 error_info_cper.Type = (UINT8)readable_pair_to_integer( 585 json_object_object_get(error_info, "type")); 586 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer( 587 json_object_object_get(error_info, "multipleError")); 588 589 //Flags object. 590 error_info_cper.Flags = (UINT8)ir_to_bitfield( 591 json_object_object_get(error_info, "flags"), 4, 592 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 593 594 //Error information. 595 json_object *error_info_information = 596 json_object_object_get(error_info, "errorInformation"); 597 switch (error_info_cper.Type) { 598 case ARM_ERROR_INFORMATION_TYPE_CACHE: 599 case ARM_ERROR_INFORMATION_TYPE_TLB: 600 ir_arm_error_cache_tlb_info_to_cper( 601 error_info_information, 602 &error_info_cper.ErrorInformation.CacheError); 603 break; 604 605 case ARM_ERROR_INFORMATION_TYPE_BUS: 606 ir_arm_error_bus_info_to_cper( 607 error_info_information, 608 &error_info_cper.ErrorInformation.BusError); 609 break; 610 611 default: 612 //Unknown error information type. 613 error_info_cper.ErrorInformation.Value = json_object_get_uint64( 614 json_object_object_get(error_info_information, "data")); 615 break; 616 } 617 618 //Virtual/physical fault address. 619 error_info_cper.VirtualFaultAddress = json_object_get_uint64( 620 json_object_object_get(error_info, "virtualFaultAddress")); 621 error_info_cper.PhysicalFaultAddress = json_object_get_uint64( 622 json_object_object_get(error_info, "physicalFaultAddress")); 623 624 //Write out to stream. 625 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, 626 out); 627 fflush(out); 628 } 629 630 //Converts a single ARM cache/TLB error information structure into a CPER structure. 631 void ir_arm_error_cache_tlb_info_to_cper( 632 json_object *error_information, 633 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper) 634 { 635 //Validation bits. 636 error_info_cper->ValidationBits = ir_to_bitfield( 637 json_object_object_get(error_information, "validationBits"), 7, 638 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 639 640 //Miscellaneous value fields. 641 error_info_cper->TransactionType = readable_pair_to_integer( 642 json_object_object_get(error_information, "transactionType")); 643 error_info_cper->Operation = readable_pair_to_integer( 644 json_object_object_get(error_information, "operation")); 645 error_info_cper->Level = json_object_get_uint64( 646 json_object_object_get(error_information, "level")); 647 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 648 json_object_object_get(error_information, 649 "processorContextCorrupt")); 650 error_info_cper->Corrected = json_object_get_boolean( 651 json_object_object_get(error_information, "corrected")); 652 error_info_cper->PrecisePC = json_object_get_boolean( 653 json_object_object_get(error_information, "precisePC")); 654 error_info_cper->RestartablePC = json_object_get_boolean( 655 json_object_object_get(error_information, "restartablePC")); 656 error_info_cper->Reserved = 0; 657 } 658 659 //Converts a single ARM bus error information structure into a CPER structure. 660 void ir_arm_error_bus_info_to_cper(json_object *error_information, 661 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper) 662 { 663 //Validation bits. 664 error_info_cper->ValidationBits = ir_to_bitfield( 665 json_object_object_get(error_information, "validationBits"), 7, 666 ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 667 668 //Miscellaneous value fields. 669 error_info_cper->TransactionType = readable_pair_to_integer( 670 json_object_object_get(error_information, "transactionType")); 671 error_info_cper->Operation = readable_pair_to_integer( 672 json_object_object_get(error_information, "operation")); 673 error_info_cper->Level = json_object_get_uint64( 674 json_object_object_get(error_information, "level")); 675 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 676 json_object_object_get(error_information, 677 "processorContextCorrupt")); 678 error_info_cper->Corrected = json_object_get_boolean( 679 json_object_object_get(error_information, "corrected")); 680 error_info_cper->PrecisePC = json_object_get_boolean( 681 json_object_object_get(error_information, "precisePC")); 682 error_info_cper->RestartablePC = json_object_get_boolean( 683 json_object_object_get(error_information, "restartablePC")); 684 error_info_cper->ParticipationType = readable_pair_to_integer( 685 json_object_object_get(error_information, "participationType")); 686 error_info_cper->AddressSpace = readable_pair_to_integer( 687 json_object_object_get(error_information, "addressSpace")); 688 error_info_cper->AccessMode = readable_pair_to_integer( 689 json_object_object_get(error_information, "accessMode")); 690 error_info_cper->MemoryAddressAttributes = json_object_get_uint64( 691 json_object_object_get(error_information, "memoryAttributes")); 692 error_info_cper->Reserved = 0; 693 } 694 695 //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 696 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out) 697 { 698 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 699 700 //Version, array size, context type. 701 info_header.Version = json_object_get_int( 702 json_object_object_get(context_info, "version")); 703 info_header.RegisterArraySize = json_object_get_int( 704 json_object_object_get(context_info, "registerArraySize")); 705 info_header.RegisterContextType = readable_pair_to_integer( 706 json_object_object_get(context_info, "registerContextType")); 707 708 //Flush to stream, write the register array itself. 709 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, 710 out); 711 fflush(out); 712 713 json_object *register_array = 714 json_object_object_get(context_info, "registerArray"); 715 switch (info_header.RegisterContextType) { 716 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 717 ir_arm_aarch32_gpr_to_cper(register_array, out); 718 break; 719 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 720 ir_arm_aarch32_el1_to_cper(register_array, out); 721 break; 722 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 723 ir_arm_aarch32_el2_to_cper(register_array, out); 724 break; 725 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 726 ir_arm_aarch32_secure_to_cper(register_array, out); 727 break; 728 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 729 ir_arm_aarch64_gpr_to_cper(register_array, out); 730 break; 731 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 732 ir_arm_aarch64_el1_to_cper(register_array, out); 733 break; 734 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 735 ir_arm_aarch64_el2_to_cper(register_array, out); 736 break; 737 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 738 ir_arm_aarch64_el3_to_cper(register_array, out); 739 break; 740 case EFI_ARM_CONTEXT_TYPE_MISC: 741 ir_arm_misc_registers_to_cper(register_array, out); 742 break; 743 default: 744 //Unknown register structure. 745 ir_arm_unknown_register_to_cper(register_array, out); 746 break; 747 } 748 } 749 750 //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 751 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out) 752 { 753 //Get uniform register array. 754 EFI_ARM_V8_AARCH32_GPR reg_array; 755 ir_to_uniform_struct(registers, (UINT32 *)®_array, 756 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 757 ARM_AARCH32_GPR_NAMES); 758 759 //Flush to stream. 760 fwrite(®_array, sizeof(reg_array), 1, out); 761 fflush(out); 762 } 763 764 //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 765 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out) 766 { 767 //Get uniform register array. 768 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 769 ir_to_uniform_struct(registers, (UINT32 *)®_array, 770 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 771 sizeof(UINT32), 772 ARM_AARCH32_EL1_REGISTER_NAMES); 773 774 //Flush to stream. 775 fwrite(®_array, sizeof(reg_array), 1, out); 776 fflush(out); 777 } 778 779 //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 780 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out) 781 { 782 //Get uniform register array. 783 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 784 ir_to_uniform_struct(registers, (UINT32 *)®_array, 785 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 786 sizeof(UINT32), 787 ARM_AARCH32_EL2_REGISTER_NAMES); 788 789 //Flush to stream. 790 fwrite(®_array, sizeof(reg_array), 1, out); 791 fflush(out); 792 } 793 794 //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 795 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out) 796 { 797 //Get uniform register array. 798 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 799 ir_to_uniform_struct(registers, (UINT32 *)®_array, 800 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 801 sizeof(UINT32), 802 ARM_AARCH32_SECURE_REGISTER_NAMES); 803 804 //Flush to stream. 805 fwrite(®_array, sizeof(reg_array), 1, out); 806 fflush(out); 807 } 808 809 //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 810 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out) 811 { 812 //Get uniform register array. 813 EFI_ARM_V8_AARCH64_GPR reg_array; 814 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 815 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 816 ARM_AARCH64_GPR_NAMES); 817 818 //Flush to stream. 819 fwrite(®_array, sizeof(reg_array), 1, out); 820 fflush(out); 821 } 822 823 //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 824 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out) 825 { 826 //Get uniform register array. 827 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 828 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 829 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 830 sizeof(UINT64), 831 ARM_AARCH64_EL1_REGISTER_NAMES); 832 833 //Flush to stream. 834 fwrite(®_array, sizeof(reg_array), 1, out); 835 fflush(out); 836 } 837 838 //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 839 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out) 840 { 841 //Get uniform register array. 842 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 843 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 844 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 845 sizeof(UINT64), 846 ARM_AARCH64_EL2_REGISTER_NAMES); 847 848 //Flush to stream. 849 fwrite(®_array, sizeof(reg_array), 1, out); 850 fflush(out); 851 } 852 853 //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 854 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out) 855 { 856 //Get uniform register array. 857 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 858 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 859 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 860 sizeof(UINT64), 861 ARM_AARCH64_EL3_REGISTER_NAMES); 862 863 //Flush to stream. 864 fwrite(®_array, sizeof(reg_array), 1, out); 865 fflush(out); 866 } 867 868 //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 869 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out) 870 { 871 EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 872 873 //MRS encoding information. 874 json_object *mrs_encoding = 875 json_object_object_get(registers, "mrsEncoding"); 876 reg_array.MrsOp2 = json_object_get_uint64( 877 json_object_object_get(mrs_encoding, "op2")); 878 reg_array.MrsCrm = json_object_get_uint64( 879 json_object_object_get(mrs_encoding, "crm")); 880 reg_array.MrsCrn = json_object_get_uint64( 881 json_object_object_get(mrs_encoding, "crn")); 882 reg_array.MrsOp1 = json_object_get_uint64( 883 json_object_object_get(mrs_encoding, "op1")); 884 reg_array.MrsO0 = json_object_get_uint64( 885 json_object_object_get(mrs_encoding, "o0")); 886 887 //Actual register value. 888 reg_array.Value = json_object_get_uint64( 889 json_object_object_get(registers, "value")); 890 891 //Flush to stream. 892 fwrite(®_array, sizeof(reg_array), 1, out); 893 fflush(out); 894 } 895 896 //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 897 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out) 898 { 899 //Get base64 represented data. 900 json_object *encoded = json_object_object_get(registers, "data"); 901 902 int32_t decoded_len = 0; 903 904 UINT8 *decoded = base64_decode(json_object_get_string(encoded), 905 json_object_get_string_len(encoded), 906 &decoded_len); 907 908 if (decoded == NULL) { 909 printf("Failed to allocate decode output buffer. \n"); 910 } else { 911 //Flush out to stream. 912 fwrite(&decoded, decoded_len, 1, out); 913 fflush(out); 914 free(decoded); 915 } 916 } 917