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