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 "libbase64.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 char *encoded = malloc(2 * input_size); 125 size_t encoded_len = 0; 126 if (!encoded) { 127 printf("Failed to allocate encode output buffer. \n"); 128 } else { 129 base64_encode((const char *)cur_pos, input_size, 130 encoded, &encoded_len, 0); 131 json_object_object_add(vendor_specific, "data", 132 json_object_new_string_len( 133 encoded, encoded_len)); 134 free(encoded); 135 136 json_object_object_add(section_ir, "vendorSpecificInfo", 137 vendor_specific); 138 } 139 } 140 141 return section_ir; 142 } 143 144 //Converts a single ARM Process Error Information structure into JSON IR. 145 json_object * 146 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 147 { 148 json_object *error_info_ir = json_object_new_object(); 149 150 //Version, length. 151 json_object_object_add(error_info_ir, "version", 152 json_object_new_int(error_info->Version)); 153 json_object_object_add(error_info_ir, "length", 154 json_object_new_int(error_info->Length)); 155 156 //Validation bitfield. 157 json_object *validation = 158 bitfield_to_ir(error_info->ValidationBits, 5, 159 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 160 json_object_object_add(error_info_ir, "validationBits", validation); 161 162 //The type of error information in this log. 163 json_object *error_type = integer_to_readable_pair( 164 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS, 165 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)"); 166 json_object_object_add(error_info_ir, "errorType", error_type); 167 168 //Multiple error count. 169 json_object *multiple_error = json_object_new_object(); 170 json_object_object_add(multiple_error, "value", 171 json_object_new_int(error_info->MultipleError)); 172 json_object_object_add( 173 multiple_error, "type", 174 json_object_new_string(error_info->MultipleError < 1 ? 175 "Single Error" : 176 "Multiple Errors")); 177 json_object_object_add(error_info_ir, "multipleError", multiple_error); 178 179 //Flags. 180 json_object *flags = bitfield_to_ir(error_info->Flags, 4, 181 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 182 json_object_object_add(error_info_ir, "flags", flags); 183 184 //Error information, split by type. 185 json_object *error_subinfo = NULL; 186 switch (error_info->Type) { 187 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache 188 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB 189 error_subinfo = cper_arm_cache_tlb_error_to_ir( 190 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info 191 ->ErrorInformation, 192 error_info); 193 break; 194 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus 195 error_subinfo = cper_arm_bus_error_to_ir( 196 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info 197 ->ErrorInformation); 198 break; 199 200 default: 201 //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object. 202 error_subinfo = json_object_new_object(); 203 json_object_object_add( 204 error_subinfo, "data", 205 json_object_new_uint64( 206 error_info->ErrorInformation.Value)); 207 break; 208 } 209 json_object_object_add(error_info_ir, "errorInformation", 210 error_subinfo); 211 212 //Virtual fault address, physical fault address. 213 json_object_object_add( 214 error_info_ir, "virtualFaultAddress", 215 json_object_new_uint64(error_info->VirtualFaultAddress)); 216 json_object_object_add( 217 error_info_ir, "physicalFaultAddress", 218 json_object_new_uint64(error_info->PhysicalFaultAddress)); 219 220 return error_info_ir; 221 } 222 223 //Converts a single ARM cache/TLB error information structure into JSON IR format. 224 json_object * 225 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 226 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 227 { 228 json_object *cache_tlb_error_ir = json_object_new_object(); 229 230 //Validation bitfield. 231 json_object *validation = 232 bitfield_to_ir(cache_tlb_error->ValidationBits, 7, 233 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 234 json_object_object_add(cache_tlb_error_ir, "validationBits", 235 validation); 236 237 //Transaction type. 238 json_object *transaction_type = integer_to_readable_pair( 239 cache_tlb_error->TransactionType, 3, 240 ARM_ERROR_TRANSACTION_TYPES_KEYS, 241 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 242 json_object_object_add(cache_tlb_error_ir, "transactionType", 243 transaction_type); 244 245 //Operation. 246 json_object *operation; 247 if (error_info->Type == 0) { 248 //Cache operation. 249 operation = integer_to_readable_pair( 250 cache_tlb_error->Operation, 11, 251 ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 252 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 253 "Unknown (Reserved)"); 254 } else { 255 //TLB operation. 256 operation = integer_to_readable_pair( 257 cache_tlb_error->Operation, 9, 258 ARM_TLB_OPERATION_TYPES_KEYS, 259 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 260 } 261 json_object_object_add(cache_tlb_error_ir, "operation", operation); 262 263 //Miscellaneous remaining fields. 264 json_object_object_add(cache_tlb_error_ir, "level", 265 json_object_new_int(cache_tlb_error->Level)); 266 json_object_object_add( 267 cache_tlb_error_ir, "processorContextCorrupt", 268 json_object_new_boolean( 269 cache_tlb_error->ProcessorContextCorrupt)); 270 json_object_object_add( 271 cache_tlb_error_ir, "corrected", 272 json_object_new_boolean(cache_tlb_error->Corrected)); 273 json_object_object_add( 274 cache_tlb_error_ir, "precisePC", 275 json_object_new_boolean(cache_tlb_error->PrecisePC)); 276 json_object_object_add( 277 cache_tlb_error_ir, "restartablePC", 278 json_object_new_boolean(cache_tlb_error->RestartablePC)); 279 return cache_tlb_error_ir; 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 char *encoded = malloc(2 * header->RegisterArraySize); 445 size_t encoded_len = 0; 446 if (!encoded) { 447 printf("Failed to allocate encode output buffer. \n"); 448 } else { 449 base64_encode((const char *)cur_pos, 450 header->RegisterArraySize, encoded, 451 &encoded_len, 0); 452 json_object_object_add(register_array, "data", 453 json_object_new_string_len( 454 encoded, 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 char *decoded = malloc(vendor_specific_len); 553 size_t decoded_len = 0; 554 if (!decoded) { 555 printf("Failed to allocate decode output buffer. \n"); 556 } else { 557 base64_decode( 558 json_object_get_string(vendor_info_string), 559 vendor_specific_len, decoded, &decoded_len, 0); 560 561 //Write out to file. 562 fwrite(decoded, decoded_len, 1, out); 563 fflush(out); 564 free(decoded); 565 } 566 } 567 568 //Free remaining resources. 569 free(section_cper); 570 } 571 572 //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 573 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out) 574 { 575 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 576 577 //Version, length. 578 error_info_cper.Version = json_object_get_int( 579 json_object_object_get(error_info, "version")); 580 error_info_cper.Length = json_object_get_int( 581 json_object_object_get(error_info, "length")); 582 583 //Validation bits. 584 error_info_cper.ValidationBits = ir_to_bitfield( 585 json_object_object_get(error_info, "validationBits"), 5, 586 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 587 588 //Type, multiple error. 589 error_info_cper.Type = (UINT8)readable_pair_to_integer( 590 json_object_object_get(error_info, "type")); 591 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer( 592 json_object_object_get(error_info, "multipleError")); 593 594 //Flags object. 595 error_info_cper.Flags = (UINT8)ir_to_bitfield( 596 json_object_object_get(error_info, "flags"), 4, 597 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 598 599 //Error information. 600 json_object *error_info_information = 601 json_object_object_get(error_info, "errorInformation"); 602 switch (error_info_cper.Type) { 603 case ARM_ERROR_INFORMATION_TYPE_CACHE: 604 case ARM_ERROR_INFORMATION_TYPE_TLB: 605 ir_arm_error_cache_tlb_info_to_cper( 606 error_info_information, 607 &error_info_cper.ErrorInformation.CacheError); 608 break; 609 610 case ARM_ERROR_INFORMATION_TYPE_BUS: 611 ir_arm_error_bus_info_to_cper( 612 error_info_information, 613 &error_info_cper.ErrorInformation.BusError); 614 break; 615 616 default: 617 //Unknown error information type. 618 error_info_cper.ErrorInformation.Value = json_object_get_uint64( 619 json_object_object_get(error_info_information, "data")); 620 break; 621 } 622 623 //Virtual/physical fault address. 624 error_info_cper.VirtualFaultAddress = json_object_get_uint64( 625 json_object_object_get(error_info, "virtualFaultAddress")); 626 error_info_cper.PhysicalFaultAddress = json_object_get_uint64( 627 json_object_object_get(error_info, "physicalFaultAddress")); 628 629 //Write out to stream. 630 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, 631 out); 632 fflush(out); 633 } 634 635 //Converts a single ARM cache/TLB error information structure into a CPER structure. 636 void ir_arm_error_cache_tlb_info_to_cper( 637 json_object *error_information, 638 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper) 639 { 640 //Validation bits. 641 error_info_cper->ValidationBits = ir_to_bitfield( 642 json_object_object_get(error_information, "validationBits"), 7, 643 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 644 645 //Miscellaneous value fields. 646 error_info_cper->TransactionType = readable_pair_to_integer( 647 json_object_object_get(error_information, "transactionType")); 648 error_info_cper->Operation = readable_pair_to_integer( 649 json_object_object_get(error_information, "operation")); 650 error_info_cper->Level = json_object_get_uint64( 651 json_object_object_get(error_information, "level")); 652 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 653 json_object_object_get(error_information, 654 "processorContextCorrupt")); 655 error_info_cper->Corrected = json_object_get_boolean( 656 json_object_object_get(error_information, "corrected")); 657 error_info_cper->PrecisePC = json_object_get_boolean( 658 json_object_object_get(error_information, "precisePC")); 659 error_info_cper->RestartablePC = json_object_get_boolean( 660 json_object_object_get(error_information, "restartablePC")); 661 error_info_cper->Reserved = 0; 662 } 663 664 //Converts a single ARM bus error information structure into a CPER structure. 665 void ir_arm_error_bus_info_to_cper(json_object *error_information, 666 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper) 667 { 668 //Validation bits. 669 error_info_cper->ValidationBits = ir_to_bitfield( 670 json_object_object_get(error_information, "validationBits"), 7, 671 ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 672 673 //Miscellaneous value fields. 674 error_info_cper->TransactionType = readable_pair_to_integer( 675 json_object_object_get(error_information, "transactionType")); 676 error_info_cper->Operation = readable_pair_to_integer( 677 json_object_object_get(error_information, "operation")); 678 error_info_cper->Level = json_object_get_uint64( 679 json_object_object_get(error_information, "level")); 680 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 681 json_object_object_get(error_information, 682 "processorContextCorrupt")); 683 error_info_cper->Corrected = json_object_get_boolean( 684 json_object_object_get(error_information, "corrected")); 685 error_info_cper->PrecisePC = json_object_get_boolean( 686 json_object_object_get(error_information, "precisePC")); 687 error_info_cper->RestartablePC = json_object_get_boolean( 688 json_object_object_get(error_information, "restartablePC")); 689 error_info_cper->ParticipationType = readable_pair_to_integer( 690 json_object_object_get(error_information, "participationType")); 691 error_info_cper->AddressSpace = readable_pair_to_integer( 692 json_object_object_get(error_information, "addressSpace")); 693 error_info_cper->AccessMode = readable_pair_to_integer( 694 json_object_object_get(error_information, "accessMode")); 695 error_info_cper->MemoryAddressAttributes = json_object_get_uint64( 696 json_object_object_get(error_information, "memoryAttributes")); 697 error_info_cper->Reserved = 0; 698 } 699 700 //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 701 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out) 702 { 703 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 704 705 //Version, array size, context type. 706 info_header.Version = json_object_get_int( 707 json_object_object_get(context_info, "version")); 708 info_header.RegisterArraySize = json_object_get_int( 709 json_object_object_get(context_info, "registerArraySize")); 710 info_header.RegisterContextType = readable_pair_to_integer( 711 json_object_object_get(context_info, "registerContextType")); 712 713 //Flush to stream, write the register array itself. 714 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, 715 out); 716 fflush(out); 717 718 json_object *register_array = 719 json_object_object_get(context_info, "registerArray"); 720 switch (info_header.RegisterContextType) { 721 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 722 ir_arm_aarch32_gpr_to_cper(register_array, out); 723 break; 724 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 725 ir_arm_aarch32_el1_to_cper(register_array, out); 726 break; 727 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 728 ir_arm_aarch32_el2_to_cper(register_array, out); 729 break; 730 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 731 ir_arm_aarch32_secure_to_cper(register_array, out); 732 break; 733 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 734 ir_arm_aarch64_gpr_to_cper(register_array, out); 735 break; 736 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 737 ir_arm_aarch64_el1_to_cper(register_array, out); 738 break; 739 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 740 ir_arm_aarch64_el2_to_cper(register_array, out); 741 break; 742 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 743 ir_arm_aarch64_el3_to_cper(register_array, out); 744 break; 745 case EFI_ARM_CONTEXT_TYPE_MISC: 746 ir_arm_misc_registers_to_cper(register_array, out); 747 break; 748 default: 749 //Unknown register structure. 750 ir_arm_unknown_register_to_cper(register_array, out); 751 break; 752 } 753 } 754 755 //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 756 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out) 757 { 758 //Get uniform register array. 759 EFI_ARM_V8_AARCH32_GPR reg_array; 760 ir_to_uniform_struct(registers, (UINT32 *)®_array, 761 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 762 ARM_AARCH32_GPR_NAMES); 763 764 //Flush to stream. 765 fwrite(®_array, sizeof(reg_array), 1, out); 766 fflush(out); 767 } 768 769 //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 770 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out) 771 { 772 //Get uniform register array. 773 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 774 ir_to_uniform_struct(registers, (UINT32 *)®_array, 775 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 776 sizeof(UINT32), 777 ARM_AARCH32_EL1_REGISTER_NAMES); 778 779 //Flush to stream. 780 fwrite(®_array, sizeof(reg_array), 1, out); 781 fflush(out); 782 } 783 784 //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 785 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out) 786 { 787 //Get uniform register array. 788 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 789 ir_to_uniform_struct(registers, (UINT32 *)®_array, 790 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 791 sizeof(UINT32), 792 ARM_AARCH32_EL2_REGISTER_NAMES); 793 794 //Flush to stream. 795 fwrite(®_array, sizeof(reg_array), 1, out); 796 fflush(out); 797 } 798 799 //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 800 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out) 801 { 802 //Get uniform register array. 803 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 804 ir_to_uniform_struct(registers, (UINT32 *)®_array, 805 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 806 sizeof(UINT32), 807 ARM_AARCH32_SECURE_REGISTER_NAMES); 808 809 //Flush to stream. 810 fwrite(®_array, sizeof(reg_array), 1, out); 811 fflush(out); 812 } 813 814 //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 815 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out) 816 { 817 //Get uniform register array. 818 EFI_ARM_V8_AARCH64_GPR reg_array; 819 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 820 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 821 ARM_AARCH64_GPR_NAMES); 822 823 //Flush to stream. 824 fwrite(®_array, sizeof(reg_array), 1, out); 825 fflush(out); 826 } 827 828 //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 829 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out) 830 { 831 //Get uniform register array. 832 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 833 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 834 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 835 sizeof(UINT64), 836 ARM_AARCH64_EL1_REGISTER_NAMES); 837 838 //Flush to stream. 839 fwrite(®_array, sizeof(reg_array), 1, out); 840 fflush(out); 841 } 842 843 //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 844 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out) 845 { 846 //Get uniform register array. 847 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 848 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 849 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 850 sizeof(UINT64), 851 ARM_AARCH64_EL2_REGISTER_NAMES); 852 853 //Flush to stream. 854 fwrite(®_array, sizeof(reg_array), 1, out); 855 fflush(out); 856 } 857 858 //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 859 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out) 860 { 861 //Get uniform register array. 862 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 863 ir_to_uniform_struct64(registers, (UINT64 *)®_array, 864 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 865 sizeof(UINT64), 866 ARM_AARCH64_EL3_REGISTER_NAMES); 867 868 //Flush to stream. 869 fwrite(®_array, sizeof(reg_array), 1, out); 870 fflush(out); 871 } 872 873 //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 874 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out) 875 { 876 EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 877 878 //MRS encoding information. 879 json_object *mrs_encoding = 880 json_object_object_get(registers, "mrsEncoding"); 881 reg_array.MrsOp2 = json_object_get_uint64( 882 json_object_object_get(mrs_encoding, "op2")); 883 reg_array.MrsCrm = json_object_get_uint64( 884 json_object_object_get(mrs_encoding, "crm")); 885 reg_array.MrsCrn = json_object_get_uint64( 886 json_object_object_get(mrs_encoding, "crn")); 887 reg_array.MrsOp1 = json_object_get_uint64( 888 json_object_object_get(mrs_encoding, "op1")); 889 reg_array.MrsO0 = json_object_get_uint64( 890 json_object_object_get(mrs_encoding, "o0")); 891 892 //Actual register value. 893 reg_array.Value = json_object_get_uint64( 894 json_object_object_get(registers, "value")); 895 896 //Flush to stream. 897 fwrite(®_array, sizeof(reg_array), 1, out); 898 fflush(out); 899 } 900 901 //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 902 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out) 903 { 904 //Get base64 represented data. 905 json_object *encoded = json_object_object_get(registers, "data"); 906 char *decoded = malloc(json_object_get_string_len(encoded)); 907 size_t decoded_len = 0; 908 if (!decoded) { 909 printf("Failed to allocate decode output buffer. \n"); 910 } else { 911 base64_decode(json_object_get_string(encoded), 912 json_object_get_string_len(encoded), decoded, 913 &decoded_len, 0); 914 915 //Flush out to stream. 916 fwrite(&decoded, decoded_len, 1, out); 917 fflush(out); 918 free(decoded); 919 } 920 } 921