12800cd8eSLawrence Tang /** 22800cd8eSLawrence Tang * Describes functions for converting ARM CPER sections from binary and JSON format 32800cd8eSLawrence Tang * into an intermediate format. 42800cd8eSLawrence Tang * 52800cd8eSLawrence Tang * Author: Lawrence.Tang@arm.com 62800cd8eSLawrence Tang **/ 72800cd8eSLawrence Tang 82800cd8eSLawrence Tang #include <stdio.h> 9*5202bbb4SLawrence Tang #include <json.h> 10d7e8ca34SLawrence Tang #include "b64.h" 112800cd8eSLawrence Tang #include "../edk/Cper.h" 122800cd8eSLawrence Tang #include "../cper-utils.h" 132800cd8eSLawrence Tang #include "cper-section-arm.h" 142800cd8eSLawrence Tang 153d0e4f24SLawrence Tang //Private pre-definitions. 16e407b4c8SLawrence Tang json_object * 17e407b4c8SLawrence Tang cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info); 18e407b4c8SLawrence Tang json_object * 19e407b4c8SLawrence Tang cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 20e407b4c8SLawrence Tang void **cur_pos); 21e407b4c8SLawrence Tang json_object * 22e407b4c8SLawrence Tang cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 23e407b4c8SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY *error_info); 247f21db6cSLawrence Tang json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error); 25e407b4c8SLawrence Tang json_object *cper_arm_misc_register_array_to_ir( 26e407b4c8SLawrence Tang EFI_ARM_MISC_CONTEXT_REGISTER *misc_register); 277cd13908SLawrence Tang void ir_arm_error_info_to_cper(json_object *error_info, FILE *out); 287cd13908SLawrence Tang void ir_arm_context_info_to_cper(json_object *context_info, FILE *out); 29e407b4c8SLawrence Tang void ir_arm_error_cache_tlb_info_to_cper( 30e407b4c8SLawrence Tang json_object *error_information, 31e407b4c8SLawrence Tang EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper); 32e407b4c8SLawrence Tang void ir_arm_error_bus_info_to_cper(json_object *error_information, 33e407b4c8SLawrence Tang EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper); 3471570a2aSLawrence Tang void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out); 3571570a2aSLawrence Tang void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out); 3671570a2aSLawrence Tang void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out); 3771570a2aSLawrence Tang void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out); 3871570a2aSLawrence Tang void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out); 3971570a2aSLawrence Tang void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out); 4071570a2aSLawrence Tang void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out); 4171570a2aSLawrence Tang void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out); 4271570a2aSLawrence Tang void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out); 43e407b4c8SLawrence Tang void ir_arm_unknown_register_to_cper(json_object *registers, 44e407b4c8SLawrence Tang EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 45e407b4c8SLawrence Tang FILE *out); 463d0e4f24SLawrence Tang 472800cd8eSLawrence Tang //Converts the given processor-generic CPER section into JSON IR. 48e407b4c8SLawrence Tang json_object *cper_section_arm_to_ir(void *section, 49e407b4c8SLawrence Tang EFI_ERROR_SECTION_DESCRIPTOR *descriptor) 502800cd8eSLawrence Tang { 517f21db6cSLawrence Tang EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section; 522800cd8eSLawrence Tang json_object *section_ir = json_object_new_object(); 532800cd8eSLawrence Tang 542800cd8eSLawrence Tang //Validation bits. 55e407b4c8SLawrence Tang json_object *validation = bitfield_to_ir( 56e407b4c8SLawrence Tang record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES); 572800cd8eSLawrence Tang json_object_object_add(section_ir, "validationBits", validation); 582800cd8eSLawrence Tang 592800cd8eSLawrence Tang //Number of error info and context info structures, and length. 60e407b4c8SLawrence Tang json_object_object_add(section_ir, "errorInfoNum", 61e407b4c8SLawrence Tang json_object_new_int(record->ErrInfoNum)); 62e407b4c8SLawrence Tang json_object_object_add(section_ir, "contextInfoNum", 63e407b4c8SLawrence Tang json_object_new_int(record->ContextInfoNum)); 64e407b4c8SLawrence Tang json_object_object_add(section_ir, "sectionLength", 65e407b4c8SLawrence Tang json_object_new_uint64(record->SectionLength)); 662800cd8eSLawrence Tang 672800cd8eSLawrence Tang //Error affinity. 682800cd8eSLawrence Tang json_object *error_affinity = json_object_new_object(); 69e407b4c8SLawrence Tang json_object_object_add(error_affinity, "value", 70e407b4c8SLawrence Tang json_object_new_int(record->ErrorAffinityLevel)); 71e407b4c8SLawrence Tang json_object_object_add( 72e407b4c8SLawrence Tang error_affinity, "type", 73e407b4c8SLawrence Tang json_object_new_string(record->ErrorAffinityLevel < 4 ? 74e407b4c8SLawrence Tang "Vendor Defined" : 75e407b4c8SLawrence Tang "Reserved")); 762800cd8eSLawrence Tang json_object_object_add(section_ir, "errorAffinity", error_affinity); 772800cd8eSLawrence Tang 782800cd8eSLawrence Tang //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1). 79e407b4c8SLawrence Tang json_object_object_add(section_ir, "mpidrEl1", 80e407b4c8SLawrence Tang json_object_new_uint64(record->MPIDR_EL1)); 81e407b4c8SLawrence Tang json_object_object_add(section_ir, "midrEl1", 82e407b4c8SLawrence Tang json_object_new_uint64(record->MIDR_EL1)); 832800cd8eSLawrence Tang 842800cd8eSLawrence Tang //Whether the processor is running, and the state of it if so. 85e407b4c8SLawrence Tang json_object_object_add(section_ir, "running", 86e407b4c8SLawrence Tang json_object_new_boolean(record->RunningState & 87e407b4c8SLawrence Tang 0b1)); 88e407b4c8SLawrence Tang if (!(record->RunningState >> 31)) { 893d0e4f24SLawrence Tang //Bit 32 of running state is on, so PSCI state information is included. 902721739aSLawrence Tang //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format 912721739aSLawrence Tang //or the newer Extended StateID format. 92e407b4c8SLawrence Tang json_object_object_add( 93e407b4c8SLawrence Tang section_ir, "psciState", 94e407b4c8SLawrence Tang json_object_new_uint64(record->PsciState)); 952800cd8eSLawrence Tang } 962800cd8eSLawrence Tang 973d0e4f24SLawrence Tang //Processor error structures. 983d0e4f24SLawrence Tang json_object *error_info_array = json_object_new_array(); 99e407b4c8SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error = 100e407b4c8SLawrence Tang (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1); 101e407b4c8SLawrence Tang for (int i = 0; i < record->ErrInfoNum; i++) { 102e407b4c8SLawrence Tang json_object_array_add(error_info_array, 103e407b4c8SLawrence Tang cper_arm_error_info_to_ir(cur_error)); 1047f21db6cSLawrence Tang cur_error++; 1053d0e4f24SLawrence Tang } 1067f21db6cSLawrence Tang json_object_object_add(section_ir, "errorInfo", error_info_array); 1077f21db6cSLawrence Tang 1087f21db6cSLawrence Tang //Processor context structures. 1097f21db6cSLawrence Tang //The current position is moved within the processing, as it is a dynamic size structure. 1107f21db6cSLawrence Tang void *cur_pos = (void *)cur_error; 1113636d3c2SLawrence Tang json_object *context_info_array = json_object_new_array(); 112e407b4c8SLawrence Tang for (int i = 0; i < record->ContextInfoNum; i++) { 113e407b4c8SLawrence Tang EFI_ARM_CONTEXT_INFORMATION_HEADER *header = 114e407b4c8SLawrence Tang (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos; 115e407b4c8SLawrence Tang json_object *processor_context = 116e407b4c8SLawrence Tang cper_arm_processor_context_to_ir(header, &cur_pos); 1173636d3c2SLawrence Tang json_object_array_add(context_info_array, processor_context); 1183636d3c2SLawrence Tang } 1193636d3c2SLawrence Tang json_object_object_add(section_ir, "contextInfo", context_info_array); 1207f21db6cSLawrence Tang 1217f21db6cSLawrence Tang //Is there any vendor-specific information following? 122e407b4c8SLawrence Tang if (cur_pos < section + record->SectionLength) { 123d7e8ca34SLawrence Tang json_object *vendor_specific = json_object_new_object(); 124e407b4c8SLawrence Tang char *encoded = 125e407b4c8SLawrence Tang b64_encode((unsigned char *)cur_pos, 126e407b4c8SLawrence Tang section + record->SectionLength - cur_pos); 127e407b4c8SLawrence Tang json_object_object_add(vendor_specific, "data", 128e407b4c8SLawrence Tang json_object_new_string(encoded)); 129d7e8ca34SLawrence Tang free(encoded); 130d7e8ca34SLawrence Tang 131e407b4c8SLawrence Tang json_object_object_add(section_ir, "vendorSpecificInfo", 132e407b4c8SLawrence Tang vendor_specific); 1337f21db6cSLawrence Tang } 1347f21db6cSLawrence Tang 1352800cd8eSLawrence Tang return section_ir; 1362800cd8eSLawrence Tang } 1373d0e4f24SLawrence Tang 1383d0e4f24SLawrence Tang //Converts a single ARM Process Error Information structure into JSON IR. 139e407b4c8SLawrence Tang json_object * 140e407b4c8SLawrence Tang cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 1413d0e4f24SLawrence Tang { 1423d0e4f24SLawrence Tang json_object *error_info_ir = json_object_new_object(); 1433d0e4f24SLawrence Tang 1443d0e4f24SLawrence Tang //Version, length. 145e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "version", 146e407b4c8SLawrence Tang json_object_new_int(error_info->Version)); 147e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "length", 148e407b4c8SLawrence Tang json_object_new_int(error_info->Length)); 1493d0e4f24SLawrence Tang 1503d0e4f24SLawrence Tang //Validation bitfield. 151e407b4c8SLawrence Tang json_object *validation = 152e407b4c8SLawrence Tang bitfield_to_ir(error_info->ValidationBits, 5, 153e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 1543d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "validationBits", validation); 1553d0e4f24SLawrence Tang 1563d0e4f24SLawrence Tang //The type of error information in this log. 157e407b4c8SLawrence Tang json_object *error_type = integer_to_readable_pair( 158e407b4c8SLawrence Tang error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS, 159e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)"); 1603d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "errorType", error_type); 1613d0e4f24SLawrence Tang 1623d0e4f24SLawrence Tang //Multiple error count. 16322a467ceSLawrence Tang json_object *multiple_error = json_object_new_object(); 164e407b4c8SLawrence Tang json_object_object_add(multiple_error, "value", 165e407b4c8SLawrence Tang json_object_new_int(error_info->MultipleError)); 166e407b4c8SLawrence Tang json_object_object_add( 167e407b4c8SLawrence Tang multiple_error, "type", 168e407b4c8SLawrence Tang json_object_new_string(error_info->MultipleError < 1 ? 169e407b4c8SLawrence Tang "Single Error" : 170e407b4c8SLawrence Tang "Multiple Errors")); 1713d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "multipleError", multiple_error); 1723d0e4f24SLawrence Tang 1733d0e4f24SLawrence Tang //Flags. 174e407b4c8SLawrence Tang json_object *flags = bitfield_to_ir(error_info->Flags, 4, 175e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 1763d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "flags", flags); 1773d0e4f24SLawrence Tang 1783d0e4f24SLawrence Tang //Error information, split by type. 1793d0e4f24SLawrence Tang json_object *error_subinfo = NULL; 180e407b4c8SLawrence Tang switch (error_info->Type) { 18171570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache 18271570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB 183e407b4c8SLawrence Tang error_subinfo = cper_arm_cache_tlb_error_to_ir( 184e407b4c8SLawrence Tang (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info 185e407b4c8SLawrence Tang ->ErrorInformation, 186e407b4c8SLawrence Tang error_info); 1873d0e4f24SLawrence Tang break; 18871570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus 189e407b4c8SLawrence Tang error_subinfo = cper_arm_bus_error_to_ir( 190e407b4c8SLawrence Tang (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info 191e407b4c8SLawrence Tang ->ErrorInformation); 1923d0e4f24SLawrence Tang break; 19371570a2aSLawrence Tang 19471570a2aSLawrence Tang default: 19571570a2aSLawrence Tang //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object. 19671570a2aSLawrence Tang error_subinfo = json_object_new_object(); 197e407b4c8SLawrence Tang json_object_object_add( 198e407b4c8SLawrence Tang error_subinfo, "data", 199e407b4c8SLawrence Tang json_object_new_uint64( 200e407b4c8SLawrence Tang *((UINT64 *)&error_info->ErrorInformation))); 20171570a2aSLawrence Tang break; 2023d0e4f24SLawrence Tang } 203e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "errorInformation", 204e407b4c8SLawrence Tang error_subinfo); 2053d0e4f24SLawrence Tang 206b98ec66cSLawrence Tang //Virtual fault address, physical fault address. 207e407b4c8SLawrence Tang json_object_object_add( 208e407b4c8SLawrence Tang error_info_ir, "virtualFaultAddress", 209e407b4c8SLawrence Tang json_object_new_uint64(error_info->VirtualFaultAddress)); 210e407b4c8SLawrence Tang json_object_object_add( 211e407b4c8SLawrence Tang error_info_ir, "physicalFaultAddress", 212e407b4c8SLawrence Tang json_object_new_uint64(error_info->PhysicalFaultAddress)); 213b98ec66cSLawrence Tang 2143d0e4f24SLawrence Tang return error_info_ir; 2153d0e4f24SLawrence Tang } 2163d0e4f24SLawrence Tang 2177f21db6cSLawrence Tang //Converts a single ARM cache/TLB error information structure into JSON IR format. 218e407b4c8SLawrence Tang json_object * 219e407b4c8SLawrence Tang cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 220e407b4c8SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 2213d0e4f24SLawrence Tang { 2227f21db6cSLawrence Tang json_object *cache_tlb_error_ir = json_object_new_object(); 2233d0e4f24SLawrence Tang 2247f21db6cSLawrence Tang //Validation bitfield. 225e407b4c8SLawrence Tang json_object *validation = 226e407b4c8SLawrence Tang bitfield_to_ir(cache_tlb_error->ValidationBits, 7, 227e407b4c8SLawrence Tang ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 228e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "validationBits", 229e407b4c8SLawrence Tang validation); 2307f21db6cSLawrence Tang 2317f21db6cSLawrence Tang //Transaction type. 232e407b4c8SLawrence Tang json_object *transaction_type = integer_to_readable_pair( 233e407b4c8SLawrence Tang cache_tlb_error->TransactionType, 3, 2347f21db6cSLawrence Tang ARM_ERROR_TRANSACTION_TYPES_KEYS, 235e407b4c8SLawrence Tang ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 236e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "transactionType", 237e407b4c8SLawrence Tang transaction_type); 2387f21db6cSLawrence Tang 2397f21db6cSLawrence Tang //Operation. 2407f21db6cSLawrence Tang json_object *operation; 241e407b4c8SLawrence Tang if (error_info->Type == 0) { 2427f21db6cSLawrence Tang //Cache operation. 243e407b4c8SLawrence Tang operation = integer_to_readable_pair( 244e407b4c8SLawrence Tang cache_tlb_error->Operation, 11, 2457f21db6cSLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 2467f21db6cSLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 2477f21db6cSLawrence Tang "Unknown (Reserved)"); 248e407b4c8SLawrence Tang } else { 2497f21db6cSLawrence Tang //TLB operation. 250e407b4c8SLawrence Tang operation = integer_to_readable_pair( 251e407b4c8SLawrence Tang cache_tlb_error->Operation, 9, 2527f21db6cSLawrence Tang ARM_TLB_OPERATION_TYPES_KEYS, 253e407b4c8SLawrence Tang ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 2547f21db6cSLawrence Tang } 2557f21db6cSLawrence Tang json_object_object_add(cache_tlb_error_ir, "operation", operation); 2567f21db6cSLawrence Tang 2577f21db6cSLawrence Tang //Miscellaneous remaining fields. 258e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "level", 259e407b4c8SLawrence Tang json_object_new_int(cache_tlb_error->Level)); 260e407b4c8SLawrence Tang json_object_object_add( 261e407b4c8SLawrence Tang cache_tlb_error_ir, "processorContextCorrupt", 262e407b4c8SLawrence Tang json_object_new_boolean( 263e407b4c8SLawrence Tang cache_tlb_error->ProcessorContextCorrupt)); 264e407b4c8SLawrence Tang json_object_object_add( 265e407b4c8SLawrence Tang cache_tlb_error_ir, "corrected", 266e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->Corrected)); 267e407b4c8SLawrence Tang json_object_object_add( 268e407b4c8SLawrence Tang cache_tlb_error_ir, "precisePC", 269e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->PrecisePC)); 270e407b4c8SLawrence Tang json_object_object_add( 271e407b4c8SLawrence Tang cache_tlb_error_ir, "restartablePC", 272e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->RestartablePC)); 2737f21db6cSLawrence Tang return cache_tlb_error_ir; 2743d0e4f24SLawrence Tang } 2753d0e4f24SLawrence Tang 2763d0e4f24SLawrence Tang //Converts a single ARM bus error information structure into JSON IR format. 2777f21db6cSLawrence Tang json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error) 2783d0e4f24SLawrence Tang { 2797f21db6cSLawrence Tang json_object *bus_error_ir = json_object_new_object(); 2807f21db6cSLawrence Tang 2817f21db6cSLawrence Tang //Validation bits. 282e407b4c8SLawrence Tang json_object *validation = 283e407b4c8SLawrence Tang bitfield_to_ir(bus_error->ValidationBits, 12, 284e407b4c8SLawrence Tang ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 2857f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "validationBits", validation); 2867f21db6cSLawrence Tang 2877f21db6cSLawrence Tang //Transaction type. 288e407b4c8SLawrence Tang json_object *transaction_type = integer_to_readable_pair( 289e407b4c8SLawrence Tang bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS, 290e407b4c8SLawrence Tang ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 291e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "transactionType", 292e407b4c8SLawrence Tang transaction_type); 2937f21db6cSLawrence Tang 2947f21db6cSLawrence Tang //Operation. 295e407b4c8SLawrence Tang json_object *operation = integer_to_readable_pair( 296e407b4c8SLawrence Tang bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 297e407b4c8SLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 2987f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "operation", operation); 2997f21db6cSLawrence Tang 3007f21db6cSLawrence Tang //Affinity level of bus error, + miscellaneous fields. 301e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "level", 302e407b4c8SLawrence Tang json_object_new_int(bus_error->Level)); 303e407b4c8SLawrence Tang json_object_object_add( 304e407b4c8SLawrence Tang bus_error_ir, "processorContextCorrupt", 305e407b4c8SLawrence Tang json_object_new_boolean(bus_error->ProcessorContextCorrupt)); 306e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "corrected", 307e407b4c8SLawrence Tang json_object_new_boolean(bus_error->Corrected)); 308e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "precisePC", 309e407b4c8SLawrence Tang json_object_new_boolean(bus_error->PrecisePC)); 310e407b4c8SLawrence Tang json_object_object_add( 311e407b4c8SLawrence Tang bus_error_ir, "restartablePC", 312e407b4c8SLawrence Tang json_object_new_boolean(bus_error->RestartablePC)); 313e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "timedOut", 314e407b4c8SLawrence Tang json_object_new_boolean(bus_error->TimeOut)); 3157f21db6cSLawrence Tang 3167f21db6cSLawrence Tang //Participation type. 317e407b4c8SLawrence Tang json_object *participation_type = integer_to_readable_pair( 318e407b4c8SLawrence Tang bus_error->ParticipationType, 4, 3197f21db6cSLawrence Tang ARM_BUS_PARTICIPATION_TYPES_KEYS, 320e407b4c8SLawrence Tang ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown"); 321e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "participationType", 322e407b4c8SLawrence Tang participation_type); 3237f21db6cSLawrence Tang 3247f21db6cSLawrence Tang //Address space. 325e407b4c8SLawrence Tang json_object *address_space = integer_to_readable_pair( 326e407b4c8SLawrence Tang bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS, 327e407b4c8SLawrence Tang ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown"); 3287f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "addressSpace", address_space); 3297f21db6cSLawrence Tang 3307f21db6cSLawrence Tang //Memory access attributes. 3317f21db6cSLawrence Tang //todo: find the specification of these in the ARM ARM 332e407b4c8SLawrence Tang json_object_object_add( 333e407b4c8SLawrence Tang bus_error_ir, "memoryAttributes", 334e407b4c8SLawrence Tang json_object_new_int(bus_error->MemoryAddressAttributes)); 3357f21db6cSLawrence Tang 3367f21db6cSLawrence Tang //Access Mode 3377f21db6cSLawrence Tang json_object *access_mode = json_object_new_object(); 338e407b4c8SLawrence Tang json_object_object_add(access_mode, "value", 339e407b4c8SLawrence Tang json_object_new_int(bus_error->AccessMode)); 340e407b4c8SLawrence Tang json_object_object_add( 341e407b4c8SLawrence Tang access_mode, "name", 342e407b4c8SLawrence Tang json_object_new_string(bus_error->AccessMode == 0 ? "Secure" : 343e407b4c8SLawrence Tang "Normal")); 3447f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "accessMode", access_mode); 3457f21db6cSLawrence Tang 3467f21db6cSLawrence Tang return bus_error_ir; 3477f21db6cSLawrence Tang } 3487f21db6cSLawrence Tang 3497f21db6cSLawrence Tang //Converts a single ARM processor context block into JSON IR. 350e407b4c8SLawrence Tang json_object * 351e407b4c8SLawrence Tang cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 352e407b4c8SLawrence Tang void **cur_pos) 3537f21db6cSLawrence Tang { 3547f21db6cSLawrence Tang json_object *context_ir = json_object_new_object(); 3557f21db6cSLawrence Tang 35671570a2aSLawrence Tang //Version. 357e407b4c8SLawrence Tang json_object_object_add(context_ir, "version", 358e407b4c8SLawrence Tang json_object_new_int(header->Version)); 35971570a2aSLawrence Tang 3607f21db6cSLawrence Tang //Add the context type. 361e407b4c8SLawrence Tang json_object *context_type = integer_to_readable_pair( 362e407b4c8SLawrence Tang header->RegisterContextType, 9, 3637f21db6cSLawrence Tang ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS, 3647f21db6cSLawrence Tang ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES, 3657f21db6cSLawrence Tang "Unknown (Reserved)"); 3667f21db6cSLawrence Tang json_object_object_add(context_ir, "registerContextType", context_type); 3677f21db6cSLawrence Tang 3687f21db6cSLawrence Tang //Register array size (bytes). 369e407b4c8SLawrence Tang json_object_object_add( 370e407b4c8SLawrence Tang context_ir, "registerArraySize", 371e407b4c8SLawrence Tang json_object_new_uint64(header->RegisterArraySize)); 3727f21db6cSLawrence Tang 3737f21db6cSLawrence Tang //The register array itself. 3747f21db6cSLawrence Tang *cur_pos = (void *)(header + 1); 3757f21db6cSLawrence Tang json_object *register_array = NULL; 376e407b4c8SLawrence Tang switch (header->RegisterContextType) { 3777f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 378e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 379e407b4c8SLawrence Tang (UINT32 *)cur_pos, 380e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 381e407b4c8SLawrence Tang ARM_AARCH32_GPR_NAMES); 3827f21db6cSLawrence Tang break; 3837f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 384e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 385e407b4c8SLawrence Tang (UINT32 *)cur_pos, 386e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 387e407b4c8SLawrence Tang sizeof(UINT32), 388e407b4c8SLawrence Tang ARM_AARCH32_EL1_REGISTER_NAMES); 3897f21db6cSLawrence Tang break; 3907f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 391e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 392e407b4c8SLawrence Tang (UINT32 *)cur_pos, 393e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 394e407b4c8SLawrence Tang sizeof(UINT32), 395e407b4c8SLawrence Tang ARM_AARCH32_EL2_REGISTER_NAMES); 3967f21db6cSLawrence Tang break; 3977f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 398e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 399e407b4c8SLawrence Tang (UINT32 *)cur_pos, 400e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 401e407b4c8SLawrence Tang sizeof(UINT32), 402e407b4c8SLawrence Tang ARM_AARCH32_SECURE_REGISTER_NAMES); 4037f21db6cSLawrence Tang break; 4047f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 405e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 406e407b4c8SLawrence Tang (UINT64 *)cur_pos, 407e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 408e407b4c8SLawrence Tang ARM_AARCH64_GPR_NAMES); 4097f21db6cSLawrence Tang break; 4107f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 411e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 412e407b4c8SLawrence Tang (UINT64 *)cur_pos, 413e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 414e407b4c8SLawrence Tang sizeof(UINT64), 415e407b4c8SLawrence Tang ARM_AARCH64_EL1_REGISTER_NAMES); 4167f21db6cSLawrence Tang break; 4177f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 418e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 419e407b4c8SLawrence Tang (UINT64 *)cur_pos, 420e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 421e407b4c8SLawrence Tang sizeof(UINT64), 422e407b4c8SLawrence Tang ARM_AARCH64_EL2_REGISTER_NAMES); 4237f21db6cSLawrence Tang break; 4247f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 425e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 426e407b4c8SLawrence Tang (UINT64 *)cur_pos, 427e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 428e407b4c8SLawrence Tang sizeof(UINT64), 429e407b4c8SLawrence Tang ARM_AARCH64_EL3_REGISTER_NAMES); 4307f21db6cSLawrence Tang break; 4317f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_MISC: 432e407b4c8SLawrence Tang register_array = cper_arm_misc_register_array_to_ir( 433e407b4c8SLawrence Tang (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos); 4347f21db6cSLawrence Tang break; 4357f21db6cSLawrence Tang default: 436d7e8ca34SLawrence Tang //Unknown register array type, add as base64 data instead. 4377f21db6cSLawrence Tang register_array = json_object_new_object(); 438e407b4c8SLawrence Tang char *encoded = b64_encode((unsigned char *)cur_pos, 439e407b4c8SLawrence Tang header->RegisterArraySize); 440e407b4c8SLawrence Tang json_object_object_add(register_array, "data", 441e407b4c8SLawrence Tang json_object_new_string(encoded)); 442d7e8ca34SLawrence Tang free(encoded); 4437f21db6cSLawrence Tang break; 4447f21db6cSLawrence Tang } 4453636d3c2SLawrence Tang json_object_object_add(context_ir, "registerArray", register_array); 4467f21db6cSLawrence Tang 4477f21db6cSLawrence Tang //Set the current position to after the processor context structure. 4487f21db6cSLawrence Tang *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize; 4497f21db6cSLawrence Tang 4507f21db6cSLawrence Tang return context_ir; 4517f21db6cSLawrence Tang } 4527f21db6cSLawrence Tang 4537f21db6cSLawrence Tang //Converts a single CPER ARM miscellaneous register array to JSON IR format. 454e407b4c8SLawrence Tang json_object * 455e407b4c8SLawrence Tang cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register) 4567f21db6cSLawrence Tang { 4577f21db6cSLawrence Tang json_object *register_array = json_object_new_object(); 4587f21db6cSLawrence Tang json_object *mrs_encoding = json_object_new_object(); 459e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "op2", 460e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsOp2)); 461e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "crm", 462e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsCrm)); 463e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "crn", 464e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsCrn)); 465e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "op1", 466e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsOp1)); 467e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "o0", 468e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsO0)); 4697f21db6cSLawrence Tang json_object_object_add(register_array, "mrsEncoding", mrs_encoding); 470e407b4c8SLawrence Tang json_object_object_add(register_array, "value", 471e407b4c8SLawrence Tang json_object_new_uint64(misc_register->Value)); 4727f21db6cSLawrence Tang 4737f21db6cSLawrence Tang return register_array; 4743d0e4f24SLawrence Tang } 4757cd13908SLawrence Tang 4767cd13908SLawrence Tang //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream. 4777cd13908SLawrence Tang void ir_section_arm_to_cper(json_object *section, FILE *out) 4787cd13908SLawrence Tang { 479e407b4c8SLawrence Tang EFI_ARM_ERROR_RECORD *section_cper = 480e407b4c8SLawrence Tang (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD)); 48101e3a44dSLawrence Tang long starting_stream_pos = ftell(out); 4827cd13908SLawrence Tang 4837cd13908SLawrence Tang //Validation bits. 484e407b4c8SLawrence Tang section_cper->ValidFields = ir_to_bitfield( 485e407b4c8SLawrence Tang json_object_object_get(section, "validationBits"), 4, 486e407b4c8SLawrence Tang ARM_ERROR_VALID_BITFIELD_NAMES); 4877cd13908SLawrence Tang 4887cd13908SLawrence Tang //Count of error/context info structures. 489e407b4c8SLawrence Tang section_cper->ErrInfoNum = json_object_get_int( 490e407b4c8SLawrence Tang json_object_object_get(section, "errorInfoNum")); 491e407b4c8SLawrence Tang section_cper->ContextInfoNum = json_object_get_int( 492e407b4c8SLawrence Tang json_object_object_get(section, "contextInfoNum")); 4937cd13908SLawrence Tang 4947cd13908SLawrence Tang //Miscellaneous raw value fields. 495e407b4c8SLawrence Tang section_cper->SectionLength = json_object_get_uint64( 496e407b4c8SLawrence Tang json_object_object_get(section, "sectionLength")); 497e407b4c8SLawrence Tang section_cper->ErrorAffinityLevel = readable_pair_to_integer( 498e407b4c8SLawrence Tang json_object_object_get(section, "errorAffinity")); 499e407b4c8SLawrence Tang section_cper->MPIDR_EL1 = json_object_get_uint64( 500e407b4c8SLawrence Tang json_object_object_get(section, "mpidrEl1")); 501e407b4c8SLawrence Tang section_cper->MIDR_EL1 = json_object_get_uint64( 502e407b4c8SLawrence Tang json_object_object_get(section, "midrEl1")); 503e407b4c8SLawrence Tang section_cper->RunningState = json_object_get_boolean( 504e407b4c8SLawrence Tang json_object_object_get(section, "running")); 5057cd13908SLawrence Tang 5067cd13908SLawrence Tang //Optional PSCI state. 5077cd13908SLawrence Tang json_object *psci_state = json_object_object_get(section, "psciState"); 5087cd13908SLawrence Tang if (psci_state != NULL) 5097cd13908SLawrence Tang section_cper->PsciState = json_object_get_uint64(psci_state); 5107cd13908SLawrence Tang 5117cd13908SLawrence Tang //Flush header to stream. 5127cd13908SLawrence Tang fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out); 5137cd13908SLawrence Tang fflush(out); 5147cd13908SLawrence Tang 5157cd13908SLawrence Tang //Error info structure array. 5167cd13908SLawrence Tang json_object *error_info = json_object_object_get(section, "errorInfo"); 5177cd13908SLawrence Tang for (int i = 0; i < section_cper->ErrInfoNum; i++) 518e407b4c8SLawrence Tang ir_arm_error_info_to_cper( 519e407b4c8SLawrence Tang json_object_array_get_idx(error_info, i), out); 5207cd13908SLawrence Tang 5217cd13908SLawrence Tang //Context info structure array. 522e407b4c8SLawrence Tang json_object *context_info = 523e407b4c8SLawrence Tang json_object_object_get(section, "contextInfo"); 5247cd13908SLawrence Tang for (int i = 0; i < section_cper->ContextInfoNum; i++) 525e407b4c8SLawrence Tang ir_arm_context_info_to_cper( 526e407b4c8SLawrence Tang json_object_array_get_idx(context_info, i), out); 5277cd13908SLawrence Tang 5287cd13908SLawrence Tang //Vendor specific error info. 529e407b4c8SLawrence Tang json_object *vendor_specific_info = 530e407b4c8SLawrence Tang json_object_object_get(section, "vendorSpecificInfo"); 531e407b4c8SLawrence Tang if (vendor_specific_info != NULL) { 532e407b4c8SLawrence Tang json_object *vendor_info_string = 533e407b4c8SLawrence Tang json_object_object_get(vendor_specific_info, "data"); 534e407b4c8SLawrence Tang int vendor_specific_len = 535e407b4c8SLawrence Tang json_object_get_string_len(vendor_info_string); 536e407b4c8SLawrence Tang UINT8 *decoded = 537e407b4c8SLawrence Tang b64_decode(json_object_get_string(vendor_info_string), 538e407b4c8SLawrence Tang vendor_specific_len); 53901e3a44dSLawrence Tang 54001e3a44dSLawrence Tang //Write out to file. 54101e3a44dSLawrence Tang long cur_stream_pos = ftell(out); 542e407b4c8SLawrence Tang fwrite(decoded, 543e407b4c8SLawrence Tang starting_stream_pos + section_cper->SectionLength - 544e407b4c8SLawrence Tang cur_stream_pos, 545e407b4c8SLawrence Tang 1, out); 5467cd13908SLawrence Tang fflush(out); 5477cd13908SLawrence Tang free(decoded); 5487cd13908SLawrence Tang } 5497cd13908SLawrence Tang 5507cd13908SLawrence Tang //Free remaining resources. 5517cd13908SLawrence Tang free(section_cper); 5527cd13908SLawrence Tang } 5537cd13908SLawrence Tang 5547cd13908SLawrence Tang //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 5557cd13908SLawrence Tang void ir_arm_error_info_to_cper(json_object *error_info, FILE *out) 5567cd13908SLawrence Tang { 5577cd13908SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 5587cd13908SLawrence Tang 5597cd13908SLawrence Tang //Version, length. 560e407b4c8SLawrence Tang error_info_cper.Version = json_object_get_int( 561e407b4c8SLawrence Tang json_object_object_get(error_info, "version")); 562e407b4c8SLawrence Tang error_info_cper.Length = json_object_get_int( 563e407b4c8SLawrence Tang json_object_object_get(error_info, "length")); 5647cd13908SLawrence Tang 5657cd13908SLawrence Tang //Validation bits. 566e407b4c8SLawrence Tang error_info_cper.ValidationBits = ir_to_bitfield( 567e407b4c8SLawrence Tang json_object_object_get(error_info, "validationBits"), 5, 568e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 5697cd13908SLawrence Tang 5707cd13908SLawrence Tang //Type, multiple error. 571e407b4c8SLawrence Tang error_info_cper.Type = (UINT8)readable_pair_to_integer( 572e407b4c8SLawrence Tang json_object_object_get(error_info, "type")); 573e407b4c8SLawrence Tang error_info_cper.MultipleError = (UINT16)readable_pair_to_integer( 574e407b4c8SLawrence Tang json_object_object_get(error_info, "multipleError")); 5757cd13908SLawrence Tang 5767cd13908SLawrence Tang //Flags object. 577e407b4c8SLawrence Tang error_info_cper.Flags = (UINT8)ir_to_bitfield( 578e407b4c8SLawrence Tang json_object_object_get(error_info, "flags"), 4, 579e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 5807cd13908SLawrence Tang 5817cd13908SLawrence Tang //Error information. 582e407b4c8SLawrence Tang json_object *error_info_information = 583e407b4c8SLawrence Tang json_object_object_get(error_info, "errorInformation"); 584e407b4c8SLawrence Tang switch (error_info_cper.Type) { 58571570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_CACHE: 58671570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_TLB: 587e407b4c8SLawrence Tang ir_arm_error_cache_tlb_info_to_cper( 588e407b4c8SLawrence Tang error_info_information, 589e407b4c8SLawrence Tang &error_info_cper.ErrorInformation.CacheError); 59071570a2aSLawrence Tang break; 59171570a2aSLawrence Tang 59271570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_BUS: 593e407b4c8SLawrence Tang ir_arm_error_bus_info_to_cper( 594e407b4c8SLawrence Tang error_info_information, 595e407b4c8SLawrence Tang &error_info_cper.ErrorInformation.BusError); 59671570a2aSLawrence Tang break; 59771570a2aSLawrence Tang 59871570a2aSLawrence Tang default: 59971570a2aSLawrence Tang //Unknown error information type. 60071570a2aSLawrence Tang *((UINT64 *)&error_info_cper.ErrorInformation) = 601e407b4c8SLawrence Tang json_object_get_uint64(json_object_object_get( 602e407b4c8SLawrence Tang error_info_information, "data")); 60371570a2aSLawrence Tang break; 60471570a2aSLawrence Tang } 6057cd13908SLawrence Tang 6067cd13908SLawrence Tang //Virtual/physical fault address. 607e407b4c8SLawrence Tang error_info_cper.VirtualFaultAddress = json_object_get_uint64( 608e407b4c8SLawrence Tang json_object_object_get(error_info, "virtualFaultAddress")); 609e407b4c8SLawrence Tang error_info_cper.PhysicalFaultAddress = json_object_get_uint64( 610e407b4c8SLawrence Tang json_object_object_get(error_info, "physicalFaultAddress")); 6117cd13908SLawrence Tang 6127cd13908SLawrence Tang //Write out to stream. 613e407b4c8SLawrence Tang fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, 614e407b4c8SLawrence Tang out); 6157cd13908SLawrence Tang fflush(out); 6167cd13908SLawrence Tang } 6177cd13908SLawrence Tang 61871570a2aSLawrence Tang //Converts a single ARM cache/TLB error information structure into a CPER structure. 619e407b4c8SLawrence Tang void ir_arm_error_cache_tlb_info_to_cper( 620e407b4c8SLawrence Tang json_object *error_information, 621e407b4c8SLawrence Tang EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper) 62271570a2aSLawrence Tang { 62371570a2aSLawrence Tang //Validation bits. 624e407b4c8SLawrence Tang error_info_cper->ValidationBits = ir_to_bitfield( 625e407b4c8SLawrence Tang json_object_object_get(error_information, "validationBits"), 7, 626e407b4c8SLawrence Tang ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 62771570a2aSLawrence Tang 62871570a2aSLawrence Tang //Miscellaneous value fields. 629e407b4c8SLawrence Tang error_info_cper->TransactionType = readable_pair_to_integer( 630e407b4c8SLawrence Tang json_object_object_get(error_information, "transactionType")); 631e407b4c8SLawrence Tang error_info_cper->Operation = readable_pair_to_integer( 632e407b4c8SLawrence Tang json_object_object_get(error_information, "operation")); 633e407b4c8SLawrence Tang error_info_cper->Level = json_object_get_uint64( 634e407b4c8SLawrence Tang json_object_object_get(error_information, "level")); 635e407b4c8SLawrence Tang error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 636e407b4c8SLawrence Tang json_object_object_get(error_information, 637e407b4c8SLawrence Tang "processorContextCorrupt")); 638e407b4c8SLawrence Tang error_info_cper->Corrected = json_object_get_boolean( 639e407b4c8SLawrence Tang json_object_object_get(error_information, "corrected")); 640e407b4c8SLawrence Tang error_info_cper->PrecisePC = json_object_get_boolean( 641e407b4c8SLawrence Tang json_object_object_get(error_information, "precisePC")); 642e407b4c8SLawrence Tang error_info_cper->RestartablePC = json_object_get_boolean( 643e407b4c8SLawrence Tang json_object_object_get(error_information, "restartablePC")); 64471570a2aSLawrence Tang error_info_cper->Reserved = 0; 64571570a2aSLawrence Tang } 64671570a2aSLawrence Tang 64771570a2aSLawrence Tang //Converts a single ARM bus error information structure into a CPER structure. 648e407b4c8SLawrence Tang void ir_arm_error_bus_info_to_cper(json_object *error_information, 649e407b4c8SLawrence Tang EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper) 65071570a2aSLawrence Tang { 65171570a2aSLawrence Tang //Validation bits. 652e407b4c8SLawrence Tang error_info_cper->ValidationBits = ir_to_bitfield( 653e407b4c8SLawrence Tang json_object_object_get(error_information, "validationBits"), 7, 654e407b4c8SLawrence Tang ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 65571570a2aSLawrence Tang 65671570a2aSLawrence Tang //Miscellaneous value fields. 657e407b4c8SLawrence Tang error_info_cper->TransactionType = readable_pair_to_integer( 658e407b4c8SLawrence Tang json_object_object_get(error_information, "transactionType")); 659e407b4c8SLawrence Tang error_info_cper->Operation = readable_pair_to_integer( 660e407b4c8SLawrence Tang json_object_object_get(error_information, "operation")); 661e407b4c8SLawrence Tang error_info_cper->Level = json_object_get_uint64( 662e407b4c8SLawrence Tang json_object_object_get(error_information, "level")); 663e407b4c8SLawrence Tang error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 664e407b4c8SLawrence Tang json_object_object_get(error_information, 665e407b4c8SLawrence Tang "processorContextCorrupt")); 666e407b4c8SLawrence Tang error_info_cper->Corrected = json_object_get_boolean( 667e407b4c8SLawrence Tang json_object_object_get(error_information, "corrected")); 668e407b4c8SLawrence Tang error_info_cper->PrecisePC = json_object_get_boolean( 669e407b4c8SLawrence Tang json_object_object_get(error_information, "precisePC")); 670e407b4c8SLawrence Tang error_info_cper->RestartablePC = json_object_get_boolean( 671e407b4c8SLawrence Tang json_object_object_get(error_information, "restartablePC")); 672e407b4c8SLawrence Tang error_info_cper->ParticipationType = readable_pair_to_integer( 673e407b4c8SLawrence Tang json_object_object_get(error_information, "participationType")); 674e407b4c8SLawrence Tang error_info_cper->AddressSpace = readable_pair_to_integer( 675e407b4c8SLawrence Tang json_object_object_get(error_information, "addressSpace")); 676e407b4c8SLawrence Tang error_info_cper->AccessMode = readable_pair_to_integer( 677e407b4c8SLawrence Tang json_object_object_get(error_information, "accessMode")); 678e407b4c8SLawrence Tang error_info_cper->MemoryAddressAttributes = json_object_get_uint64( 679e407b4c8SLawrence Tang json_object_object_get(error_information, "memoryAttributes")); 68071570a2aSLawrence Tang error_info_cper->Reserved = 0; 68171570a2aSLawrence Tang } 68271570a2aSLawrence Tang 6837cd13908SLawrence Tang //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 6847cd13908SLawrence Tang void ir_arm_context_info_to_cper(json_object *context_info, FILE *out) 6857cd13908SLawrence Tang { 68671570a2aSLawrence Tang EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 6877cd13908SLawrence Tang 68871570a2aSLawrence Tang //Version, array size, context type. 689e407b4c8SLawrence Tang info_header.Version = json_object_get_int( 690e407b4c8SLawrence Tang json_object_object_get(context_info, "version")); 691e407b4c8SLawrence Tang info_header.RegisterArraySize = json_object_get_int( 692e407b4c8SLawrence Tang json_object_object_get(context_info, "registerArraySize")); 693e407b4c8SLawrence Tang info_header.RegisterContextType = readable_pair_to_integer( 694e407b4c8SLawrence Tang json_object_object_get(context_info, "registerContextType")); 69571570a2aSLawrence Tang 69671570a2aSLawrence Tang //Flush to stream, write the register array itself. 697e407b4c8SLawrence Tang fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, 698e407b4c8SLawrence Tang out); 69971570a2aSLawrence Tang fflush(out); 70071570a2aSLawrence Tang 701e407b4c8SLawrence Tang json_object *register_array = 702e407b4c8SLawrence Tang json_object_object_get(context_info, "registerArray"); 703e407b4c8SLawrence Tang switch (info_header.RegisterContextType) { 70471570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 70571570a2aSLawrence Tang ir_arm_aarch32_gpr_to_cper(register_array, out); 70671570a2aSLawrence Tang break; 70771570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 70871570a2aSLawrence Tang ir_arm_aarch32_el1_to_cper(register_array, out); 70971570a2aSLawrence Tang break; 71071570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 71171570a2aSLawrence Tang ir_arm_aarch32_el2_to_cper(register_array, out); 71271570a2aSLawrence Tang break; 71371570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 71471570a2aSLawrence Tang ir_arm_aarch32_secure_to_cper(register_array, out); 71571570a2aSLawrence Tang break; 71671570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 71771570a2aSLawrence Tang ir_arm_aarch64_gpr_to_cper(register_array, out); 71871570a2aSLawrence Tang break; 71971570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 72071570a2aSLawrence Tang ir_arm_aarch64_el1_to_cper(register_array, out); 72171570a2aSLawrence Tang break; 72271570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 72371570a2aSLawrence Tang ir_arm_aarch64_el2_to_cper(register_array, out); 72471570a2aSLawrence Tang break; 72571570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 72671570a2aSLawrence Tang ir_arm_aarch64_el3_to_cper(register_array, out); 72771570a2aSLawrence Tang break; 72871570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_MISC: 72971570a2aSLawrence Tang ir_arm_misc_registers_to_cper(register_array, out); 73071570a2aSLawrence Tang break; 73171570a2aSLawrence Tang default: 73271570a2aSLawrence Tang //Unknown register structure. 733e407b4c8SLawrence Tang ir_arm_unknown_register_to_cper(register_array, &info_header, 734e407b4c8SLawrence Tang out); 73571570a2aSLawrence Tang break; 73671570a2aSLawrence Tang } 73771570a2aSLawrence Tang } 73871570a2aSLawrence Tang 73971570a2aSLawrence Tang //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 74071570a2aSLawrence Tang void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out) 74171570a2aSLawrence Tang { 74271570a2aSLawrence Tang //Get uniform register array. 74371570a2aSLawrence Tang EFI_ARM_V8_AARCH32_GPR reg_array; 74471570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 745e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 746e407b4c8SLawrence Tang ARM_AARCH32_GPR_NAMES); 74771570a2aSLawrence Tang 74871570a2aSLawrence Tang //Flush to stream. 74971570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 75071570a2aSLawrence Tang fflush(out); 75171570a2aSLawrence Tang } 75271570a2aSLawrence Tang 75371570a2aSLawrence Tang //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 75471570a2aSLawrence Tang void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out) 75571570a2aSLawrence Tang { 75671570a2aSLawrence Tang //Get uniform register array. 75771570a2aSLawrence Tang EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 75871570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 759e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 760e407b4c8SLawrence Tang sizeof(UINT32), 761e407b4c8SLawrence Tang ARM_AARCH32_EL1_REGISTER_NAMES); 76271570a2aSLawrence Tang 76371570a2aSLawrence Tang //Flush to stream. 76471570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 76571570a2aSLawrence Tang fflush(out); 76671570a2aSLawrence Tang } 76771570a2aSLawrence Tang 76871570a2aSLawrence Tang //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 76971570a2aSLawrence Tang void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out) 77071570a2aSLawrence Tang { 77171570a2aSLawrence Tang //Get uniform register array. 77271570a2aSLawrence Tang EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 77371570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 774e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 775e407b4c8SLawrence Tang sizeof(UINT32), 776e407b4c8SLawrence Tang ARM_AARCH32_EL2_REGISTER_NAMES); 77771570a2aSLawrence Tang 77871570a2aSLawrence Tang //Flush to stream. 77971570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 78071570a2aSLawrence Tang fflush(out); 78171570a2aSLawrence Tang } 78271570a2aSLawrence Tang 78371570a2aSLawrence Tang //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 78471570a2aSLawrence Tang void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out) 78571570a2aSLawrence Tang { 78671570a2aSLawrence Tang //Get uniform register array. 78771570a2aSLawrence Tang EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 78871570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 789e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 790e407b4c8SLawrence Tang sizeof(UINT32), 791e407b4c8SLawrence Tang ARM_AARCH32_SECURE_REGISTER_NAMES); 79271570a2aSLawrence Tang 79371570a2aSLawrence Tang //Flush to stream. 79471570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 79571570a2aSLawrence Tang fflush(out); 79671570a2aSLawrence Tang } 79771570a2aSLawrence Tang 79871570a2aSLawrence Tang //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 79971570a2aSLawrence Tang void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out) 80071570a2aSLawrence Tang { 80171570a2aSLawrence Tang //Get uniform register array. 80271570a2aSLawrence Tang EFI_ARM_V8_AARCH64_GPR reg_array; 80371570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 804e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 805e407b4c8SLawrence Tang ARM_AARCH64_GPR_NAMES); 80671570a2aSLawrence Tang 80771570a2aSLawrence Tang //Flush to stream. 80871570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 80971570a2aSLawrence Tang fflush(out); 81071570a2aSLawrence Tang } 81171570a2aSLawrence Tang 81271570a2aSLawrence Tang //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 81371570a2aSLawrence Tang void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out) 81471570a2aSLawrence Tang { 81571570a2aSLawrence Tang //Get uniform register array. 81671570a2aSLawrence Tang EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 81771570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 818e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 819e407b4c8SLawrence Tang sizeof(UINT64), 820e407b4c8SLawrence Tang ARM_AARCH64_EL1_REGISTER_NAMES); 82171570a2aSLawrence Tang 82271570a2aSLawrence Tang //Flush to stream. 82371570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 82471570a2aSLawrence Tang fflush(out); 82571570a2aSLawrence Tang } 82671570a2aSLawrence Tang 82771570a2aSLawrence Tang //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 82871570a2aSLawrence Tang void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out) 82971570a2aSLawrence Tang { 83071570a2aSLawrence Tang //Get uniform register array. 83171570a2aSLawrence Tang EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 83271570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 833e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 834e407b4c8SLawrence Tang sizeof(UINT64), 835e407b4c8SLawrence Tang ARM_AARCH64_EL2_REGISTER_NAMES); 83671570a2aSLawrence Tang 83771570a2aSLawrence Tang //Flush to stream. 83871570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 83971570a2aSLawrence Tang fflush(out); 84071570a2aSLawrence Tang } 84171570a2aSLawrence Tang 84271570a2aSLawrence Tang //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 84371570a2aSLawrence Tang void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out) 84471570a2aSLawrence Tang { 84571570a2aSLawrence Tang //Get uniform register array. 84671570a2aSLawrence Tang EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 84771570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 848e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 849e407b4c8SLawrence Tang sizeof(UINT64), 850e407b4c8SLawrence Tang ARM_AARCH64_EL3_REGISTER_NAMES); 85171570a2aSLawrence Tang 85271570a2aSLawrence Tang //Flush to stream. 85371570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 85471570a2aSLawrence Tang fflush(out); 85571570a2aSLawrence Tang } 85671570a2aSLawrence Tang 85771570a2aSLawrence Tang //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 85871570a2aSLawrence Tang void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out) 85971570a2aSLawrence Tang { 86071570a2aSLawrence Tang EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 86171570a2aSLawrence Tang 86271570a2aSLawrence Tang //MRS encoding information. 863e407b4c8SLawrence Tang json_object *mrs_encoding = 864e407b4c8SLawrence Tang json_object_object_get(registers, "mrsEncoding"); 865e407b4c8SLawrence Tang reg_array.MrsOp2 = json_object_get_uint64( 866e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "op2")); 867e407b4c8SLawrence Tang reg_array.MrsCrm = json_object_get_uint64( 868e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "crm")); 869e407b4c8SLawrence Tang reg_array.MrsCrn = json_object_get_uint64( 870e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "crn")); 871e407b4c8SLawrence Tang reg_array.MrsOp1 = json_object_get_uint64( 872e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "op1")); 873e407b4c8SLawrence Tang reg_array.MrsO0 = json_object_get_uint64( 874e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "o0")); 87571570a2aSLawrence Tang 87671570a2aSLawrence Tang //Actual register value. 877e407b4c8SLawrence Tang reg_array.Value = json_object_get_uint64( 878e407b4c8SLawrence Tang json_object_object_get(registers, "value")); 87971570a2aSLawrence Tang 88071570a2aSLawrence Tang //Flush to stream. 88171570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 88271570a2aSLawrence Tang fflush(out); 88371570a2aSLawrence Tang } 88471570a2aSLawrence Tang 88571570a2aSLawrence Tang //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 886e407b4c8SLawrence Tang void ir_arm_unknown_register_to_cper(json_object *registers, 887e407b4c8SLawrence Tang EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 888e407b4c8SLawrence Tang FILE *out) 88971570a2aSLawrence Tang { 89071570a2aSLawrence Tang //Get base64 represented data. 89171570a2aSLawrence Tang json_object *encoded = json_object_object_get(registers, "data"); 892e407b4c8SLawrence Tang UINT8 *decoded = b64_decode(json_object_get_string(encoded), 893e407b4c8SLawrence Tang json_object_get_string_len(encoded)); 89471570a2aSLawrence Tang 89571570a2aSLawrence Tang //Flush out to stream. 89671570a2aSLawrence Tang fwrite(&decoded, header->RegisterArraySize, 1, out); 89771570a2aSLawrence Tang fflush(out); 89871570a2aSLawrence Tang free(decoded); 8997cd13908SLawrence Tang }