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*a7d2cdddSEd Tanous #include "base64.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);
43f8fc7052SJohn 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.
cper_section_arm_to_ir(void * section)46f8fc7052SJohn 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 &
84f8fc7052SJohn 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.
107f8fc7052SJohn 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 =
113f8fc7052SJohn Chung cper_arm_processor_context_to_ir(header,
114f8fc7052SJohn 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?
120f8fc7052SJohn Chung if (cur_pos < (uint8_t *)section + record->SectionLength) {
121d7e8ca34SLawrence Tang json_object *vendor_specific = json_object_new_object();
122f8fc7052SJohn Chung size_t input_size =
123f8fc7052SJohn Chung (uint8_t *)section + record->SectionLength - cur_pos;
124*a7d2cdddSEd Tanous int32_t encoded_len = 0;
125*a7d2cdddSEd Tanous char *encoded =
126*a7d2cdddSEd Tanous base64_encode(cur_pos, input_size, &encoded_len);
127*a7d2cdddSEd Tanous if (encoded == NULL) {
128*a7d2cdddSEd Tanous return NULL;
129*a7d2cdddSEd Tanous }
130e407b4c8SLawrence Tang json_object_object_add(vendor_specific, "data",
131*a7d2cdddSEd Tanous json_object_new_string_len(encoded,
132*a7d2cdddSEd Tanous encoded_len));
133d7e8ca34SLawrence Tang free(encoded);
134d7e8ca34SLawrence Tang
135e407b4c8SLawrence Tang json_object_object_add(section_ir, "vendorSpecificInfo",
136e407b4c8SLawrence Tang vendor_specific);
1377f21db6cSLawrence Tang }
1387f21db6cSLawrence Tang
1392800cd8eSLawrence Tang return section_ir;
1402800cd8eSLawrence Tang }
1413d0e4f24SLawrence Tang
1423d0e4f24SLawrence Tang //Converts a single ARM Process Error Information structure into JSON IR.
143e407b4c8SLawrence Tang json_object *
cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)144e407b4c8SLawrence Tang cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
1453d0e4f24SLawrence Tang {
1463d0e4f24SLawrence Tang json_object *error_info_ir = json_object_new_object();
1473d0e4f24SLawrence Tang
1483d0e4f24SLawrence Tang //Version, length.
149e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "version",
150e407b4c8SLawrence Tang json_object_new_int(error_info->Version));
151e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "length",
152e407b4c8SLawrence Tang json_object_new_int(error_info->Length));
1533d0e4f24SLawrence Tang
1543d0e4f24SLawrence Tang //Validation bitfield.
155e407b4c8SLawrence Tang json_object *validation =
156e407b4c8SLawrence Tang bitfield_to_ir(error_info->ValidationBits, 5,
157e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
1583d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "validationBits", validation);
1593d0e4f24SLawrence Tang
1603d0e4f24SLawrence Tang //The type of error information in this log.
161e407b4c8SLawrence Tang json_object *error_type = integer_to_readable_pair(
162e407b4c8SLawrence Tang error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
163e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
1643d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "errorType", error_type);
1653d0e4f24SLawrence Tang
1663d0e4f24SLawrence Tang //Multiple error count.
16722a467ceSLawrence Tang json_object *multiple_error = json_object_new_object();
168e407b4c8SLawrence Tang json_object_object_add(multiple_error, "value",
169e407b4c8SLawrence Tang json_object_new_int(error_info->MultipleError));
170e407b4c8SLawrence Tang json_object_object_add(
171e407b4c8SLawrence Tang multiple_error, "type",
172e407b4c8SLawrence Tang json_object_new_string(error_info->MultipleError < 1 ?
173e407b4c8SLawrence Tang "Single Error" :
174e407b4c8SLawrence Tang "Multiple Errors"));
1753d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "multipleError", multiple_error);
1763d0e4f24SLawrence Tang
1773d0e4f24SLawrence Tang //Flags.
178e407b4c8SLawrence Tang json_object *flags = bitfield_to_ir(error_info->Flags, 4,
179e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
1803d0e4f24SLawrence Tang json_object_object_add(error_info_ir, "flags", flags);
1813d0e4f24SLawrence Tang
1823d0e4f24SLawrence Tang //Error information, split by type.
1833d0e4f24SLawrence Tang json_object *error_subinfo = NULL;
184e407b4c8SLawrence Tang switch (error_info->Type) {
18571570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
18671570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
187e407b4c8SLawrence Tang error_subinfo = cper_arm_cache_tlb_error_to_ir(
188e407b4c8SLawrence Tang (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
189e407b4c8SLawrence Tang ->ErrorInformation,
190e407b4c8SLawrence Tang error_info);
1913d0e4f24SLawrence Tang break;
19271570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
193e407b4c8SLawrence Tang error_subinfo = cper_arm_bus_error_to_ir(
194e407b4c8SLawrence Tang (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
195e407b4c8SLawrence Tang ->ErrorInformation);
1963d0e4f24SLawrence Tang break;
19771570a2aSLawrence Tang
19871570a2aSLawrence Tang default:
19971570a2aSLawrence Tang //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object.
20071570a2aSLawrence Tang error_subinfo = json_object_new_object();
201e407b4c8SLawrence Tang json_object_object_add(
202e407b4c8SLawrence Tang error_subinfo, "data",
203e407b4c8SLawrence Tang json_object_new_uint64(
2040b9c9402SJohn Chung error_info->ErrorInformation.Value));
20571570a2aSLawrence Tang break;
2063d0e4f24SLawrence Tang }
207e407b4c8SLawrence Tang json_object_object_add(error_info_ir, "errorInformation",
208e407b4c8SLawrence Tang error_subinfo);
2093d0e4f24SLawrence Tang
210b98ec66cSLawrence Tang //Virtual fault address, physical fault address.
211e407b4c8SLawrence Tang json_object_object_add(
212e407b4c8SLawrence Tang error_info_ir, "virtualFaultAddress",
213e407b4c8SLawrence Tang json_object_new_uint64(error_info->VirtualFaultAddress));
214e407b4c8SLawrence Tang json_object_object_add(
215e407b4c8SLawrence Tang error_info_ir, "physicalFaultAddress",
216e407b4c8SLawrence Tang json_object_new_uint64(error_info->PhysicalFaultAddress));
217b98ec66cSLawrence Tang
2183d0e4f24SLawrence Tang return error_info_ir;
2193d0e4f24SLawrence Tang }
2203d0e4f24SLawrence Tang
2217f21db6cSLawrence Tang //Converts a single ARM cache/TLB error information structure into JSON IR format.
222e407b4c8SLawrence Tang json_object *
cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE * cache_tlb_error,EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)223e407b4c8SLawrence Tang cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
224e407b4c8SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
2253d0e4f24SLawrence Tang {
2267f21db6cSLawrence Tang json_object *cache_tlb_error_ir = json_object_new_object();
2273d0e4f24SLawrence Tang
2287f21db6cSLawrence Tang //Validation bitfield.
229e407b4c8SLawrence Tang json_object *validation =
230e407b4c8SLawrence Tang bitfield_to_ir(cache_tlb_error->ValidationBits, 7,
231e407b4c8SLawrence Tang ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
232e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "validationBits",
233e407b4c8SLawrence Tang validation);
2347f21db6cSLawrence Tang
2357f21db6cSLawrence Tang //Transaction type.
236e407b4c8SLawrence Tang json_object *transaction_type = integer_to_readable_pair(
237e407b4c8SLawrence Tang cache_tlb_error->TransactionType, 3,
2387f21db6cSLawrence Tang ARM_ERROR_TRANSACTION_TYPES_KEYS,
239e407b4c8SLawrence Tang ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
240e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "transactionType",
241e407b4c8SLawrence Tang transaction_type);
2427f21db6cSLawrence Tang
2437f21db6cSLawrence Tang //Operation.
2447f21db6cSLawrence Tang json_object *operation;
245e407b4c8SLawrence Tang if (error_info->Type == 0) {
2467f21db6cSLawrence Tang //Cache operation.
247e407b4c8SLawrence Tang operation = integer_to_readable_pair(
248e407b4c8SLawrence Tang cache_tlb_error->Operation, 11,
2497f21db6cSLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
2507f21db6cSLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
2517f21db6cSLawrence Tang "Unknown (Reserved)");
252e407b4c8SLawrence Tang } else {
2537f21db6cSLawrence Tang //TLB operation.
254e407b4c8SLawrence Tang operation = integer_to_readable_pair(
255e407b4c8SLawrence Tang cache_tlb_error->Operation, 9,
2567f21db6cSLawrence Tang ARM_TLB_OPERATION_TYPES_KEYS,
257e407b4c8SLawrence Tang ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
2587f21db6cSLawrence Tang }
2597f21db6cSLawrence Tang json_object_object_add(cache_tlb_error_ir, "operation", operation);
2607f21db6cSLawrence Tang
2617f21db6cSLawrence Tang //Miscellaneous remaining fields.
262e407b4c8SLawrence Tang json_object_object_add(cache_tlb_error_ir, "level",
263e407b4c8SLawrence Tang json_object_new_int(cache_tlb_error->Level));
264e407b4c8SLawrence Tang json_object_object_add(
265e407b4c8SLawrence Tang cache_tlb_error_ir, "processorContextCorrupt",
266e407b4c8SLawrence Tang json_object_new_boolean(
267e407b4c8SLawrence Tang cache_tlb_error->ProcessorContextCorrupt));
268e407b4c8SLawrence Tang json_object_object_add(
269e407b4c8SLawrence Tang cache_tlb_error_ir, "corrected",
270e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->Corrected));
271e407b4c8SLawrence Tang json_object_object_add(
272e407b4c8SLawrence Tang cache_tlb_error_ir, "precisePC",
273e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->PrecisePC));
274e407b4c8SLawrence Tang json_object_object_add(
275e407b4c8SLawrence Tang cache_tlb_error_ir, "restartablePC",
276e407b4c8SLawrence Tang json_object_new_boolean(cache_tlb_error->RestartablePC));
2777f21db6cSLawrence Tang return cache_tlb_error_ir;
2783d0e4f24SLawrence Tang }
2793d0e4f24SLawrence Tang
2803d0e4f24SLawrence Tang //Converts a single ARM bus error information structure into JSON IR format.
cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE * bus_error)2817f21db6cSLawrence Tang json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
2823d0e4f24SLawrence Tang {
2837f21db6cSLawrence Tang json_object *bus_error_ir = json_object_new_object();
2847f21db6cSLawrence Tang
2857f21db6cSLawrence Tang //Validation bits.
286e407b4c8SLawrence Tang json_object *validation =
287e407b4c8SLawrence Tang bitfield_to_ir(bus_error->ValidationBits, 12,
288e407b4c8SLawrence Tang ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
2897f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "validationBits", validation);
2907f21db6cSLawrence Tang
2917f21db6cSLawrence Tang //Transaction type.
292e407b4c8SLawrence Tang json_object *transaction_type = integer_to_readable_pair(
293e407b4c8SLawrence Tang bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS,
294e407b4c8SLawrence Tang ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
295e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "transactionType",
296e407b4c8SLawrence Tang transaction_type);
2977f21db6cSLawrence Tang
2987f21db6cSLawrence Tang //Operation.
299e407b4c8SLawrence Tang json_object *operation = integer_to_readable_pair(
300e407b4c8SLawrence Tang bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
301e407b4c8SLawrence Tang ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
3027f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "operation", operation);
3037f21db6cSLawrence Tang
3047f21db6cSLawrence Tang //Affinity level of bus error, + miscellaneous fields.
305e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "level",
306e407b4c8SLawrence Tang json_object_new_int(bus_error->Level));
307e407b4c8SLawrence Tang json_object_object_add(
308e407b4c8SLawrence Tang bus_error_ir, "processorContextCorrupt",
309e407b4c8SLawrence Tang json_object_new_boolean(bus_error->ProcessorContextCorrupt));
310e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "corrected",
311e407b4c8SLawrence Tang json_object_new_boolean(bus_error->Corrected));
312e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "precisePC",
313e407b4c8SLawrence Tang json_object_new_boolean(bus_error->PrecisePC));
314e407b4c8SLawrence Tang json_object_object_add(
315e407b4c8SLawrence Tang bus_error_ir, "restartablePC",
316e407b4c8SLawrence Tang json_object_new_boolean(bus_error->RestartablePC));
317e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "timedOut",
318e407b4c8SLawrence Tang json_object_new_boolean(bus_error->TimeOut));
3197f21db6cSLawrence Tang
3207f21db6cSLawrence Tang //Participation type.
321e407b4c8SLawrence Tang json_object *participation_type = integer_to_readable_pair(
322e407b4c8SLawrence Tang bus_error->ParticipationType, 4,
3237f21db6cSLawrence Tang ARM_BUS_PARTICIPATION_TYPES_KEYS,
324e407b4c8SLawrence Tang ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
325e407b4c8SLawrence Tang json_object_object_add(bus_error_ir, "participationType",
326e407b4c8SLawrence Tang participation_type);
3277f21db6cSLawrence Tang
3287f21db6cSLawrence Tang //Address space.
329e407b4c8SLawrence Tang json_object *address_space = integer_to_readable_pair(
330e407b4c8SLawrence Tang bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
331e407b4c8SLawrence Tang ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
3327f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "addressSpace", address_space);
3337f21db6cSLawrence Tang
3347f21db6cSLawrence Tang //Memory access attributes.
3357f21db6cSLawrence Tang //todo: find the specification of these in the ARM ARM
336e407b4c8SLawrence Tang json_object_object_add(
337e407b4c8SLawrence Tang bus_error_ir, "memoryAttributes",
338e407b4c8SLawrence Tang json_object_new_int(bus_error->MemoryAddressAttributes));
3397f21db6cSLawrence Tang
3407f21db6cSLawrence Tang //Access Mode
3417f21db6cSLawrence Tang json_object *access_mode = json_object_new_object();
342e407b4c8SLawrence Tang json_object_object_add(access_mode, "value",
343e407b4c8SLawrence Tang json_object_new_int(bus_error->AccessMode));
344e407b4c8SLawrence Tang json_object_object_add(
345e407b4c8SLawrence Tang access_mode, "name",
346e407b4c8SLawrence Tang json_object_new_string(bus_error->AccessMode == 0 ? "Secure" :
347e407b4c8SLawrence Tang "Normal"));
3487f21db6cSLawrence Tang json_object_object_add(bus_error_ir, "accessMode", access_mode);
3497f21db6cSLawrence Tang
3507f21db6cSLawrence Tang return bus_error_ir;
3517f21db6cSLawrence Tang }
3527f21db6cSLawrence Tang
3537f21db6cSLawrence Tang //Converts a single ARM processor context block into JSON IR.
354e407b4c8SLawrence Tang json_object *
cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER * header,void ** cur_pos)355e407b4c8SLawrence Tang cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
356e407b4c8SLawrence Tang void **cur_pos)
3577f21db6cSLawrence Tang {
3587f21db6cSLawrence Tang json_object *context_ir = json_object_new_object();
3597f21db6cSLawrence Tang
36071570a2aSLawrence Tang //Version.
361e407b4c8SLawrence Tang json_object_object_add(context_ir, "version",
362e407b4c8SLawrence Tang json_object_new_int(header->Version));
36371570a2aSLawrence Tang
3647f21db6cSLawrence Tang //Add the context type.
365e407b4c8SLawrence Tang json_object *context_type = integer_to_readable_pair(
366e407b4c8SLawrence Tang header->RegisterContextType, 9,
3677f21db6cSLawrence Tang ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
3687f21db6cSLawrence Tang ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
3697f21db6cSLawrence Tang "Unknown (Reserved)");
3707f21db6cSLawrence Tang json_object_object_add(context_ir, "registerContextType", context_type);
3717f21db6cSLawrence Tang
3727f21db6cSLawrence Tang //Register array size (bytes).
373e407b4c8SLawrence Tang json_object_object_add(
374e407b4c8SLawrence Tang context_ir, "registerArraySize",
375e407b4c8SLawrence Tang json_object_new_uint64(header->RegisterArraySize));
3767f21db6cSLawrence Tang
3777f21db6cSLawrence Tang //The register array itself.
3787f21db6cSLawrence Tang *cur_pos = (void *)(header + 1);
3797f21db6cSLawrence Tang json_object *register_array = NULL;
380e407b4c8SLawrence Tang switch (header->RegisterContextType) {
3817f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
382e407b4c8SLawrence Tang register_array = uniform_struct_to_ir(
383e407b4c8SLawrence Tang (UINT32 *)cur_pos,
384e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
385e407b4c8SLawrence Tang ARM_AARCH32_GPR_NAMES);
3867f21db6cSLawrence Tang break;
3877f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
388e407b4c8SLawrence Tang register_array = uniform_struct_to_ir(
389e407b4c8SLawrence Tang (UINT32 *)cur_pos,
390e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
391e407b4c8SLawrence Tang sizeof(UINT32),
392e407b4c8SLawrence Tang ARM_AARCH32_EL1_REGISTER_NAMES);
3937f21db6cSLawrence Tang break;
3947f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
395e407b4c8SLawrence Tang register_array = uniform_struct_to_ir(
396e407b4c8SLawrence Tang (UINT32 *)cur_pos,
397e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
398e407b4c8SLawrence Tang sizeof(UINT32),
399e407b4c8SLawrence Tang ARM_AARCH32_EL2_REGISTER_NAMES);
4007f21db6cSLawrence Tang break;
4017f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
402e407b4c8SLawrence Tang register_array = uniform_struct_to_ir(
403e407b4c8SLawrence Tang (UINT32 *)cur_pos,
404e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
405e407b4c8SLawrence Tang sizeof(UINT32),
406e407b4c8SLawrence Tang ARM_AARCH32_SECURE_REGISTER_NAMES);
4077f21db6cSLawrence Tang break;
4087f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
409e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir(
410e407b4c8SLawrence Tang (UINT64 *)cur_pos,
411e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
412e407b4c8SLawrence Tang ARM_AARCH64_GPR_NAMES);
4137f21db6cSLawrence Tang break;
4147f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
415e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir(
416e407b4c8SLawrence Tang (UINT64 *)cur_pos,
417e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
418e407b4c8SLawrence Tang sizeof(UINT64),
419e407b4c8SLawrence Tang ARM_AARCH64_EL1_REGISTER_NAMES);
4207f21db6cSLawrence Tang break;
4217f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
422e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir(
423e407b4c8SLawrence Tang (UINT64 *)cur_pos,
424e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
425e407b4c8SLawrence Tang sizeof(UINT64),
426e407b4c8SLawrence Tang ARM_AARCH64_EL2_REGISTER_NAMES);
4277f21db6cSLawrence Tang break;
4287f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
429e407b4c8SLawrence Tang register_array = uniform_struct64_to_ir(
430e407b4c8SLawrence Tang (UINT64 *)cur_pos,
431e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
432e407b4c8SLawrence Tang sizeof(UINT64),
433e407b4c8SLawrence Tang ARM_AARCH64_EL3_REGISTER_NAMES);
4347f21db6cSLawrence Tang break;
4357f21db6cSLawrence Tang case EFI_ARM_CONTEXT_TYPE_MISC:
436e407b4c8SLawrence Tang register_array = cper_arm_misc_register_array_to_ir(
437e407b4c8SLawrence Tang (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos);
4387f21db6cSLawrence Tang break;
4397f21db6cSLawrence Tang default:
440d7e8ca34SLawrence Tang //Unknown register array type, add as base64 data instead.
4417f21db6cSLawrence Tang register_array = json_object_new_object();
442*a7d2cdddSEd Tanous int32_t encoded_len = 0;
443*a7d2cdddSEd Tanous char *encoded = base64_encode((UINT8 *)cur_pos,
444*a7d2cdddSEd Tanous header->RegisterArraySize,
445*a7d2cdddSEd Tanous &encoded_len);
446*a7d2cdddSEd Tanous if (encoded == NULL) {
447f8fc7052SJohn Chung printf("Failed to allocate encode output buffer. \n");
448*a7d2cdddSEd Tanous return NULL;
449f8fc7052SJohn Chung }
450*a7d2cdddSEd Tanous json_object_object_add(register_array, "data",
451*a7d2cdddSEd Tanous json_object_new_string_len(encoded,
452*a7d2cdddSEd Tanous encoded_len));
453*a7d2cdddSEd Tanous free(encoded);
454*a7d2cdddSEd Tanous
4557f21db6cSLawrence Tang break;
4567f21db6cSLawrence Tang }
4573636d3c2SLawrence Tang json_object_object_add(context_ir, "registerArray", register_array);
4587f21db6cSLawrence Tang
4597f21db6cSLawrence Tang //Set the current position to after the processor context structure.
4607f21db6cSLawrence Tang *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
4617f21db6cSLawrence Tang
4627f21db6cSLawrence Tang return context_ir;
4637f21db6cSLawrence Tang }
4647f21db6cSLawrence Tang
4657f21db6cSLawrence Tang //Converts a single CPER ARM miscellaneous register array to JSON IR format.
466e407b4c8SLawrence Tang json_object *
cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER * misc_register)467e407b4c8SLawrence Tang cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
4687f21db6cSLawrence Tang {
4697f21db6cSLawrence Tang json_object *register_array = json_object_new_object();
4707f21db6cSLawrence Tang json_object *mrs_encoding = json_object_new_object();
471e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "op2",
472e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsOp2));
473e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "crm",
474e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsCrm));
475e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "crn",
476e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsCrn));
477e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "op1",
478e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsOp1));
479e407b4c8SLawrence Tang json_object_object_add(mrs_encoding, "o0",
480e407b4c8SLawrence Tang json_object_new_uint64(misc_register->MrsO0));
4817f21db6cSLawrence Tang json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
482e407b4c8SLawrence Tang json_object_object_add(register_array, "value",
483e407b4c8SLawrence Tang json_object_new_uint64(misc_register->Value));
4847f21db6cSLawrence Tang
4857f21db6cSLawrence Tang return register_array;
4863d0e4f24SLawrence Tang }
4877cd13908SLawrence Tang
4887cd13908SLawrence Tang //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
ir_section_arm_to_cper(json_object * section,FILE * out)4897cd13908SLawrence Tang void ir_section_arm_to_cper(json_object *section, FILE *out)
4907cd13908SLawrence Tang {
491e407b4c8SLawrence Tang EFI_ARM_ERROR_RECORD *section_cper =
492e407b4c8SLawrence Tang (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD));
4937cd13908SLawrence Tang
4947cd13908SLawrence Tang //Validation bits.
495e407b4c8SLawrence Tang section_cper->ValidFields = ir_to_bitfield(
496e407b4c8SLawrence Tang json_object_object_get(section, "validationBits"), 4,
497e407b4c8SLawrence Tang ARM_ERROR_VALID_BITFIELD_NAMES);
4987cd13908SLawrence Tang
4997cd13908SLawrence Tang //Count of error/context info structures.
500e407b4c8SLawrence Tang section_cper->ErrInfoNum = json_object_get_int(
501e407b4c8SLawrence Tang json_object_object_get(section, "errorInfoNum"));
502e407b4c8SLawrence Tang section_cper->ContextInfoNum = json_object_get_int(
503e407b4c8SLawrence Tang json_object_object_get(section, "contextInfoNum"));
5047cd13908SLawrence Tang
5057cd13908SLawrence Tang //Miscellaneous raw value fields.
506e407b4c8SLawrence Tang section_cper->SectionLength = json_object_get_uint64(
507e407b4c8SLawrence Tang json_object_object_get(section, "sectionLength"));
508e407b4c8SLawrence Tang section_cper->ErrorAffinityLevel = readable_pair_to_integer(
509e407b4c8SLawrence Tang json_object_object_get(section, "errorAffinity"));
510e407b4c8SLawrence Tang section_cper->MPIDR_EL1 = json_object_get_uint64(
511e407b4c8SLawrence Tang json_object_object_get(section, "mpidrEl1"));
512e407b4c8SLawrence Tang section_cper->MIDR_EL1 = json_object_get_uint64(
513e407b4c8SLawrence Tang json_object_object_get(section, "midrEl1"));
514e407b4c8SLawrence Tang section_cper->RunningState = json_object_get_boolean(
515e407b4c8SLawrence Tang json_object_object_get(section, "running"));
5167cd13908SLawrence Tang
5177cd13908SLawrence Tang //Optional PSCI state.
5187cd13908SLawrence Tang json_object *psci_state = json_object_object_get(section, "psciState");
519f8fc7052SJohn Chung if (psci_state != NULL) {
5207cd13908SLawrence Tang section_cper->PsciState = json_object_get_uint64(psci_state);
521f8fc7052SJohn Chung }
5227cd13908SLawrence Tang
5237cd13908SLawrence Tang //Flush header to stream.
5247cd13908SLawrence Tang fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out);
5257cd13908SLawrence Tang fflush(out);
5267cd13908SLawrence Tang
5277cd13908SLawrence Tang //Error info structure array.
5287cd13908SLawrence Tang json_object *error_info = json_object_object_get(section, "errorInfo");
529f8fc7052SJohn Chung for (int i = 0; i < section_cper->ErrInfoNum; i++) {
530e407b4c8SLawrence Tang ir_arm_error_info_to_cper(
531e407b4c8SLawrence Tang json_object_array_get_idx(error_info, i), out);
532f8fc7052SJohn Chung }
5337cd13908SLawrence Tang
5347cd13908SLawrence Tang //Context info structure array.
535e407b4c8SLawrence Tang json_object *context_info =
536e407b4c8SLawrence Tang json_object_object_get(section, "contextInfo");
537f8fc7052SJohn Chung for (int i = 0; i < section_cper->ContextInfoNum; i++) {
538e407b4c8SLawrence Tang ir_arm_context_info_to_cper(
539e407b4c8SLawrence Tang json_object_array_get_idx(context_info, i), out);
540f8fc7052SJohn Chung }
5417cd13908SLawrence Tang
5427cd13908SLawrence Tang //Vendor specific error info.
543e407b4c8SLawrence Tang json_object *vendor_specific_info =
544e407b4c8SLawrence Tang json_object_object_get(section, "vendorSpecificInfo");
545e407b4c8SLawrence Tang if (vendor_specific_info != NULL) {
546e407b4c8SLawrence Tang json_object *vendor_info_string =
547e407b4c8SLawrence Tang json_object_object_get(vendor_specific_info, "data");
548e407b4c8SLawrence Tang int vendor_specific_len =
549e407b4c8SLawrence Tang json_object_get_string_len(vendor_info_string);
550*a7d2cdddSEd Tanous
551*a7d2cdddSEd Tanous int32_t decoded_len = 0;
552*a7d2cdddSEd Tanous
553*a7d2cdddSEd Tanous UINT8 *decoded = base64_decode(
554f8fc7052SJohn Chung json_object_get_string(vendor_info_string),
555*a7d2cdddSEd Tanous vendor_specific_len, &decoded_len);
55601e3a44dSLawrence Tang
55701e3a44dSLawrence Tang //Write out to file.
558f8fc7052SJohn Chung fwrite(decoded, decoded_len, 1, out);
5597cd13908SLawrence Tang fflush(out);
5607cd13908SLawrence Tang free(decoded);
5617cd13908SLawrence Tang }
5627cd13908SLawrence Tang
5637cd13908SLawrence Tang //Free remaining resources.
5647cd13908SLawrence Tang free(section_cper);
5657cd13908SLawrence Tang }
5667cd13908SLawrence Tang
5677cd13908SLawrence Tang //Converts a single ARM error information structure into CPER binary, outputting to the given stream.
ir_arm_error_info_to_cper(json_object * error_info,FILE * out)5687cd13908SLawrence Tang void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
5697cd13908SLawrence Tang {
5707cd13908SLawrence Tang EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
5717cd13908SLawrence Tang
5727cd13908SLawrence Tang //Version, length.
573e407b4c8SLawrence Tang error_info_cper.Version = json_object_get_int(
574e407b4c8SLawrence Tang json_object_object_get(error_info, "version"));
575e407b4c8SLawrence Tang error_info_cper.Length = json_object_get_int(
576e407b4c8SLawrence Tang json_object_object_get(error_info, "length"));
5777cd13908SLawrence Tang
5787cd13908SLawrence Tang //Validation bits.
579e407b4c8SLawrence Tang error_info_cper.ValidationBits = ir_to_bitfield(
580e407b4c8SLawrence Tang json_object_object_get(error_info, "validationBits"), 5,
581e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
5827cd13908SLawrence Tang
5837cd13908SLawrence Tang //Type, multiple error.
584e407b4c8SLawrence Tang error_info_cper.Type = (UINT8)readable_pair_to_integer(
585e407b4c8SLawrence Tang json_object_object_get(error_info, "type"));
586e407b4c8SLawrence Tang error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(
587e407b4c8SLawrence Tang json_object_object_get(error_info, "multipleError"));
5887cd13908SLawrence Tang
5897cd13908SLawrence Tang //Flags object.
590e407b4c8SLawrence Tang error_info_cper.Flags = (UINT8)ir_to_bitfield(
591e407b4c8SLawrence Tang json_object_object_get(error_info, "flags"), 4,
592e407b4c8SLawrence Tang ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
5937cd13908SLawrence Tang
5947cd13908SLawrence Tang //Error information.
595e407b4c8SLawrence Tang json_object *error_info_information =
596e407b4c8SLawrence Tang json_object_object_get(error_info, "errorInformation");
597e407b4c8SLawrence Tang switch (error_info_cper.Type) {
59871570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_CACHE:
59971570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_TLB:
600e407b4c8SLawrence Tang ir_arm_error_cache_tlb_info_to_cper(
601e407b4c8SLawrence Tang error_info_information,
602e407b4c8SLawrence Tang &error_info_cper.ErrorInformation.CacheError);
60371570a2aSLawrence Tang break;
60471570a2aSLawrence Tang
60571570a2aSLawrence Tang case ARM_ERROR_INFORMATION_TYPE_BUS:
606e407b4c8SLawrence Tang ir_arm_error_bus_info_to_cper(
607e407b4c8SLawrence Tang error_info_information,
608e407b4c8SLawrence Tang &error_info_cper.ErrorInformation.BusError);
60971570a2aSLawrence Tang break;
61071570a2aSLawrence Tang
61171570a2aSLawrence Tang default:
61271570a2aSLawrence Tang //Unknown error information type.
6130b9c9402SJohn Chung error_info_cper.ErrorInformation.Value = json_object_get_uint64(
6140b9c9402SJohn Chung json_object_object_get(error_info_information, "data"));
61571570a2aSLawrence Tang break;
61671570a2aSLawrence Tang }
6177cd13908SLawrence Tang
6187cd13908SLawrence Tang //Virtual/physical fault address.
619e407b4c8SLawrence Tang error_info_cper.VirtualFaultAddress = json_object_get_uint64(
620e407b4c8SLawrence Tang json_object_object_get(error_info, "virtualFaultAddress"));
621e407b4c8SLawrence Tang error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
622e407b4c8SLawrence Tang json_object_object_get(error_info, "physicalFaultAddress"));
6237cd13908SLawrence Tang
6247cd13908SLawrence Tang //Write out to stream.
625e407b4c8SLawrence Tang fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
626e407b4c8SLawrence Tang out);
6277cd13908SLawrence Tang fflush(out);
6287cd13908SLawrence Tang }
6297cd13908SLawrence Tang
63071570a2aSLawrence Tang //Converts a single ARM cache/TLB error information structure into a CPER structure.
ir_arm_error_cache_tlb_info_to_cper(json_object * error_information,EFI_ARM_CACHE_ERROR_STRUCTURE * error_info_cper)631e407b4c8SLawrence Tang void ir_arm_error_cache_tlb_info_to_cper(
632e407b4c8SLawrence Tang json_object *error_information,
633e407b4c8SLawrence Tang EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
63471570a2aSLawrence Tang {
63571570a2aSLawrence Tang //Validation bits.
636e407b4c8SLawrence Tang error_info_cper->ValidationBits = ir_to_bitfield(
637e407b4c8SLawrence Tang json_object_object_get(error_information, "validationBits"), 7,
638e407b4c8SLawrence Tang ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
63971570a2aSLawrence Tang
64071570a2aSLawrence Tang //Miscellaneous value fields.
641e407b4c8SLawrence Tang error_info_cper->TransactionType = readable_pair_to_integer(
642e407b4c8SLawrence Tang json_object_object_get(error_information, "transactionType"));
643e407b4c8SLawrence Tang error_info_cper->Operation = readable_pair_to_integer(
644e407b4c8SLawrence Tang json_object_object_get(error_information, "operation"));
645e407b4c8SLawrence Tang error_info_cper->Level = json_object_get_uint64(
646e407b4c8SLawrence Tang json_object_object_get(error_information, "level"));
647e407b4c8SLawrence Tang error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
648e407b4c8SLawrence Tang json_object_object_get(error_information,
649e407b4c8SLawrence Tang "processorContextCorrupt"));
650e407b4c8SLawrence Tang error_info_cper->Corrected = json_object_get_boolean(
651e407b4c8SLawrence Tang json_object_object_get(error_information, "corrected"));
652e407b4c8SLawrence Tang error_info_cper->PrecisePC = json_object_get_boolean(
653e407b4c8SLawrence Tang json_object_object_get(error_information, "precisePC"));
654e407b4c8SLawrence Tang error_info_cper->RestartablePC = json_object_get_boolean(
655e407b4c8SLawrence Tang json_object_object_get(error_information, "restartablePC"));
65671570a2aSLawrence Tang error_info_cper->Reserved = 0;
65771570a2aSLawrence Tang }
65871570a2aSLawrence Tang
65971570a2aSLawrence Tang //Converts a single ARM bus error information structure into a CPER structure.
ir_arm_error_bus_info_to_cper(json_object * error_information,EFI_ARM_BUS_ERROR_STRUCTURE * error_info_cper)660e407b4c8SLawrence Tang void ir_arm_error_bus_info_to_cper(json_object *error_information,
661e407b4c8SLawrence Tang EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
66271570a2aSLawrence Tang {
66371570a2aSLawrence Tang //Validation bits.
664e407b4c8SLawrence Tang error_info_cper->ValidationBits = ir_to_bitfield(
665e407b4c8SLawrence Tang json_object_object_get(error_information, "validationBits"), 7,
666e407b4c8SLawrence Tang ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
66771570a2aSLawrence Tang
66871570a2aSLawrence Tang //Miscellaneous value fields.
669e407b4c8SLawrence Tang error_info_cper->TransactionType = readable_pair_to_integer(
670e407b4c8SLawrence Tang json_object_object_get(error_information, "transactionType"));
671e407b4c8SLawrence Tang error_info_cper->Operation = readable_pair_to_integer(
672e407b4c8SLawrence Tang json_object_object_get(error_information, "operation"));
673e407b4c8SLawrence Tang error_info_cper->Level = json_object_get_uint64(
674e407b4c8SLawrence Tang json_object_object_get(error_information, "level"));
675e407b4c8SLawrence Tang error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
676e407b4c8SLawrence Tang json_object_object_get(error_information,
677e407b4c8SLawrence Tang "processorContextCorrupt"));
678e407b4c8SLawrence Tang error_info_cper->Corrected = json_object_get_boolean(
679e407b4c8SLawrence Tang json_object_object_get(error_information, "corrected"));
680e407b4c8SLawrence Tang error_info_cper->PrecisePC = json_object_get_boolean(
681e407b4c8SLawrence Tang json_object_object_get(error_information, "precisePC"));
682e407b4c8SLawrence Tang error_info_cper->RestartablePC = json_object_get_boolean(
683e407b4c8SLawrence Tang json_object_object_get(error_information, "restartablePC"));
684e407b4c8SLawrence Tang error_info_cper->ParticipationType = readable_pair_to_integer(
685e407b4c8SLawrence Tang json_object_object_get(error_information, "participationType"));
686e407b4c8SLawrence Tang error_info_cper->AddressSpace = readable_pair_to_integer(
687e407b4c8SLawrence Tang json_object_object_get(error_information, "addressSpace"));
688e407b4c8SLawrence Tang error_info_cper->AccessMode = readable_pair_to_integer(
689e407b4c8SLawrence Tang json_object_object_get(error_information, "accessMode"));
690e407b4c8SLawrence Tang error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
691e407b4c8SLawrence Tang json_object_object_get(error_information, "memoryAttributes"));
69271570a2aSLawrence Tang error_info_cper->Reserved = 0;
69371570a2aSLawrence Tang }
69471570a2aSLawrence Tang
6957cd13908SLawrence Tang //Converts a single ARM context information structure into CPER binary, outputting to the given stream.
ir_arm_context_info_to_cper(json_object * context_info,FILE * out)6967cd13908SLawrence Tang void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
6977cd13908SLawrence Tang {
69871570a2aSLawrence Tang EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
6997cd13908SLawrence Tang
70071570a2aSLawrence Tang //Version, array size, context type.
701e407b4c8SLawrence Tang info_header.Version = json_object_get_int(
702e407b4c8SLawrence Tang json_object_object_get(context_info, "version"));
703e407b4c8SLawrence Tang info_header.RegisterArraySize = json_object_get_int(
704e407b4c8SLawrence Tang json_object_object_get(context_info, "registerArraySize"));
705e407b4c8SLawrence Tang info_header.RegisterContextType = readable_pair_to_integer(
706e407b4c8SLawrence Tang json_object_object_get(context_info, "registerContextType"));
70771570a2aSLawrence Tang
70871570a2aSLawrence Tang //Flush to stream, write the register array itself.
709e407b4c8SLawrence Tang fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
710e407b4c8SLawrence Tang out);
71171570a2aSLawrence Tang fflush(out);
71271570a2aSLawrence Tang
713e407b4c8SLawrence Tang json_object *register_array =
714e407b4c8SLawrence Tang json_object_object_get(context_info, "registerArray");
715e407b4c8SLawrence Tang switch (info_header.RegisterContextType) {
71671570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
71771570a2aSLawrence Tang ir_arm_aarch32_gpr_to_cper(register_array, out);
71871570a2aSLawrence Tang break;
71971570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
72071570a2aSLawrence Tang ir_arm_aarch32_el1_to_cper(register_array, out);
72171570a2aSLawrence Tang break;
72271570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
72371570a2aSLawrence Tang ir_arm_aarch32_el2_to_cper(register_array, out);
72471570a2aSLawrence Tang break;
72571570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
72671570a2aSLawrence Tang ir_arm_aarch32_secure_to_cper(register_array, out);
72771570a2aSLawrence Tang break;
72871570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
72971570a2aSLawrence Tang ir_arm_aarch64_gpr_to_cper(register_array, out);
73071570a2aSLawrence Tang break;
73171570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
73271570a2aSLawrence Tang ir_arm_aarch64_el1_to_cper(register_array, out);
73371570a2aSLawrence Tang break;
73471570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
73571570a2aSLawrence Tang ir_arm_aarch64_el2_to_cper(register_array, out);
73671570a2aSLawrence Tang break;
73771570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
73871570a2aSLawrence Tang ir_arm_aarch64_el3_to_cper(register_array, out);
73971570a2aSLawrence Tang break;
74071570a2aSLawrence Tang case EFI_ARM_CONTEXT_TYPE_MISC:
74171570a2aSLawrence Tang ir_arm_misc_registers_to_cper(register_array, out);
74271570a2aSLawrence Tang break;
74371570a2aSLawrence Tang default:
74471570a2aSLawrence Tang //Unknown register structure.
745f8fc7052SJohn Chung ir_arm_unknown_register_to_cper(register_array, out);
74671570a2aSLawrence Tang break;
74771570a2aSLawrence Tang }
74871570a2aSLawrence Tang }
74971570a2aSLawrence Tang
75071570a2aSLawrence Tang //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_gpr_to_cper(json_object * registers,FILE * out)75171570a2aSLawrence Tang void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
75271570a2aSLawrence Tang {
75371570a2aSLawrence Tang //Get uniform register array.
75471570a2aSLawrence Tang EFI_ARM_V8_AARCH32_GPR reg_array;
75571570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array,
756e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
757e407b4c8SLawrence Tang ARM_AARCH32_GPR_NAMES);
75871570a2aSLawrence Tang
75971570a2aSLawrence Tang //Flush to stream.
76071570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
76171570a2aSLawrence Tang fflush(out);
76271570a2aSLawrence Tang }
76371570a2aSLawrence Tang
76471570a2aSLawrence Tang //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_el1_to_cper(json_object * registers,FILE * out)76571570a2aSLawrence Tang void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
76671570a2aSLawrence Tang {
76771570a2aSLawrence Tang //Get uniform register array.
76871570a2aSLawrence Tang EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
76971570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array,
770e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
771e407b4c8SLawrence Tang sizeof(UINT32),
772e407b4c8SLawrence Tang ARM_AARCH32_EL1_REGISTER_NAMES);
77371570a2aSLawrence Tang
77471570a2aSLawrence Tang //Flush to stream.
77571570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
77671570a2aSLawrence Tang fflush(out);
77771570a2aSLawrence Tang }
77871570a2aSLawrence Tang
77971570a2aSLawrence Tang //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_el2_to_cper(json_object * registers,FILE * out)78071570a2aSLawrence Tang void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
78171570a2aSLawrence Tang {
78271570a2aSLawrence Tang //Get uniform register array.
78371570a2aSLawrence Tang EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
78471570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array,
785e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
786e407b4c8SLawrence Tang sizeof(UINT32),
787e407b4c8SLawrence Tang ARM_AARCH32_EL2_REGISTER_NAMES);
78871570a2aSLawrence Tang
78971570a2aSLawrence Tang //Flush to stream.
79071570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
79171570a2aSLawrence Tang fflush(out);
79271570a2aSLawrence Tang }
79371570a2aSLawrence Tang
79471570a2aSLawrence Tang //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch32_secure_to_cper(json_object * registers,FILE * out)79571570a2aSLawrence Tang void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
79671570a2aSLawrence Tang {
79771570a2aSLawrence Tang //Get uniform register array.
79871570a2aSLawrence Tang EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
79971570a2aSLawrence Tang ir_to_uniform_struct(registers, (UINT32 *)®_array,
800e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
801e407b4c8SLawrence Tang sizeof(UINT32),
802e407b4c8SLawrence Tang ARM_AARCH32_SECURE_REGISTER_NAMES);
80371570a2aSLawrence Tang
80471570a2aSLawrence Tang //Flush to stream.
80571570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
80671570a2aSLawrence Tang fflush(out);
80771570a2aSLawrence Tang }
80871570a2aSLawrence Tang
80971570a2aSLawrence Tang //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_gpr_to_cper(json_object * registers,FILE * out)81071570a2aSLawrence Tang void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
81171570a2aSLawrence Tang {
81271570a2aSLawrence Tang //Get uniform register array.
81371570a2aSLawrence Tang EFI_ARM_V8_AARCH64_GPR reg_array;
81471570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array,
815e407b4c8SLawrence Tang sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
816e407b4c8SLawrence Tang ARM_AARCH64_GPR_NAMES);
81771570a2aSLawrence Tang
81871570a2aSLawrence Tang //Flush to stream.
81971570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
82071570a2aSLawrence Tang fflush(out);
82171570a2aSLawrence Tang }
82271570a2aSLawrence Tang
82371570a2aSLawrence Tang //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_el1_to_cper(json_object * registers,FILE * out)82471570a2aSLawrence Tang void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
82571570a2aSLawrence Tang {
82671570a2aSLawrence Tang //Get uniform register array.
82771570a2aSLawrence Tang EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
82871570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array,
829e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
830e407b4c8SLawrence Tang sizeof(UINT64),
831e407b4c8SLawrence Tang ARM_AARCH64_EL1_REGISTER_NAMES);
83271570a2aSLawrence Tang
83371570a2aSLawrence Tang //Flush to stream.
83471570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
83571570a2aSLawrence Tang fflush(out);
83671570a2aSLawrence Tang }
83771570a2aSLawrence Tang
83871570a2aSLawrence Tang //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_el2_to_cper(json_object * registers,FILE * out)83971570a2aSLawrence Tang void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
84071570a2aSLawrence Tang {
84171570a2aSLawrence Tang //Get uniform register array.
84271570a2aSLawrence Tang EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
84371570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array,
844e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
845e407b4c8SLawrence Tang sizeof(UINT64),
846e407b4c8SLawrence Tang ARM_AARCH64_EL2_REGISTER_NAMES);
84771570a2aSLawrence Tang
84871570a2aSLawrence Tang //Flush to stream.
84971570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
85071570a2aSLawrence Tang fflush(out);
85171570a2aSLawrence Tang }
85271570a2aSLawrence Tang
85371570a2aSLawrence Tang //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_aarch64_el3_to_cper(json_object * registers,FILE * out)85471570a2aSLawrence Tang void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
85571570a2aSLawrence Tang {
85671570a2aSLawrence Tang //Get uniform register array.
85771570a2aSLawrence Tang EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
85871570a2aSLawrence Tang ir_to_uniform_struct64(registers, (UINT64 *)®_array,
859e407b4c8SLawrence Tang sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
860e407b4c8SLawrence Tang sizeof(UINT64),
861e407b4c8SLawrence Tang ARM_AARCH64_EL3_REGISTER_NAMES);
86271570a2aSLawrence Tang
86371570a2aSLawrence Tang //Flush to stream.
86471570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
86571570a2aSLawrence Tang fflush(out);
86671570a2aSLawrence Tang }
86771570a2aSLawrence Tang
86871570a2aSLawrence Tang //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_misc_registers_to_cper(json_object * registers,FILE * out)86971570a2aSLawrence Tang void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
87071570a2aSLawrence Tang {
87171570a2aSLawrence Tang EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
87271570a2aSLawrence Tang
87371570a2aSLawrence Tang //MRS encoding information.
874e407b4c8SLawrence Tang json_object *mrs_encoding =
875e407b4c8SLawrence Tang json_object_object_get(registers, "mrsEncoding");
876e407b4c8SLawrence Tang reg_array.MrsOp2 = json_object_get_uint64(
877e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "op2"));
878e407b4c8SLawrence Tang reg_array.MrsCrm = json_object_get_uint64(
879e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "crm"));
880e407b4c8SLawrence Tang reg_array.MrsCrn = json_object_get_uint64(
881e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "crn"));
882e407b4c8SLawrence Tang reg_array.MrsOp1 = json_object_get_uint64(
883e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "op1"));
884e407b4c8SLawrence Tang reg_array.MrsO0 = json_object_get_uint64(
885e407b4c8SLawrence Tang json_object_object_get(mrs_encoding, "o0"));
88671570a2aSLawrence Tang
88771570a2aSLawrence Tang //Actual register value.
888e407b4c8SLawrence Tang reg_array.Value = json_object_get_uint64(
889e407b4c8SLawrence Tang json_object_object_get(registers, "value"));
89071570a2aSLawrence Tang
89171570a2aSLawrence Tang //Flush to stream.
89271570a2aSLawrence Tang fwrite(®_array, sizeof(reg_array), 1, out);
89371570a2aSLawrence Tang fflush(out);
89471570a2aSLawrence Tang }
89571570a2aSLawrence Tang
89671570a2aSLawrence Tang //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
ir_arm_unknown_register_to_cper(json_object * registers,FILE * out)897f8fc7052SJohn Chung void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
89871570a2aSLawrence Tang {
89971570a2aSLawrence Tang //Get base64 represented data.
90071570a2aSLawrence Tang json_object *encoded = json_object_object_get(registers, "data");
901*a7d2cdddSEd Tanous
902*a7d2cdddSEd Tanous int32_t decoded_len = 0;
903*a7d2cdddSEd Tanous
904*a7d2cdddSEd Tanous UINT8 *decoded = base64_decode(json_object_get_string(encoded),
905*a7d2cdddSEd Tanous json_object_get_string_len(encoded),
906*a7d2cdddSEd Tanous &decoded_len);
907*a7d2cdddSEd Tanous
908*a7d2cdddSEd Tanous if (decoded == NULL) {
909f8fc7052SJohn Chung printf("Failed to allocate decode output buffer. \n");
910f8fc7052SJohn Chung } else {
91171570a2aSLawrence Tang //Flush out to stream.
912f8fc7052SJohn Chung fwrite(&decoded, decoded_len, 1, out);
91371570a2aSLawrence Tang fflush(out);
91471570a2aSLawrence Tang free(decoded);
9157cd13908SLawrence Tang }
916f8fc7052SJohn Chung }
917