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 *)&reg_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(&reg_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 *)&reg_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(&reg_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 *)&reg_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(&reg_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 *)&reg_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(&reg_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 *)&reg_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(&reg_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 *)&reg_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(&reg_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 *)&reg_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(&reg_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 *)&reg_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(&reg_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(&reg_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