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> 95202bbb4SLawrence Tang #include <json.h> 10*f8fc7052SJohn Chung #include "libbase64.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); 43*f8fc7052SJohn Chung void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out); 443d0e4f24SLawrence Tang 452800cd8eSLawrence Tang //Converts the given processor-generic CPER section into JSON IR. 46*f8fc7052SJohn Chung json_object *cper_section_arm_to_ir(void *section) 472800cd8eSLawrence Tang { 487f21db6cSLawrence Tang EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section; 492800cd8eSLawrence Tang json_object *section_ir = json_object_new_object(); 502800cd8eSLawrence Tang 512800cd8eSLawrence Tang //Validation bits. 52e407b4c8SLawrence Tang json_object *validation = bitfield_to_ir( 53e407b4c8SLawrence Tang record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES); 542800cd8eSLawrence Tang json_object_object_add(section_ir, "validationBits", validation); 552800cd8eSLawrence Tang 562800cd8eSLawrence Tang //Number of error info and context info structures, and length. 57e407b4c8SLawrence Tang json_object_object_add(section_ir, "errorInfoNum", 58e407b4c8SLawrence Tang json_object_new_int(record->ErrInfoNum)); 59e407b4c8SLawrence Tang json_object_object_add(section_ir, "contextInfoNum", 60e407b4c8SLawrence Tang json_object_new_int(record->ContextInfoNum)); 61e407b4c8SLawrence Tang json_object_object_add(section_ir, "sectionLength", 62e407b4c8SLawrence Tang json_object_new_uint64(record->SectionLength)); 632800cd8eSLawrence Tang 642800cd8eSLawrence Tang //Error affinity. 652800cd8eSLawrence Tang json_object *error_affinity = json_object_new_object(); 66e407b4c8SLawrence Tang json_object_object_add(error_affinity, "value", 67e407b4c8SLawrence Tang json_object_new_int(record->ErrorAffinityLevel)); 68e407b4c8SLawrence Tang json_object_object_add( 69e407b4c8SLawrence Tang error_affinity, "type", 70e407b4c8SLawrence Tang json_object_new_string(record->ErrorAffinityLevel < 4 ? 71e407b4c8SLawrence Tang "Vendor Defined" : 72e407b4c8SLawrence Tang "Reserved")); 732800cd8eSLawrence Tang json_object_object_add(section_ir, "errorAffinity", error_affinity); 742800cd8eSLawrence Tang 752800cd8eSLawrence Tang //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1). 76e407b4c8SLawrence Tang json_object_object_add(section_ir, "mpidrEl1", 77e407b4c8SLawrence Tang json_object_new_uint64(record->MPIDR_EL1)); 78e407b4c8SLawrence Tang json_object_object_add(section_ir, "midrEl1", 79e407b4c8SLawrence Tang json_object_new_uint64(record->MIDR_EL1)); 802800cd8eSLawrence Tang 812800cd8eSLawrence Tang //Whether the processor is running, and the state of it if so. 82e407b4c8SLawrence Tang json_object_object_add(section_ir, "running", 83e407b4c8SLawrence Tang json_object_new_boolean(record->RunningState & 84*f8fc7052SJohn Chung 0x1)); 85e407b4c8SLawrence Tang if (!(record->RunningState >> 31)) { 863d0e4f24SLawrence Tang //Bit 32 of running state is on, so PSCI state information is included. 872721739aSLawrence Tang //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format 882721739aSLawrence Tang //or the newer Extended StateID format. 89e407b4c8SLawrence Tang json_object_object_add( 90e407b4c8SLawrence Tang section_ir, "psciState", 91e407b4c8SLawrence Tang json_object_new_uint64(record->PsciState)); 922800cd8eSLawrence Tang } 932800cd8eSLawrence Tang 943d0e4f24SLawrence Tang //Processor error structures. 953d0e4f24SLawrence Tang json_object *error_info_array = json_object_new_array(); 96e407b4c8SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error = 97e407b4c8SLawrence Tang (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1); 98e407b4c8SLawrence Tang for (int i = 0; i < record->ErrInfoNum; i++) { 99e407b4c8SLawrence Tang json_object_array_add(error_info_array, 100e407b4c8SLawrence Tang cper_arm_error_info_to_ir(cur_error)); 1017f21db6cSLawrence Tang cur_error++; 1023d0e4f24SLawrence Tang } 1037f21db6cSLawrence Tang json_object_object_add(section_ir, "errorInfo", error_info_array); 1047f21db6cSLawrence Tang 1057f21db6cSLawrence Tang //Processor context structures. 1067f21db6cSLawrence Tang //The current position is moved within the processing, as it is a dynamic size structure. 107*f8fc7052SJohn Chung uint8_t *cur_pos = (uint8_t *)cur_error; 1083636d3c2SLawrence Tang json_object *context_info_array = json_object_new_array(); 109e407b4c8SLawrence Tang for (int i = 0; i < record->ContextInfoNum; i++) { 110e407b4c8SLawrence Tang EFI_ARM_CONTEXT_INFORMATION_HEADER *header = 111e407b4c8SLawrence Tang (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos; 112e407b4c8SLawrence Tang json_object *processor_context = 113*f8fc7052SJohn Chung cper_arm_processor_context_to_ir(header, 114*f8fc7052SJohn Chung (void **)&cur_pos); 1153636d3c2SLawrence Tang json_object_array_add(context_info_array, processor_context); 1163636d3c2SLawrence Tang } 1173636d3c2SLawrence Tang json_object_object_add(section_ir, "contextInfo", context_info_array); 1187f21db6cSLawrence Tang 1197f21db6cSLawrence Tang //Is there any vendor-specific information following? 120*f8fc7052SJohn Chung if (cur_pos < (uint8_t *)section + record->SectionLength) { 121d7e8ca34SLawrence Tang json_object *vendor_specific = json_object_new_object(); 122*f8fc7052SJohn Chung size_t input_size = 123*f8fc7052SJohn Chung (uint8_t *)section + record->SectionLength - cur_pos; 124*f8fc7052SJohn Chung char *encoded = malloc(2 * input_size); 125*f8fc7052SJohn Chung size_t encoded_len = 0; 126*f8fc7052SJohn Chung if (!encoded) { 127*f8fc7052SJohn Chung printf("Failed to allocate encode output buffer. \n"); 128*f8fc7052SJohn Chung } else { 129*f8fc7052SJohn Chung base64_encode((const char *)cur_pos, input_size, 130*f8fc7052SJohn Chung encoded, &encoded_len, 0); 131e407b4c8SLawrence Tang json_object_object_add(vendor_specific, "data", 132*f8fc7052SJohn Chung json_object_new_string_len( 133*f8fc7052SJohn Chung encoded, encoded_len)); 134d7e8ca34SLawrence Tang free(encoded); 135d7e8ca34SLawrence Tang 136e407b4c8SLawrence Tang json_object_object_add(section_ir, "vendorSpecificInfo", 137e407b4c8SLawrence Tang vendor_specific); 1387f21db6cSLawrence Tang } 139*f8fc7052SJohn Chung } 1407f21db6cSLawrence Tang 1412800cd8eSLawrence Tang return section_ir; 1422800cd8eSLawrence Tang } 1433d0e4f24SLawrence Tang 1443d0e4f24SLawrence Tang //Converts a single ARM Process Error Information structure into JSON IR. 145e407b4c8SLawrence Tang json_object * 146e407b4c8SLawrence Tang cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 1473d0e4f24SLawrence Tang { 1483d0e4f24SLawrence Tang json_object *error_info_ir = json_object_new_object(); 1493d0e4f24SLawrence Tang 1503d0e4f24SLawrence Tang //Version, length. 151e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "version", 152e407b4c8SLawrence Tang json_object_new_int(error_info->Version)); 153e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "length", 154e407b4c8SLawrence Tang json_object_new_int(error_info->Length)); 1553d0e4f24SLawrence Tang 1563d0e4f24SLawrence Tang //Validation bitfield. 157e407b4c8SLawrence Tang json_object *validation = 158e407b4c8SLawrence Tang bitfield_to_ir(error_info->ValidationBits, 5, 159e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 1603d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "validationBits", validation); 1613d0e4f24SLawrence Tang 1623d0e4f24SLawrence Tang //The type of error information in this log. 163e407b4c8SLawrence Tang json_object *error_type = integer_to_readable_pair( 164e407b4c8SLawrence Tang error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS, 165e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)"); 1663d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "errorType", error_type); 1673d0e4f24SLawrence Tang 1683d0e4f24SLawrence Tang //Multiple error count. 16922a467ceSLawrence Tang json_object *multiple_error = json_object_new_object(); 170e407b4c8SLawrence Tang json_object_object_add(multiple_error, "value", 171e407b4c8SLawrence Tang json_object_new_int(error_info->MultipleError)); 172e407b4c8SLawrence Tang json_object_object_add( 173e407b4c8SLawrence Tang multiple_error, "type", 174e407b4c8SLawrence Tang json_object_new_string(error_info->MultipleError < 1 ? 175e407b4c8SLawrence Tang "Single Error" : 176e407b4c8SLawrence Tang "Multiple Errors")); 1773d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "multipleError", multiple_error); 1783d0e4f24SLawrence Tang 1793d0e4f24SLawrence Tang //Flags. 180e407b4c8SLawrence Tang json_object *flags = bitfield_to_ir(error_info->Flags, 4, 181e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 1823d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "flags", flags); 1833d0e4f24SLawrence Tang 1843d0e4f24SLawrence Tang //Error information, split by type. 1853d0e4f24SLawrence Tang json_object *error_subinfo = NULL; 186e407b4c8SLawrence Tang switch (error_info->Type) { 18771570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache 18871570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB 189e407b4c8SLawrence Tang error_subinfo = cper_arm_cache_tlb_error_to_ir( 190e407b4c8SLawrence Tang (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info 191e407b4c8SLawrence Tang ->ErrorInformation, 192e407b4c8SLawrence Tang error_info); 1933d0e4f24SLawrence Tang break; 19471570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus 195e407b4c8SLawrence Tang error_subinfo = cper_arm_bus_error_to_ir( 196e407b4c8SLawrence Tang (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info 197e407b4c8SLawrence Tang ->ErrorInformation); 1983d0e4f24SLawrence Tang break; 19971570a2aSLawrence Tang 20071570a2aSLawrence Tang default: 20171570a2aSLawrence Tang //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object. 20271570a2aSLawrence Tang error_subinfo = json_object_new_object(); 203e407b4c8SLawrence Tang json_object_object_add( 204e407b4c8SLawrence Tang error_subinfo, "data", 205e407b4c8SLawrence Tang json_object_new_uint64( 206e407b4c8SLawrence Tang *((UINT64 *)&error_info->ErrorInformation))); 20771570a2aSLawrence Tang break; 2083d0e4f24SLawrence Tang } 209e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "errorInformation", 210e407b4c8SLawrence Tang error_subinfo); 2113d0e4f24SLawrence Tang 212b98ec66cSLawrence Tang //Virtual fault address, physical fault address. 213e407b4c8SLawrence Tang json_object_object_add( 214e407b4c8SLawrence Tang error_info_ir, "virtualFaultAddress", 215e407b4c8SLawrence Tang json_object_new_uint64(error_info->VirtualFaultAddress)); 216e407b4c8SLawrence Tang json_object_object_add( 217e407b4c8SLawrence Tang error_info_ir, "physicalFaultAddress", 218e407b4c8SLawrence Tang json_object_new_uint64(error_info->PhysicalFaultAddress)); 219b98ec66cSLawrence Tang 2203d0e4f24SLawrence Tang return error_info_ir; 2213d0e4f24SLawrence Tang } 2223d0e4f24SLawrence Tang 2237f21db6cSLawrence Tang //Converts a single ARM cache/TLB error information structure into JSON IR format. 224e407b4c8SLawrence Tang json_object * 225e407b4c8SLawrence Tang cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error, 226e407b4c8SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY *error_info) 2273d0e4f24SLawrence Tang { 2287f21db6cSLawrence Tang json_object *cache_tlb_error_ir = json_object_new_object(); 2293d0e4f24SLawrence Tang 2307f21db6cSLawrence Tang //Validation bitfield. 231e407b4c8SLawrence Tang json_object *validation = 232e407b4c8SLawrence Tang bitfield_to_ir(cache_tlb_error->ValidationBits, 7, 233e407b4c8SLawrence Tang ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 234e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "validationBits", 235e407b4c8SLawrence Tang validation); 2367f21db6cSLawrence Tang 2377f21db6cSLawrence Tang //Transaction type. 238e407b4c8SLawrence Tang json_object *transaction_type = integer_to_readable_pair( 239e407b4c8SLawrence Tang cache_tlb_error->TransactionType, 3, 2407f21db6cSLawrence Tang ARM_ERROR_TRANSACTION_TYPES_KEYS, 241e407b4c8SLawrence Tang ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 242e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "transactionType", 243e407b4c8SLawrence Tang transaction_type); 2447f21db6cSLawrence Tang 2457f21db6cSLawrence Tang //Operation. 2467f21db6cSLawrence Tang json_object *operation; 247e407b4c8SLawrence Tang if (error_info->Type == 0) { 2487f21db6cSLawrence Tang //Cache operation. 249e407b4c8SLawrence Tang operation = integer_to_readable_pair( 250e407b4c8SLawrence Tang cache_tlb_error->Operation, 11, 2517f21db6cSLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 2527f21db6cSLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 2537f21db6cSLawrence Tang "Unknown (Reserved)"); 254e407b4c8SLawrence Tang } else { 2557f21db6cSLawrence Tang //TLB operation. 256e407b4c8SLawrence Tang operation = integer_to_readable_pair( 257e407b4c8SLawrence Tang cache_tlb_error->Operation, 9, 2587f21db6cSLawrence Tang ARM_TLB_OPERATION_TYPES_KEYS, 259e407b4c8SLawrence Tang ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 2607f21db6cSLawrence Tang } 2617f21db6cSLawrence Tang json_object_object_add(cache_tlb_error_ir, "operation", operation); 2627f21db6cSLawrence Tang 2637f21db6cSLawrence Tang //Miscellaneous remaining fields. 264e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "level", 265e407b4c8SLawrence Tang json_object_new_int(cache_tlb_error->Level)); 266e407b4c8SLawrence Tang json_object_object_add( 267e407b4c8SLawrence Tang cache_tlb_error_ir, "processorContextCorrupt", 268e407b4c8SLawrence Tang json_object_new_boolean( 269e407b4c8SLawrence Tang cache_tlb_error->ProcessorContextCorrupt)); 270e407b4c8SLawrence Tang json_object_object_add( 271e407b4c8SLawrence Tang cache_tlb_error_ir, "corrected", 272e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->Corrected)); 273e407b4c8SLawrence Tang json_object_object_add( 274e407b4c8SLawrence Tang cache_tlb_error_ir, "precisePC", 275e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->PrecisePC)); 276e407b4c8SLawrence Tang json_object_object_add( 277e407b4c8SLawrence Tang cache_tlb_error_ir, "restartablePC", 278e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->RestartablePC)); 2797f21db6cSLawrence Tang return cache_tlb_error_ir; 2803d0e4f24SLawrence Tang } 2813d0e4f24SLawrence Tang 2823d0e4f24SLawrence Tang //Converts a single ARM bus error information structure into JSON IR format. 2837f21db6cSLawrence Tang json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error) 2843d0e4f24SLawrence Tang { 2857f21db6cSLawrence Tang json_object *bus_error_ir = json_object_new_object(); 2867f21db6cSLawrence Tang 2877f21db6cSLawrence Tang //Validation bits. 288e407b4c8SLawrence Tang json_object *validation = 289e407b4c8SLawrence Tang bitfield_to_ir(bus_error->ValidationBits, 12, 290e407b4c8SLawrence Tang ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 2917f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "validationBits", validation); 2927f21db6cSLawrence Tang 2937f21db6cSLawrence Tang //Transaction type. 294e407b4c8SLawrence Tang json_object *transaction_type = integer_to_readable_pair( 295e407b4c8SLawrence Tang bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS, 296e407b4c8SLawrence Tang ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)"); 297e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "transactionType", 298e407b4c8SLawrence Tang transaction_type); 2997f21db6cSLawrence Tang 3007f21db6cSLawrence Tang //Operation. 301e407b4c8SLawrence Tang json_object *operation = integer_to_readable_pair( 302e407b4c8SLawrence Tang bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 303e407b4c8SLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)"); 3047f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "operation", operation); 3057f21db6cSLawrence Tang 3067f21db6cSLawrence Tang //Affinity level of bus error, + miscellaneous fields. 307e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "level", 308e407b4c8SLawrence Tang json_object_new_int(bus_error->Level)); 309e407b4c8SLawrence Tang json_object_object_add( 310e407b4c8SLawrence Tang bus_error_ir, "processorContextCorrupt", 311e407b4c8SLawrence Tang json_object_new_boolean(bus_error->ProcessorContextCorrupt)); 312e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "corrected", 313e407b4c8SLawrence Tang json_object_new_boolean(bus_error->Corrected)); 314e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "precisePC", 315e407b4c8SLawrence Tang json_object_new_boolean(bus_error->PrecisePC)); 316e407b4c8SLawrence Tang json_object_object_add( 317e407b4c8SLawrence Tang bus_error_ir, "restartablePC", 318e407b4c8SLawrence Tang json_object_new_boolean(bus_error->RestartablePC)); 319e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "timedOut", 320e407b4c8SLawrence Tang json_object_new_boolean(bus_error->TimeOut)); 3217f21db6cSLawrence Tang 3227f21db6cSLawrence Tang //Participation type. 323e407b4c8SLawrence Tang json_object *participation_type = integer_to_readable_pair( 324e407b4c8SLawrence Tang bus_error->ParticipationType, 4, 3257f21db6cSLawrence Tang ARM_BUS_PARTICIPATION_TYPES_KEYS, 326e407b4c8SLawrence Tang ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown"); 327e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "participationType", 328e407b4c8SLawrence Tang participation_type); 3297f21db6cSLawrence Tang 3307f21db6cSLawrence Tang //Address space. 331e407b4c8SLawrence Tang json_object *address_space = integer_to_readable_pair( 332e407b4c8SLawrence Tang bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS, 333e407b4c8SLawrence Tang ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown"); 3347f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "addressSpace", address_space); 3357f21db6cSLawrence Tang 3367f21db6cSLawrence Tang //Memory access attributes. 3377f21db6cSLawrence Tang //todo: find the specification of these in the ARM ARM 338e407b4c8SLawrence Tang json_object_object_add( 339e407b4c8SLawrence Tang bus_error_ir, "memoryAttributes", 340e407b4c8SLawrence Tang json_object_new_int(bus_error->MemoryAddressAttributes)); 3417f21db6cSLawrence Tang 3427f21db6cSLawrence Tang //Access Mode 3437f21db6cSLawrence Tang json_object *access_mode = json_object_new_object(); 344e407b4c8SLawrence Tang json_object_object_add(access_mode, "value", 345e407b4c8SLawrence Tang json_object_new_int(bus_error->AccessMode)); 346e407b4c8SLawrence Tang json_object_object_add( 347e407b4c8SLawrence Tang access_mode, "name", 348e407b4c8SLawrence Tang json_object_new_string(bus_error->AccessMode == 0 ? "Secure" : 349e407b4c8SLawrence Tang "Normal")); 3507f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "accessMode", access_mode); 3517f21db6cSLawrence Tang 3527f21db6cSLawrence Tang return bus_error_ir; 3537f21db6cSLawrence Tang } 3547f21db6cSLawrence Tang 3557f21db6cSLawrence Tang //Converts a single ARM processor context block into JSON IR. 356e407b4c8SLawrence Tang json_object * 357e407b4c8SLawrence Tang cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header, 358e407b4c8SLawrence Tang void **cur_pos) 3597f21db6cSLawrence Tang { 3607f21db6cSLawrence Tang json_object *context_ir = json_object_new_object(); 3617f21db6cSLawrence Tang 36271570a2aSLawrence Tang //Version. 363e407b4c8SLawrence Tang json_object_object_add(context_ir, "version", 364e407b4c8SLawrence Tang json_object_new_int(header->Version)); 36571570a2aSLawrence Tang 3667f21db6cSLawrence Tang //Add the context type. 367e407b4c8SLawrence Tang json_object *context_type = integer_to_readable_pair( 368e407b4c8SLawrence Tang header->RegisterContextType, 9, 3697f21db6cSLawrence Tang ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS, 3707f21db6cSLawrence Tang ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES, 3717f21db6cSLawrence Tang "Unknown (Reserved)"); 3727f21db6cSLawrence Tang json_object_object_add(context_ir, "registerContextType", context_type); 3737f21db6cSLawrence Tang 3747f21db6cSLawrence Tang //Register array size (bytes). 375e407b4c8SLawrence Tang json_object_object_add( 376e407b4c8SLawrence Tang context_ir, "registerArraySize", 377e407b4c8SLawrence Tang json_object_new_uint64(header->RegisterArraySize)); 3787f21db6cSLawrence Tang 3797f21db6cSLawrence Tang //The register array itself. 3807f21db6cSLawrence Tang *cur_pos = (void *)(header + 1); 3817f21db6cSLawrence Tang json_object *register_array = NULL; 382e407b4c8SLawrence Tang switch (header->RegisterContextType) { 3837f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 384e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 385e407b4c8SLawrence Tang (UINT32 *)cur_pos, 386e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 387e407b4c8SLawrence Tang ARM_AARCH32_GPR_NAMES); 3887f21db6cSLawrence Tang break; 3897f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 390e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 391e407b4c8SLawrence Tang (UINT32 *)cur_pos, 392e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 393e407b4c8SLawrence Tang sizeof(UINT32), 394e407b4c8SLawrence Tang ARM_AARCH32_EL1_REGISTER_NAMES); 3957f21db6cSLawrence Tang break; 3967f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 397e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 398e407b4c8SLawrence Tang (UINT32 *)cur_pos, 399e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 400e407b4c8SLawrence Tang sizeof(UINT32), 401e407b4c8SLawrence Tang ARM_AARCH32_EL2_REGISTER_NAMES); 4027f21db6cSLawrence Tang break; 4037f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 404e407b4c8SLawrence Tang register_array = uniform_struct_to_ir( 405e407b4c8SLawrence Tang (UINT32 *)cur_pos, 406e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 407e407b4c8SLawrence Tang sizeof(UINT32), 408e407b4c8SLawrence Tang ARM_AARCH32_SECURE_REGISTER_NAMES); 4097f21db6cSLawrence Tang break; 4107f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 411e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 412e407b4c8SLawrence Tang (UINT64 *)cur_pos, 413e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 414e407b4c8SLawrence Tang ARM_AARCH64_GPR_NAMES); 4157f21db6cSLawrence Tang break; 4167f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 417e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 418e407b4c8SLawrence Tang (UINT64 *)cur_pos, 419e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 420e407b4c8SLawrence Tang sizeof(UINT64), 421e407b4c8SLawrence Tang ARM_AARCH64_EL1_REGISTER_NAMES); 4227f21db6cSLawrence Tang break; 4237f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 424e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 425e407b4c8SLawrence Tang (UINT64 *)cur_pos, 426e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 427e407b4c8SLawrence Tang sizeof(UINT64), 428e407b4c8SLawrence Tang ARM_AARCH64_EL2_REGISTER_NAMES); 4297f21db6cSLawrence Tang break; 4307f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 431e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir( 432e407b4c8SLawrence Tang (UINT64 *)cur_pos, 433e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 434e407b4c8SLawrence Tang sizeof(UINT64), 435e407b4c8SLawrence Tang ARM_AARCH64_EL3_REGISTER_NAMES); 4367f21db6cSLawrence Tang break; 4377f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_MISC: 438e407b4c8SLawrence Tang register_array = cper_arm_misc_register_array_to_ir( 439e407b4c8SLawrence Tang (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos); 4407f21db6cSLawrence Tang break; 4417f21db6cSLawrence Tang default: 442d7e8ca34SLawrence Tang //Unknown register array type, add as base64 data instead. 4437f21db6cSLawrence Tang register_array = json_object_new_object(); 444*f8fc7052SJohn Chung char *encoded = malloc(2 * header->RegisterArraySize); 445*f8fc7052SJohn Chung size_t encoded_len = 0; 446*f8fc7052SJohn Chung if (!encoded) { 447*f8fc7052SJohn Chung printf("Failed to allocate encode output buffer. \n"); 448*f8fc7052SJohn Chung } else { 449*f8fc7052SJohn Chung base64_encode((const char *)cur_pos, 450*f8fc7052SJohn Chung header->RegisterArraySize, encoded, 451*f8fc7052SJohn Chung &encoded_len, 0); 452e407b4c8SLawrence Tang json_object_object_add(register_array, "data", 453*f8fc7052SJohn Chung json_object_new_string_len( 454*f8fc7052SJohn Chung encoded, encoded_len)); 455d7e8ca34SLawrence Tang free(encoded); 456*f8fc7052SJohn Chung } 4577f21db6cSLawrence Tang break; 4587f21db6cSLawrence Tang } 4593636d3c2SLawrence Tang json_object_object_add(context_ir, "registerArray", register_array); 4607f21db6cSLawrence Tang 4617f21db6cSLawrence Tang //Set the current position to after the processor context structure. 4627f21db6cSLawrence Tang *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize; 4637f21db6cSLawrence Tang 4647f21db6cSLawrence Tang return context_ir; 4657f21db6cSLawrence Tang } 4667f21db6cSLawrence Tang 4677f21db6cSLawrence Tang //Converts a single CPER ARM miscellaneous register array to JSON IR format. 468e407b4c8SLawrence Tang json_object * 469e407b4c8SLawrence Tang cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register) 4707f21db6cSLawrence Tang { 4717f21db6cSLawrence Tang json_object *register_array = json_object_new_object(); 4727f21db6cSLawrence Tang json_object *mrs_encoding = json_object_new_object(); 473e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "op2", 474e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsOp2)); 475e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "crm", 476e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsCrm)); 477e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "crn", 478e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsCrn)); 479e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "op1", 480e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsOp1)); 481e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "o0", 482e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsO0)); 4837f21db6cSLawrence Tang json_object_object_add(register_array, "mrsEncoding", mrs_encoding); 484e407b4c8SLawrence Tang json_object_object_add(register_array, "value", 485e407b4c8SLawrence Tang json_object_new_uint64(misc_register->Value)); 4867f21db6cSLawrence Tang 4877f21db6cSLawrence Tang return register_array; 4883d0e4f24SLawrence Tang } 4897cd13908SLawrence Tang 4907cd13908SLawrence Tang //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream. 4917cd13908SLawrence Tang void ir_section_arm_to_cper(json_object *section, FILE *out) 4927cd13908SLawrence Tang { 493e407b4c8SLawrence Tang EFI_ARM_ERROR_RECORD *section_cper = 494e407b4c8SLawrence Tang (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD)); 4957cd13908SLawrence Tang 4967cd13908SLawrence Tang //Validation bits. 497e407b4c8SLawrence Tang section_cper->ValidFields = ir_to_bitfield( 498e407b4c8SLawrence Tang json_object_object_get(section, "validationBits"), 4, 499e407b4c8SLawrence Tang ARM_ERROR_VALID_BITFIELD_NAMES); 5007cd13908SLawrence Tang 5017cd13908SLawrence Tang //Count of error/context info structures. 502e407b4c8SLawrence Tang section_cper->ErrInfoNum = json_object_get_int( 503e407b4c8SLawrence Tang json_object_object_get(section, "errorInfoNum")); 504e407b4c8SLawrence Tang section_cper->ContextInfoNum = json_object_get_int( 505e407b4c8SLawrence Tang json_object_object_get(section, "contextInfoNum")); 5067cd13908SLawrence Tang 5077cd13908SLawrence Tang //Miscellaneous raw value fields. 508e407b4c8SLawrence Tang section_cper->SectionLength = json_object_get_uint64( 509e407b4c8SLawrence Tang json_object_object_get(section, "sectionLength")); 510e407b4c8SLawrence Tang section_cper->ErrorAffinityLevel = readable_pair_to_integer( 511e407b4c8SLawrence Tang json_object_object_get(section, "errorAffinity")); 512e407b4c8SLawrence Tang section_cper->MPIDR_EL1 = json_object_get_uint64( 513e407b4c8SLawrence Tang json_object_object_get(section, "mpidrEl1")); 514e407b4c8SLawrence Tang section_cper->MIDR_EL1 = json_object_get_uint64( 515e407b4c8SLawrence Tang json_object_object_get(section, "midrEl1")); 516e407b4c8SLawrence Tang section_cper->RunningState = json_object_get_boolean( 517e407b4c8SLawrence Tang json_object_object_get(section, "running")); 5187cd13908SLawrence Tang 5197cd13908SLawrence Tang //Optional PSCI state. 5207cd13908SLawrence Tang json_object *psci_state = json_object_object_get(section, "psciState"); 521*f8fc7052SJohn Chung if (psci_state != NULL) { 5227cd13908SLawrence Tang section_cper->PsciState = json_object_get_uint64(psci_state); 523*f8fc7052SJohn Chung } 5247cd13908SLawrence Tang 5257cd13908SLawrence Tang //Flush header to stream. 5267cd13908SLawrence Tang fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out); 5277cd13908SLawrence Tang fflush(out); 5287cd13908SLawrence Tang 5297cd13908SLawrence Tang //Error info structure array. 5307cd13908SLawrence Tang json_object *error_info = json_object_object_get(section, "errorInfo"); 531*f8fc7052SJohn Chung for (int i = 0; i < section_cper->ErrInfoNum; i++) { 532e407b4c8SLawrence Tang ir_arm_error_info_to_cper( 533e407b4c8SLawrence Tang json_object_array_get_idx(error_info, i), out); 534*f8fc7052SJohn Chung } 5357cd13908SLawrence Tang 5367cd13908SLawrence Tang //Context info structure array. 537e407b4c8SLawrence Tang json_object *context_info = 538e407b4c8SLawrence Tang json_object_object_get(section, "contextInfo"); 539*f8fc7052SJohn Chung for (int i = 0; i < section_cper->ContextInfoNum; i++) { 540e407b4c8SLawrence Tang ir_arm_context_info_to_cper( 541e407b4c8SLawrence Tang json_object_array_get_idx(context_info, i), out); 542*f8fc7052SJohn Chung } 5437cd13908SLawrence Tang 5447cd13908SLawrence Tang //Vendor specific error info. 545e407b4c8SLawrence Tang json_object *vendor_specific_info = 546e407b4c8SLawrence Tang json_object_object_get(section, "vendorSpecificInfo"); 547e407b4c8SLawrence Tang if (vendor_specific_info != NULL) { 548e407b4c8SLawrence Tang json_object *vendor_info_string = 549e407b4c8SLawrence Tang json_object_object_get(vendor_specific_info, "data"); 550e407b4c8SLawrence Tang int vendor_specific_len = 551e407b4c8SLawrence Tang json_object_get_string_len(vendor_info_string); 552*f8fc7052SJohn Chung char *decoded = malloc(vendor_specific_len); 553*f8fc7052SJohn Chung size_t decoded_len = 0; 554*f8fc7052SJohn Chung if (!decoded) { 555*f8fc7052SJohn Chung printf("Failed to allocate decode output buffer. \n"); 556*f8fc7052SJohn Chung } else { 557*f8fc7052SJohn Chung base64_decode( 558*f8fc7052SJohn Chung json_object_get_string(vendor_info_string), 559*f8fc7052SJohn Chung vendor_specific_len, decoded, &decoded_len, 0); 56001e3a44dSLawrence Tang 56101e3a44dSLawrence Tang //Write out to file. 562*f8fc7052SJohn Chung fwrite(decoded, decoded_len, 1, out); 5637cd13908SLawrence Tang fflush(out); 5647cd13908SLawrence Tang free(decoded); 5657cd13908SLawrence Tang } 566*f8fc7052SJohn Chung } 5677cd13908SLawrence Tang 5687cd13908SLawrence Tang //Free remaining resources. 5697cd13908SLawrence Tang free(section_cper); 5707cd13908SLawrence Tang } 5717cd13908SLawrence Tang 5727cd13908SLawrence Tang //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 5737cd13908SLawrence Tang void ir_arm_error_info_to_cper(json_object *error_info, FILE *out) 5747cd13908SLawrence Tang { 5757cd13908SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 5767cd13908SLawrence Tang 5777cd13908SLawrence Tang //Version, length. 578e407b4c8SLawrence Tang error_info_cper.Version = json_object_get_int( 579e407b4c8SLawrence Tang json_object_object_get(error_info, "version")); 580e407b4c8SLawrence Tang error_info_cper.Length = json_object_get_int( 581e407b4c8SLawrence Tang json_object_object_get(error_info, "length")); 5827cd13908SLawrence Tang 5837cd13908SLawrence Tang //Validation bits. 584e407b4c8SLawrence Tang error_info_cper.ValidationBits = ir_to_bitfield( 585e407b4c8SLawrence Tang json_object_object_get(error_info, "validationBits"), 5, 586e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 5877cd13908SLawrence Tang 5887cd13908SLawrence Tang //Type, multiple error. 589e407b4c8SLawrence Tang error_info_cper.Type = (UINT8)readable_pair_to_integer( 590e407b4c8SLawrence Tang json_object_object_get(error_info, "type")); 591e407b4c8SLawrence Tang error_info_cper.MultipleError = (UINT16)readable_pair_to_integer( 592e407b4c8SLawrence Tang json_object_object_get(error_info, "multipleError")); 5937cd13908SLawrence Tang 5947cd13908SLawrence Tang //Flags object. 595e407b4c8SLawrence Tang error_info_cper.Flags = (UINT8)ir_to_bitfield( 596e407b4c8SLawrence Tang json_object_object_get(error_info, "flags"), 4, 597e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 5987cd13908SLawrence Tang 5997cd13908SLawrence Tang //Error information. 600e407b4c8SLawrence Tang json_object *error_info_information = 601e407b4c8SLawrence Tang json_object_object_get(error_info, "errorInformation"); 602e407b4c8SLawrence Tang switch (error_info_cper.Type) { 60371570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_CACHE: 60471570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_TLB: 605e407b4c8SLawrence Tang ir_arm_error_cache_tlb_info_to_cper( 606e407b4c8SLawrence Tang error_info_information, 607e407b4c8SLawrence Tang &error_info_cper.ErrorInformation.CacheError); 60871570a2aSLawrence Tang break; 60971570a2aSLawrence Tang 61071570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_BUS: 611e407b4c8SLawrence Tang ir_arm_error_bus_info_to_cper( 612e407b4c8SLawrence Tang error_info_information, 613e407b4c8SLawrence Tang &error_info_cper.ErrorInformation.BusError); 61471570a2aSLawrence Tang break; 61571570a2aSLawrence Tang 61671570a2aSLawrence Tang default: 61771570a2aSLawrence Tang //Unknown error information type. 61871570a2aSLawrence Tang *((UINT64 *)&error_info_cper.ErrorInformation) = 619e407b4c8SLawrence Tang json_object_get_uint64(json_object_object_get( 620e407b4c8SLawrence Tang error_info_information, "data")); 62171570a2aSLawrence Tang break; 62271570a2aSLawrence Tang } 6237cd13908SLawrence Tang 6247cd13908SLawrence Tang //Virtual/physical fault address. 625e407b4c8SLawrence Tang error_info_cper.VirtualFaultAddress = json_object_get_uint64( 626e407b4c8SLawrence Tang json_object_object_get(error_info, "virtualFaultAddress")); 627e407b4c8SLawrence Tang error_info_cper.PhysicalFaultAddress = json_object_get_uint64( 628e407b4c8SLawrence Tang json_object_object_get(error_info, "physicalFaultAddress")); 6297cd13908SLawrence Tang 6307cd13908SLawrence Tang //Write out to stream. 631e407b4c8SLawrence Tang fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, 632e407b4c8SLawrence Tang out); 6337cd13908SLawrence Tang fflush(out); 6347cd13908SLawrence Tang } 6357cd13908SLawrence Tang 63671570a2aSLawrence Tang //Converts a single ARM cache/TLB error information structure into a CPER structure. 637e407b4c8SLawrence Tang void ir_arm_error_cache_tlb_info_to_cper( 638e407b4c8SLawrence Tang json_object *error_information, 639e407b4c8SLawrence Tang EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper) 64071570a2aSLawrence Tang { 64171570a2aSLawrence Tang //Validation bits. 642e407b4c8SLawrence Tang error_info_cper->ValidationBits = ir_to_bitfield( 643e407b4c8SLawrence Tang json_object_object_get(error_information, "validationBits"), 7, 644e407b4c8SLawrence Tang ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 64571570a2aSLawrence Tang 64671570a2aSLawrence Tang //Miscellaneous value fields. 647e407b4c8SLawrence Tang error_info_cper->TransactionType = readable_pair_to_integer( 648e407b4c8SLawrence Tang json_object_object_get(error_information, "transactionType")); 649e407b4c8SLawrence Tang error_info_cper->Operation = readable_pair_to_integer( 650e407b4c8SLawrence Tang json_object_object_get(error_information, "operation")); 651e407b4c8SLawrence Tang error_info_cper->Level = json_object_get_uint64( 652e407b4c8SLawrence Tang json_object_object_get(error_information, "level")); 653e407b4c8SLawrence Tang error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 654e407b4c8SLawrence Tang json_object_object_get(error_information, 655e407b4c8SLawrence Tang "processorContextCorrupt")); 656e407b4c8SLawrence Tang error_info_cper->Corrected = json_object_get_boolean( 657e407b4c8SLawrence Tang json_object_object_get(error_information, "corrected")); 658e407b4c8SLawrence Tang error_info_cper->PrecisePC = json_object_get_boolean( 659e407b4c8SLawrence Tang json_object_object_get(error_information, "precisePC")); 660e407b4c8SLawrence Tang error_info_cper->RestartablePC = json_object_get_boolean( 661e407b4c8SLawrence Tang json_object_object_get(error_information, "restartablePC")); 66271570a2aSLawrence Tang error_info_cper->Reserved = 0; 66371570a2aSLawrence Tang } 66471570a2aSLawrence Tang 66571570a2aSLawrence Tang //Converts a single ARM bus error information structure into a CPER structure. 666e407b4c8SLawrence Tang void ir_arm_error_bus_info_to_cper(json_object *error_information, 667e407b4c8SLawrence Tang EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper) 66871570a2aSLawrence Tang { 66971570a2aSLawrence Tang //Validation bits. 670e407b4c8SLawrence Tang error_info_cper->ValidationBits = ir_to_bitfield( 671e407b4c8SLawrence Tang json_object_object_get(error_information, "validationBits"), 7, 672e407b4c8SLawrence Tang ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 67371570a2aSLawrence Tang 67471570a2aSLawrence Tang //Miscellaneous value fields. 675e407b4c8SLawrence Tang error_info_cper->TransactionType = readable_pair_to_integer( 676e407b4c8SLawrence Tang json_object_object_get(error_information, "transactionType")); 677e407b4c8SLawrence Tang error_info_cper->Operation = readable_pair_to_integer( 678e407b4c8SLawrence Tang json_object_object_get(error_information, "operation")); 679e407b4c8SLawrence Tang error_info_cper->Level = json_object_get_uint64( 680e407b4c8SLawrence Tang json_object_object_get(error_information, "level")); 681e407b4c8SLawrence Tang error_info_cper->ProcessorContextCorrupt = json_object_get_boolean( 682e407b4c8SLawrence Tang json_object_object_get(error_information, 683e407b4c8SLawrence Tang "processorContextCorrupt")); 684e407b4c8SLawrence Tang error_info_cper->Corrected = json_object_get_boolean( 685e407b4c8SLawrence Tang json_object_object_get(error_information, "corrected")); 686e407b4c8SLawrence Tang error_info_cper->PrecisePC = json_object_get_boolean( 687e407b4c8SLawrence Tang json_object_object_get(error_information, "precisePC")); 688e407b4c8SLawrence Tang error_info_cper->RestartablePC = json_object_get_boolean( 689e407b4c8SLawrence Tang json_object_object_get(error_information, "restartablePC")); 690e407b4c8SLawrence Tang error_info_cper->ParticipationType = readable_pair_to_integer( 691e407b4c8SLawrence Tang json_object_object_get(error_information, "participationType")); 692e407b4c8SLawrence Tang error_info_cper->AddressSpace = readable_pair_to_integer( 693e407b4c8SLawrence Tang json_object_object_get(error_information, "addressSpace")); 694e407b4c8SLawrence Tang error_info_cper->AccessMode = readable_pair_to_integer( 695e407b4c8SLawrence Tang json_object_object_get(error_information, "accessMode")); 696e407b4c8SLawrence Tang error_info_cper->MemoryAddressAttributes = json_object_get_uint64( 697e407b4c8SLawrence Tang json_object_object_get(error_information, "memoryAttributes")); 69871570a2aSLawrence Tang error_info_cper->Reserved = 0; 69971570a2aSLawrence Tang } 70071570a2aSLawrence Tang 7017cd13908SLawrence Tang //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 7027cd13908SLawrence Tang void ir_arm_context_info_to_cper(json_object *context_info, FILE *out) 7037cd13908SLawrence Tang { 70471570a2aSLawrence Tang EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 7057cd13908SLawrence Tang 70671570a2aSLawrence Tang //Version, array size, context type. 707e407b4c8SLawrence Tang info_header.Version = json_object_get_int( 708e407b4c8SLawrence Tang json_object_object_get(context_info, "version")); 709e407b4c8SLawrence Tang info_header.RegisterArraySize = json_object_get_int( 710e407b4c8SLawrence Tang json_object_object_get(context_info, "registerArraySize")); 711e407b4c8SLawrence Tang info_header.RegisterContextType = readable_pair_to_integer( 712e407b4c8SLawrence Tang json_object_object_get(context_info, "registerContextType")); 71371570a2aSLawrence Tang 71471570a2aSLawrence Tang //Flush to stream, write the register array itself. 715e407b4c8SLawrence Tang fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, 716e407b4c8SLawrence Tang out); 71771570a2aSLawrence Tang fflush(out); 71871570a2aSLawrence Tang 719e407b4c8SLawrence Tang json_object *register_array = 720e407b4c8SLawrence Tang json_object_object_get(context_info, "registerArray"); 721e407b4c8SLawrence Tang switch (info_header.RegisterContextType) { 72271570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 72371570a2aSLawrence Tang ir_arm_aarch32_gpr_to_cper(register_array, out); 72471570a2aSLawrence Tang break; 72571570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 72671570a2aSLawrence Tang ir_arm_aarch32_el1_to_cper(register_array, out); 72771570a2aSLawrence Tang break; 72871570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 72971570a2aSLawrence Tang ir_arm_aarch32_el2_to_cper(register_array, out); 73071570a2aSLawrence Tang break; 73171570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 73271570a2aSLawrence Tang ir_arm_aarch32_secure_to_cper(register_array, out); 73371570a2aSLawrence Tang break; 73471570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 73571570a2aSLawrence Tang ir_arm_aarch64_gpr_to_cper(register_array, out); 73671570a2aSLawrence Tang break; 73771570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 73871570a2aSLawrence Tang ir_arm_aarch64_el1_to_cper(register_array, out); 73971570a2aSLawrence Tang break; 74071570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 74171570a2aSLawrence Tang ir_arm_aarch64_el2_to_cper(register_array, out); 74271570a2aSLawrence Tang break; 74371570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 74471570a2aSLawrence Tang ir_arm_aarch64_el3_to_cper(register_array, out); 74571570a2aSLawrence Tang break; 74671570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_MISC: 74771570a2aSLawrence Tang ir_arm_misc_registers_to_cper(register_array, out); 74871570a2aSLawrence Tang break; 74971570a2aSLawrence Tang default: 75071570a2aSLawrence Tang //Unknown register structure. 751*f8fc7052SJohn Chung ir_arm_unknown_register_to_cper(register_array, out); 75271570a2aSLawrence Tang break; 75371570a2aSLawrence Tang } 75471570a2aSLawrence Tang } 75571570a2aSLawrence Tang 75671570a2aSLawrence Tang //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 75771570a2aSLawrence Tang void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out) 75871570a2aSLawrence Tang { 75971570a2aSLawrence Tang //Get uniform register array. 76071570a2aSLawrence Tang EFI_ARM_V8_AARCH32_GPR reg_array; 76171570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 762e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), 763e407b4c8SLawrence Tang ARM_AARCH32_GPR_NAMES); 76471570a2aSLawrence Tang 76571570a2aSLawrence Tang //Flush to stream. 76671570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 76771570a2aSLawrence Tang fflush(out); 76871570a2aSLawrence Tang } 76971570a2aSLawrence Tang 77071570a2aSLawrence Tang //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 77171570a2aSLawrence Tang void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out) 77271570a2aSLawrence Tang { 77371570a2aSLawrence Tang //Get uniform register array. 77471570a2aSLawrence Tang EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 77571570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 776e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / 777e407b4c8SLawrence Tang sizeof(UINT32), 778e407b4c8SLawrence Tang ARM_AARCH32_EL1_REGISTER_NAMES); 77971570a2aSLawrence Tang 78071570a2aSLawrence Tang //Flush to stream. 78171570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 78271570a2aSLawrence Tang fflush(out); 78371570a2aSLawrence Tang } 78471570a2aSLawrence Tang 78571570a2aSLawrence Tang //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 78671570a2aSLawrence Tang void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out) 78771570a2aSLawrence Tang { 78871570a2aSLawrence Tang //Get uniform register array. 78971570a2aSLawrence Tang EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 79071570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 791e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / 792e407b4c8SLawrence Tang sizeof(UINT32), 793e407b4c8SLawrence Tang ARM_AARCH32_EL2_REGISTER_NAMES); 79471570a2aSLawrence Tang 79571570a2aSLawrence Tang //Flush to stream. 79671570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 79771570a2aSLawrence Tang fflush(out); 79871570a2aSLawrence Tang } 79971570a2aSLawrence Tang 80071570a2aSLawrence Tang //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 80171570a2aSLawrence Tang void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out) 80271570a2aSLawrence Tang { 80371570a2aSLawrence Tang //Get uniform register array. 80471570a2aSLawrence Tang EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 80571570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array, 806e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / 807e407b4c8SLawrence Tang sizeof(UINT32), 808e407b4c8SLawrence Tang ARM_AARCH32_SECURE_REGISTER_NAMES); 80971570a2aSLawrence Tang 81071570a2aSLawrence Tang //Flush to stream. 81171570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 81271570a2aSLawrence Tang fflush(out); 81371570a2aSLawrence Tang } 81471570a2aSLawrence Tang 81571570a2aSLawrence Tang //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 81671570a2aSLawrence Tang void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out) 81771570a2aSLawrence Tang { 81871570a2aSLawrence Tang //Get uniform register array. 81971570a2aSLawrence Tang EFI_ARM_V8_AARCH64_GPR reg_array; 82071570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 821e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), 822e407b4c8SLawrence Tang ARM_AARCH64_GPR_NAMES); 82371570a2aSLawrence Tang 82471570a2aSLawrence Tang //Flush to stream. 82571570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 82671570a2aSLawrence Tang fflush(out); 82771570a2aSLawrence Tang } 82871570a2aSLawrence Tang 82971570a2aSLawrence Tang //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 83071570a2aSLawrence Tang void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out) 83171570a2aSLawrence Tang { 83271570a2aSLawrence Tang //Get uniform register array. 83371570a2aSLawrence Tang EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 83471570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 835e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / 836e407b4c8SLawrence Tang sizeof(UINT64), 837e407b4c8SLawrence Tang ARM_AARCH64_EL1_REGISTER_NAMES); 83871570a2aSLawrence Tang 83971570a2aSLawrence Tang //Flush to stream. 84071570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 84171570a2aSLawrence Tang fflush(out); 84271570a2aSLawrence Tang } 84371570a2aSLawrence Tang 84471570a2aSLawrence Tang //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 84571570a2aSLawrence Tang void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out) 84671570a2aSLawrence Tang { 84771570a2aSLawrence Tang //Get uniform register array. 84871570a2aSLawrence Tang EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 84971570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 850e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / 851e407b4c8SLawrence Tang sizeof(UINT64), 852e407b4c8SLawrence Tang ARM_AARCH64_EL2_REGISTER_NAMES); 85371570a2aSLawrence Tang 85471570a2aSLawrence Tang //Flush to stream. 85571570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 85671570a2aSLawrence Tang fflush(out); 85771570a2aSLawrence Tang } 85871570a2aSLawrence Tang 85971570a2aSLawrence Tang //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 86071570a2aSLawrence Tang void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out) 86171570a2aSLawrence Tang { 86271570a2aSLawrence Tang //Get uniform register array. 86371570a2aSLawrence Tang EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 86471570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array, 865e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / 866e407b4c8SLawrence Tang sizeof(UINT64), 867e407b4c8SLawrence Tang ARM_AARCH64_EL3_REGISTER_NAMES); 86871570a2aSLawrence Tang 86971570a2aSLawrence Tang //Flush to stream. 87071570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 87171570a2aSLawrence Tang fflush(out); 87271570a2aSLawrence Tang } 87371570a2aSLawrence Tang 87471570a2aSLawrence Tang //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 87571570a2aSLawrence Tang void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out) 87671570a2aSLawrence Tang { 87771570a2aSLawrence Tang EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 87871570a2aSLawrence Tang 87971570a2aSLawrence Tang //MRS encoding information. 880e407b4c8SLawrence Tang json_object *mrs_encoding = 881e407b4c8SLawrence Tang json_object_object_get(registers, "mrsEncoding"); 882e407b4c8SLawrence Tang reg_array.MrsOp2 = json_object_get_uint64( 883e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "op2")); 884e407b4c8SLawrence Tang reg_array.MrsCrm = json_object_get_uint64( 885e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "crm")); 886e407b4c8SLawrence Tang reg_array.MrsCrn = json_object_get_uint64( 887e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "crn")); 888e407b4c8SLawrence Tang reg_array.MrsOp1 = json_object_get_uint64( 889e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "op1")); 890e407b4c8SLawrence Tang reg_array.MrsO0 = json_object_get_uint64( 891e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "o0")); 89271570a2aSLawrence Tang 89371570a2aSLawrence Tang //Actual register value. 894e407b4c8SLawrence Tang reg_array.Value = json_object_get_uint64( 895e407b4c8SLawrence Tang json_object_object_get(registers, "value")); 89671570a2aSLawrence Tang 89771570a2aSLawrence Tang //Flush to stream. 89871570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out); 89971570a2aSLawrence Tang fflush(out); 90071570a2aSLawrence Tang } 90171570a2aSLawrence Tang 90271570a2aSLawrence Tang //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 903*f8fc7052SJohn Chung void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out) 90471570a2aSLawrence Tang { 90571570a2aSLawrence Tang //Get base64 represented data. 90671570a2aSLawrence Tang json_object *encoded = json_object_object_get(registers, "data"); 907*f8fc7052SJohn Chung char *decoded = malloc(json_object_get_string_len(encoded)); 908*f8fc7052SJohn Chung size_t decoded_len = 0; 909*f8fc7052SJohn Chung if (!decoded) { 910*f8fc7052SJohn Chung printf("Failed to allocate decode output buffer. \n"); 911*f8fc7052SJohn Chung } else { 912*f8fc7052SJohn Chung base64_decode(json_object_get_string(encoded), 913*f8fc7052SJohn Chung json_object_get_string_len(encoded), decoded, 914*f8fc7052SJohn Chung &decoded_len, 0); 91571570a2aSLawrence Tang 91671570a2aSLawrence Tang //Flush out to stream. 917*f8fc7052SJohn Chung fwrite(&decoded, decoded_len, 1, out); 91871570a2aSLawrence Tang fflush(out); 91971570a2aSLawrence Tang free(decoded); 9207cd13908SLawrence Tang } 921*f8fc7052SJohn Chung } 922