xref: /openbmc/libcper/sections/cper-section-arm.c (revision ae8f6d9aaeaf37332e8924dd2c0b6f320335548c)
1 /**
2  * Describes functions for converting ARM CPER sections from binary and JSON format
3  * into an intermediate format.
4  *
5  * Author: Lawrence.Tang@arm.com
6  **/
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <json.h>
11 #include <libcper/base64.h>
12 #include <libcper/Cper.h>
13 #include <libcper/cper-utils.h>
14 #include <libcper/sections/cper-section-arm.h>
15 
16 //Private pre-definitions.
17 json_object *
18 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
19 json_object *
20 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
21 				 void **cur_pos);
22 json_object *
23 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
24 			       EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
25 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
26 json_object *cper_arm_misc_register_array_to_ir(
27 	EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
28 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
29 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
30 void ir_arm_error_cache_tlb_info_to_cper(
31 	json_object *error_information,
32 	EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
33 void ir_arm_error_bus_info_to_cper(json_object *error_information,
34 				   EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
35 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
36 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
37 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
38 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
39 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
40 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
41 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
42 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
43 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
44 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
45 
46 //Converts the given processor-generic CPER section into JSON IR.
cper_section_arm_to_ir(void * section)47 json_object *cper_section_arm_to_ir(void *section)
48 {
49 	EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
50 	json_object *section_ir = json_object_new_object();
51 
52 	//Length of ValidationBits from spec
53 	ValidationTypes ui64Type = { UINT_64T,
54 				     .value.ui64 = record->ValidFields };
55 
56 	//Number of error info and context info structures, and length.
57 	json_object_object_add(section_ir, "errorInfoNum",
58 			       json_object_new_int(record->ErrInfoNum));
59 	json_object_object_add(section_ir, "contextInfoNum",
60 			       json_object_new_int(record->ContextInfoNum));
61 	json_object_object_add(section_ir, "sectionLength",
62 			       json_object_new_uint64(record->SectionLength));
63 
64 	//Error affinity.
65 	if (isvalid_prop_to_ir(&ui64Type, 1)) {
66 		json_object *error_affinity = json_object_new_object();
67 		json_object_object_add(
68 			error_affinity, "value",
69 			json_object_new_int(record->ErrorAffinityLevel));
70 		json_object_object_add(
71 			error_affinity, "type",
72 			json_object_new_string(record->ErrorAffinityLevel < 4 ?
73 						       "Vendor Defined" :
74 						       "Reserved"));
75 		json_object_object_add(section_ir, "errorAffinity",
76 				       error_affinity);
77 	}
78 
79 	//Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
80 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
81 		uint64_t mpidr_eli1 = record->MPIDR_EL1;
82 		uint64_t sock;
83 		json_object_object_add(section_ir, "mpidrEl1",
84 				       json_object_new_uint64(mpidr_eli1));
85 
86 		//Arm Processor socket info dependes on mpidr_eli1
87 		sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
88 		json_object_object_add(section_ir, "affinity3",
89 				       json_object_new_uint64(sock));
90 	}
91 
92 	json_object_object_add(section_ir, "midrEl1",
93 			       json_object_new_uint64(record->MIDR_EL1));
94 
95 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
96 		//Whether the processor is running, and the state of it if so.
97 		json_object_object_add(
98 			section_ir, "running",
99 			json_object_new_boolean(record->RunningState & 0x1));
100 	}
101 	if (!(record->RunningState >> 31)) {
102 		//Bit 32 of running state is on, so PSCI state information is included.
103 		//This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
104 		//or the newer Extended StateID format.
105 		json_object_object_add(
106 			section_ir, "psciState",
107 			json_object_new_uint64(record->PsciState));
108 	}
109 
110 	//Processor error structures.
111 	json_object *error_info_array = json_object_new_array();
112 	EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
113 		(EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
114 	for (int i = 0; i < record->ErrInfoNum; i++) {
115 		json_object_array_add(error_info_array,
116 				      cper_arm_error_info_to_ir(cur_error));
117 		cur_error++;
118 	}
119 	json_object_object_add(section_ir, "errorInfo", error_info_array);
120 
121 	//Processor context structures.
122 	//The current position is moved within the processing, as it is a dynamic size structure.
123 	uint8_t *cur_pos = (uint8_t *)cur_error;
124 	json_object *context_info_array = json_object_new_array();
125 	for (int i = 0; i < record->ContextInfoNum; i++) {
126 		EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
127 			(EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
128 		json_object *processor_context =
129 			cper_arm_processor_context_to_ir(header,
130 							 (void **)&cur_pos);
131 		json_object_array_add(context_info_array, processor_context);
132 	}
133 	json_object_object_add(section_ir, "contextInfo", context_info_array);
134 
135 	//Is there any vendor-specific information following?
136 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
137 		if (cur_pos < (uint8_t *)section + record->SectionLength) {
138 			json_object *vendor_specific = json_object_new_object();
139 			size_t input_size = (uint8_t *)section +
140 					    record->SectionLength - cur_pos;
141 			int32_t encoded_len = 0;
142 			char *encoded = base64_encode(cur_pos, input_size,
143 						      &encoded_len);
144 			if (encoded == NULL) {
145 				printf("base64 encode of vendorSpecificInfo failed\n");
146 				return NULL;
147 			}
148 			json_object_object_add(vendor_specific, "data",
149 					       json_object_new_string_len(
150 						       encoded, encoded_len));
151 			free(encoded);
152 
153 			json_object_object_add(section_ir, "vendorSpecificInfo",
154 					       vendor_specific);
155 		} else {
156 			printf("vendorSpecificInfo is marked valid but not present in binary\n");
157 		}
158 	}
159 
160 	return section_ir;
161 }
162 
163 //Converts a single ARM Process Error Information structure into JSON IR.
164 json_object *
cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)165 cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
166 {
167 	json_object *error_info_ir = json_object_new_object();
168 
169 	//Version, length.
170 	json_object_object_add(error_info_ir, "version",
171 			       json_object_new_int(error_info->Version));
172 	json_object_object_add(error_info_ir, "length",
173 			       json_object_new_int(error_info->Length));
174 
175 	//Validation bitfield.
176 	ValidationTypes ui16Type = { UINT_16T,
177 				     .value.ui16 = error_info->ValidationBits };
178 
179 	//The type of error information in this log.
180 	json_object *error_type = integer_to_readable_pair(
181 		error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
182 		ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
183 	json_object_object_add(error_info_ir, "errorType", error_type);
184 
185 	//Multiple error count.
186 	if (isvalid_prop_to_ir(&ui16Type, 0)) {
187 		json_object *multiple_error = json_object_new_object();
188 		json_object_object_add(
189 			multiple_error, "value",
190 			json_object_new_int(error_info->MultipleError));
191 		json_object_object_add(
192 			multiple_error, "type",
193 			json_object_new_string(error_info->MultipleError < 1 ?
194 						       "Single Error" :
195 						       "Multiple Errors"));
196 		json_object_object_add(error_info_ir, "multipleError",
197 				       multiple_error);
198 	}
199 
200 	//Flags.
201 	if (isvalid_prop_to_ir(&ui16Type, 1)) {
202 		json_object *flags = bitfield_to_ir(
203 			error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
204 		json_object_object_add(error_info_ir, "flags", flags);
205 	}
206 
207 	//Error information, split by type.
208 	if (isvalid_prop_to_ir(&ui16Type, 2)) {
209 		json_object *error_subinfo = NULL;
210 		switch (error_info->Type) {
211 		case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
212 		case ARM_ERROR_INFORMATION_TYPE_TLB:   //TLB
213 			error_subinfo = cper_arm_cache_tlb_error_to_ir(
214 				(EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
215 					->ErrorInformation,
216 				error_info);
217 			break;
218 		case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
219 			error_subinfo = cper_arm_bus_error_to_ir(
220 				(EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
221 					->ErrorInformation);
222 			break;
223 
224 		default:
225 			//Unknown/microarch, will not support.
226 			break;
227 		}
228 		json_object_object_add(error_info_ir, "errorInformation",
229 				       error_subinfo);
230 	}
231 
232 	//Virtual fault address, physical fault address.
233 	if (isvalid_prop_to_ir(&ui16Type, 3)) {
234 		json_object_object_add(
235 			error_info_ir, "virtualFaultAddress",
236 			json_object_new_uint64(
237 				error_info->VirtualFaultAddress));
238 	}
239 	if (isvalid_prop_to_ir(&ui16Type, 4)) {
240 		json_object_object_add(
241 			error_info_ir, "physicalFaultAddress",
242 			json_object_new_uint64(
243 				error_info->PhysicalFaultAddress));
244 	}
245 
246 	return error_info_ir;
247 }
248 
249 //Converts a single ARM cache/TLB error information structure into JSON IR format.
250 json_object *
cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE * cache_tlb_error,EFI_ARM_ERROR_INFORMATION_ENTRY * error_info)251 cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
252 			       EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
253 {
254 	json_object *cache_tlb_error_ir = json_object_new_object();
255 	json_object *cache_tlb_prop = json_object_new_object();
256 	char *cache_tlb_propname;
257 
258 	//Validation bitfield.
259 	ValidationTypes ui64Type = {
260 		UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
261 	};
262 
263 	//Transaction type.
264 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
265 		json_object *transaction_type = integer_to_readable_pair(
266 			cache_tlb_error->TransactionType, 3,
267 			ARM_ERROR_TRANSACTION_TYPES_KEYS,
268 			ARM_ERROR_TRANSACTION_TYPES_VALUES,
269 			"Unknown (Reserved)");
270 		json_object_object_add(cache_tlb_error_ir, "transactionType",
271 				       transaction_type);
272 	}
273 
274 	//Operation.
275 	bool cacheErrorFlag = 1;
276 	if (error_info->Type == 0) {
277 		cache_tlb_propname = "cacheError";
278 	} else {
279 		//TLB operation.
280 		cache_tlb_propname = "tlbError";
281 		cacheErrorFlag = 0;
282 	}
283 
284 	if (isvalid_prop_to_ir(&ui64Type, 1)) {
285 		json_object *operation;
286 
287 		if (cacheErrorFlag) {
288 			//Cache operation.
289 			operation = integer_to_readable_pair(
290 				cache_tlb_error->Operation, 11,
291 				ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
292 				ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
293 				"Unknown (Reserved)");
294 		} else {
295 			operation = integer_to_readable_pair(
296 				cache_tlb_error->Operation, 9,
297 				ARM_TLB_OPERATION_TYPES_KEYS,
298 				ARM_TLB_OPERATION_TYPES_VALUES,
299 				"Unknown (Reserved)");
300 		}
301 		json_object_object_add(cache_tlb_error_ir, "operation",
302 				       operation);
303 	}
304 
305 	//Miscellaneous remaining fields.
306 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
307 		json_object_object_add(
308 			cache_tlb_error_ir, "level",
309 			json_object_new_int(cache_tlb_error->Level));
310 	}
311 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
312 		json_object_object_add(
313 			cache_tlb_error_ir, "processorContextCorrupt",
314 			json_object_new_boolean(
315 				cache_tlb_error->ProcessorContextCorrupt));
316 	}
317 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
318 		json_object_object_add(
319 			cache_tlb_error_ir, "corrected",
320 			json_object_new_boolean(cache_tlb_error->Corrected));
321 	}
322 	if (isvalid_prop_to_ir(&ui64Type, 5)) {
323 		json_object_object_add(
324 			cache_tlb_error_ir, "precisePC",
325 			json_object_new_boolean(cache_tlb_error->PrecisePC));
326 	}
327 	if (isvalid_prop_to_ir(&ui64Type, 6)) {
328 		json_object_object_add(cache_tlb_error_ir, "restartablePC",
329 				       json_object_new_boolean(
330 					       cache_tlb_error->RestartablePC));
331 	}
332 
333 	json_object_object_add(cache_tlb_prop, cache_tlb_propname,
334 			       cache_tlb_error_ir);
335 
336 	return cache_tlb_prop;
337 }
338 
339 //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)340 json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
341 {
342 	json_object *bus_error_ir = json_object_new_object();
343 	json_object *bus_prop = json_object_new_object();
344 	char *bus_propname = "busError";
345 
346 	//Validation bits.
347 	ValidationTypes ui64Type = { UINT_64T,
348 				     .value.ui64 = bus_error->ValidationBits };
349 
350 	//Transaction type.
351 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
352 		json_object *transaction_type = integer_to_readable_pair(
353 			bus_error->TransactionType, 3,
354 			ARM_ERROR_TRANSACTION_TYPES_KEYS,
355 			ARM_ERROR_TRANSACTION_TYPES_VALUES,
356 			"Unknown (Reserved)");
357 		json_object_object_add(bus_error_ir, "transactionType",
358 				       transaction_type);
359 	}
360 
361 	//Operation.
362 	if (isvalid_prop_to_ir(&ui64Type, 1)) {
363 		json_object *operation = integer_to_readable_pair(
364 			bus_error->Operation, 7,
365 			ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
366 			ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
367 			"Unknown (Reserved)");
368 		json_object_object_add(bus_error_ir, "operation", operation);
369 	}
370 
371 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
372 		//Affinity level of bus error, + miscellaneous fields.
373 		json_object_object_add(bus_error_ir, "level",
374 				       json_object_new_int(bus_error->Level));
375 	}
376 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
377 		json_object_object_add(
378 			bus_error_ir, "processorContextCorrupt",
379 			json_object_new_boolean(
380 				bus_error->ProcessorContextCorrupt));
381 	}
382 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
383 		json_object_object_add(
384 			bus_error_ir, "corrected",
385 			json_object_new_boolean(bus_error->Corrected));
386 	}
387 	if (isvalid_prop_to_ir(&ui64Type, 5)) {
388 		json_object_object_add(
389 			bus_error_ir, "precisePC",
390 			json_object_new_boolean(bus_error->PrecisePC));
391 	}
392 	if (isvalid_prop_to_ir(&ui64Type, 6)) {
393 		json_object_object_add(
394 			bus_error_ir, "restartablePC",
395 			json_object_new_boolean(bus_error->RestartablePC));
396 	}
397 
398 	//Participation type.
399 	if (isvalid_prop_to_ir(&ui64Type, 7)) {
400 		json_object *participation_type = integer_to_readable_pair(
401 			bus_error->ParticipationType, 4,
402 			ARM_BUS_PARTICIPATION_TYPES_KEYS,
403 			ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
404 		json_object_object_add(bus_error_ir, "participationType",
405 				       participation_type);
406 	}
407 	if (isvalid_prop_to_ir(&ui64Type, 8)) {
408 		json_object_object_add(
409 			bus_error_ir, "timedOut",
410 			json_object_new_boolean(bus_error->TimeOut));
411 	}
412 
413 	//Address space.
414 	if (isvalid_prop_to_ir(&ui64Type, 9)) {
415 		json_object *address_space = integer_to_readable_pair(
416 			bus_error->AddressSpace, 3,
417 			ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
418 			ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
419 		json_object_object_add(bus_error_ir, "addressSpace",
420 				       address_space);
421 	}
422 
423 	//Memory access attributes.
424 	//todo: find the specification of these in the ARM ARM
425 	if (isvalid_prop_to_ir(&ui64Type, 10)) {
426 		json_object_object_add(
427 			bus_error_ir, "memoryAttributes",
428 			json_object_new_int(
429 				bus_error->MemoryAddressAttributes));
430 	}
431 
432 	//Access Mode
433 	if (isvalid_prop_to_ir(&ui64Type, 8)) {
434 		json_object *access_mode = json_object_new_object();
435 		json_object_object_add(
436 			access_mode, "value",
437 			json_object_new_int(bus_error->AccessMode));
438 		json_object_object_add(
439 			access_mode, "name",
440 			json_object_new_string(bus_error->AccessMode == 0 ?
441 						       "Secure" :
442 						       "Normal"));
443 		json_object_object_add(bus_error_ir, "accessMode", access_mode);
444 	}
445 	json_object_object_add(bus_prop, bus_propname, bus_error_ir);
446 
447 	return bus_prop;
448 }
449 
450 //Converts a single ARM processor context block into JSON IR.
451 json_object *
cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER * header,void ** cur_pos)452 cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
453 				 void **cur_pos)
454 {
455 	json_object *context_ir = json_object_new_object();
456 
457 	//Version.
458 	json_object_object_add(context_ir, "version",
459 			       json_object_new_int(header->Version));
460 
461 	//Add the context type.
462 	json_object *context_type = integer_to_readable_pair(
463 		header->RegisterContextType, 9,
464 		ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
465 		ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
466 		"Unknown (Reserved)");
467 	json_object_object_add(context_ir, "registerContextType", context_type);
468 
469 	//Register array size (bytes).
470 	json_object_object_add(
471 		context_ir, "registerArraySize",
472 		json_object_new_uint64(header->RegisterArraySize));
473 
474 	//The register array itself.
475 	*cur_pos = (void *)(header + 1);
476 	json_object *register_array = NULL;
477 	switch (header->RegisterContextType) {
478 	case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
479 		register_array = uniform_struct_to_ir(
480 			(UINT32 *)*cur_pos,
481 			sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
482 			ARM_AARCH32_GPR_NAMES);
483 		break;
484 	case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
485 		register_array = uniform_struct_to_ir(
486 			(UINT32 *)*cur_pos,
487 			sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
488 				sizeof(UINT32),
489 			ARM_AARCH32_EL1_REGISTER_NAMES);
490 		break;
491 	case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
492 		register_array = uniform_struct_to_ir(
493 			(UINT32 *)*cur_pos,
494 			sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
495 				sizeof(UINT32),
496 			ARM_AARCH32_EL2_REGISTER_NAMES);
497 		break;
498 	case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
499 		register_array = uniform_struct_to_ir(
500 			(UINT32 *)*cur_pos,
501 			sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
502 				sizeof(UINT32),
503 			ARM_AARCH32_SECURE_REGISTER_NAMES);
504 		break;
505 	case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
506 		register_array = uniform_struct64_to_ir(
507 			(UINT64 *)*cur_pos,
508 			sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
509 			ARM_AARCH64_GPR_NAMES);
510 		break;
511 	case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
512 		register_array = uniform_struct64_to_ir(
513 			(UINT64 *)*cur_pos,
514 			sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
515 				sizeof(UINT64),
516 			ARM_AARCH64_EL1_REGISTER_NAMES);
517 		break;
518 	case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
519 		register_array = uniform_struct64_to_ir(
520 			(UINT64 *)*cur_pos,
521 			sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
522 				sizeof(UINT64),
523 			ARM_AARCH64_EL2_REGISTER_NAMES);
524 		break;
525 	case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
526 		register_array = uniform_struct64_to_ir(
527 			(UINT64 *)*cur_pos,
528 			sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
529 				sizeof(UINT64),
530 			ARM_AARCH64_EL3_REGISTER_NAMES);
531 		break;
532 	case EFI_ARM_CONTEXT_TYPE_MISC:
533 		register_array = cper_arm_misc_register_array_to_ir(
534 			(EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
535 		break;
536 	default:
537 		//Unknown register array type, add as base64 data instead.
538 		register_array = json_object_new_object();
539 		int32_t encoded_len = 0;
540 		char *encoded = base64_encode((UINT8 *)*cur_pos,
541 					      header->RegisterArraySize,
542 					      &encoded_len);
543 		if (encoded == NULL) {
544 			printf("Failed to allocate encode output buffer. \n");
545 			return NULL;
546 		}
547 		json_object_object_add(register_array, "data",
548 				       json_object_new_string_len(encoded,
549 								  encoded_len));
550 		free(encoded);
551 
552 		break;
553 	}
554 	json_object_object_add(context_ir, "registerArray", register_array);
555 
556 	//Set the current position to after the processor context structure.
557 	*cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
558 
559 	return context_ir;
560 }
561 
562 //Converts a single CPER ARM miscellaneous register array to JSON IR format.
563 json_object *
cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER * misc_register)564 cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
565 {
566 	json_object *register_array = json_object_new_object();
567 	json_object *mrs_encoding = json_object_new_object();
568 	json_object_object_add(mrs_encoding, "op2",
569 			       json_object_new_uint64(misc_register->MrsOp2));
570 	json_object_object_add(mrs_encoding, "crm",
571 			       json_object_new_uint64(misc_register->MrsCrm));
572 	json_object_object_add(mrs_encoding, "crn",
573 			       json_object_new_uint64(misc_register->MrsCrn));
574 	json_object_object_add(mrs_encoding, "op1",
575 			       json_object_new_uint64(misc_register->MrsOp1));
576 	json_object_object_add(mrs_encoding, "o0",
577 			       json_object_new_uint64(misc_register->MrsO0));
578 	json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
579 	json_object_object_add(register_array, "value",
580 			       json_object_new_uint64(misc_register->Value));
581 
582 	return register_array;
583 }
584 
585 //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)586 void ir_section_arm_to_cper(json_object *section, FILE *out)
587 {
588 	EFI_ARM_ERROR_RECORD section_cper;
589 	memset(&section_cper, 0, sizeof(section_cper));
590 
591 	//Validation bits.
592 	struct json_object *obj = NULL;
593 	ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
594 
595 	//Count of error/context info structures.
596 	section_cper.ErrInfoNum = json_object_get_int(
597 		json_object_object_get(section, "errorInfoNum"));
598 	section_cper.ContextInfoNum = json_object_get_int(
599 		json_object_object_get(section, "contextInfoNum"));
600 
601 	//Miscellaneous raw value fields.
602 	section_cper.SectionLength = json_object_get_uint64(
603 		json_object_object_get(section, "sectionLength"));
604 	if (json_object_object_get_ex(section, "mpidrEl1", &obj)) {
605 		section_cper.MPIDR_EL1 = json_object_get_uint64(obj);
606 		add_to_valid_bitfield(&u32Type, 0);
607 	}
608 	if (json_object_object_get_ex(section, "errorAffinity", &obj)) {
609 		section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj);
610 		add_to_valid_bitfield(&u32Type, 1);
611 	}
612 	section_cper.MIDR_EL1 = json_object_get_uint64(
613 		json_object_object_get(section, "midrEl1"));
614 	if (json_object_object_get_ex(section, "running", &obj)) {
615 		section_cper.RunningState = json_object_get_boolean(obj);
616 		add_to_valid_bitfield(&u32Type, 2);
617 	}
618 
619 	//Optional PSCI state.
620 	json_object *psci_state = json_object_object_get(section, "psciState");
621 	if (psci_state != NULL) {
622 		section_cper.PsciState = json_object_get_uint64(psci_state);
623 	}
624 
625 	//Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo
626 	bool vendorSpecificPresent =
627 		json_object_object_get_ex(section, "vendorSpecificInfo", &obj);
628 	json_object *vendor_specific_info = obj;
629 	if (vendorSpecificPresent) {
630 		add_to_valid_bitfield(&u32Type, 3);
631 	}
632 
633 	section_cper.ValidFields = u32Type.value.ui32;
634 
635 	//Flush header to stream.
636 	fwrite(&section_cper, sizeof(section_cper), 1, out);
637 
638 	//Error info structure array.
639 
640 	json_object *error_info = json_object_object_get(section, "errorInfo");
641 	for (int i = 0; i < section_cper.ErrInfoNum; i++) {
642 		ir_arm_error_info_to_cper(
643 			json_object_array_get_idx(error_info, i), out);
644 	}
645 
646 	//Context info structure array.
647 	json_object *context_info =
648 		json_object_object_get(section, "contextInfo");
649 	for (int i = 0; i < section_cper.ContextInfoNum; i++) {
650 		ir_arm_context_info_to_cper(
651 			json_object_array_get_idx(context_info, i), out);
652 	}
653 
654 	//Vendor specific error info.
655 	if (vendorSpecificPresent) {
656 		json_object *vendor_info_string =
657 			json_object_object_get(vendor_specific_info, "data");
658 		int vendor_specific_len =
659 			json_object_get_string_len(vendor_info_string);
660 
661 		int32_t decoded_len = 0;
662 
663 		UINT8 *decoded = base64_decode(
664 			json_object_get_string(vendor_info_string),
665 			vendor_specific_len, &decoded_len);
666 
667 		//Write out to file.
668 		fwrite(decoded, decoded_len, 1, out);
669 		free(decoded);
670 	}
671 
672 	fflush(out);
673 }
674 
675 //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)676 void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
677 {
678 	EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
679 	memset(&error_info_cper, 0, sizeof(error_info_cper));
680 	struct json_object *obj = NULL;
681 	ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
682 
683 	//Version, length.
684 	error_info_cper.Version = json_object_get_int(
685 		json_object_object_get(error_info, "version"));
686 	error_info_cper.Length = json_object_get_int(
687 		json_object_object_get(error_info, "length"));
688 
689 	//Type, multiple error.
690 	error_info_cper.Type = (UINT8)readable_pair_to_integer(
691 		json_object_object_get(error_info, "errorType"));
692 
693 	if (json_object_object_get_ex(error_info, "multipleError", &obj)) {
694 		error_info_cper.MultipleError =
695 			(UINT16)readable_pair_to_integer(obj);
696 		add_to_valid_bitfield(&ui16Type, 0);
697 	} else {
698 		error_info_cper.MultipleError = 0;
699 	}
700 
701 	//Flags object.
702 	if (json_object_object_get_ex(error_info, "flags", &obj)) {
703 		error_info_cper.Flags = (UINT8)ir_to_bitfield(
704 			obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
705 		add_to_valid_bitfield(&ui16Type, 1);
706 	} else {
707 		error_info_cper.Flags = 0;
708 	}
709 
710 	//Error information.
711 	if (json_object_object_get_ex(error_info, "errorInformation", &obj)) {
712 		json_object *error_info_information = obj;
713 		json_object *error_info_prop = NULL;
714 		switch (error_info_cper.Type) {
715 		case ARM_ERROR_INFORMATION_TYPE_CACHE:
716 			error_info_cper.ErrorInformation.Value = 0;
717 			error_info_prop = json_object_object_get(
718 				error_info_information, "cacheError");
719 			ir_arm_error_cache_tlb_info_to_cper(
720 				error_info_prop,
721 				&error_info_cper.ErrorInformation.CacheError);
722 			break;
723 		case ARM_ERROR_INFORMATION_TYPE_TLB:
724 			error_info_cper.ErrorInformation.Value = 0;
725 			error_info_prop = json_object_object_get(
726 				error_info_information, "tlbError");
727 			ir_arm_error_cache_tlb_info_to_cper(
728 				error_info_prop,
729 				&error_info_cper.ErrorInformation.CacheError);
730 			break;
731 
732 		case ARM_ERROR_INFORMATION_TYPE_BUS:
733 			error_info_cper.ErrorInformation.Value = 0;
734 			error_info_prop = json_object_object_get(
735 				error_info_information, "busError");
736 			ir_arm_error_bus_info_to_cper(
737 				error_info_prop,
738 				&error_info_cper.ErrorInformation.BusError);
739 			break;
740 
741 		default:
742 			//Unknown error information type.
743 			break;
744 		}
745 		add_to_valid_bitfield(&ui16Type, 2);
746 	}
747 
748 	//Virtual/physical fault address.
749 	if (json_object_object_get_ex(error_info, "virtualFaultAddress",
750 				      &obj)) {
751 		error_info_cper.VirtualFaultAddress =
752 			json_object_get_uint64(obj);
753 		add_to_valid_bitfield(&ui16Type, 3);
754 	} else {
755 		error_info_cper.VirtualFaultAddress = 0;
756 	}
757 
758 	if (json_object_object_get_ex(error_info, "physicalFaultAddress",
759 				      &obj)) {
760 		error_info_cper.PhysicalFaultAddress =
761 			json_object_get_uint64(obj);
762 		add_to_valid_bitfield(&ui16Type, 4);
763 	} else {
764 		error_info_cper.PhysicalFaultAddress = 0;
765 	}
766 	error_info_cper.ValidationBits = ui16Type.value.ui16;
767 
768 	//Write out to stream.
769 	fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
770 	       out);
771 }
772 
773 //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)774 void ir_arm_error_cache_tlb_info_to_cper(
775 	json_object *error_information,
776 	EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
777 {
778 	// //Validation bits.
779 	ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
780 	struct json_object *obj = NULL;
781 
782 	//Miscellaneous value fields.
783 	if (json_object_object_get_ex(error_information, "transactionType",
784 				      &obj)) {
785 		error_info_cper->TransactionType =
786 			readable_pair_to_integer(obj);
787 		add_to_valid_bitfield(&ui64Type, 0);
788 	}
789 	if (json_object_object_get_ex(error_information, "operation", &obj)) {
790 		error_info_cper->Operation = readable_pair_to_integer(obj);
791 		add_to_valid_bitfield(&ui64Type, 1);
792 	}
793 	if (json_object_object_get_ex(error_information, "level", &obj)) {
794 		error_info_cper->Level = json_object_get_uint64(obj);
795 		add_to_valid_bitfield(&ui64Type, 2);
796 	}
797 	if (json_object_object_get_ex(error_information,
798 				      "processorContextCorrupt", &obj)) {
799 		error_info_cper->ProcessorContextCorrupt =
800 			json_object_get_boolean(obj);
801 		add_to_valid_bitfield(&ui64Type, 3);
802 	}
803 	if (json_object_object_get_ex(error_information, "corrected", &obj)) {
804 		error_info_cper->Corrected = json_object_get_boolean(obj);
805 		add_to_valid_bitfield(&ui64Type, 4);
806 	}
807 	if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
808 		error_info_cper->PrecisePC = json_object_get_boolean(obj);
809 		add_to_valid_bitfield(&ui64Type, 5);
810 	}
811 	if (json_object_object_get_ex(error_information, "restartablePC",
812 				      &obj)) {
813 		error_info_cper->RestartablePC = json_object_get_boolean(obj);
814 		add_to_valid_bitfield(&ui64Type, 6);
815 	}
816 	error_info_cper->Reserved = 0;
817 	error_info_cper->ValidationBits = ui64Type.value.ui64;
818 }
819 
820 //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)821 void ir_arm_error_bus_info_to_cper(json_object *error_information,
822 				   EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
823 {
824 	//Validation bits.
825 	ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
826 	struct json_object *obj = NULL;
827 
828 	memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE));
829 
830 	//Miscellaneous value fields.
831 	if (json_object_object_get_ex(error_information, "transactionType",
832 				      &obj)) {
833 		error_info_cper->TransactionType =
834 			readable_pair_to_integer(obj);
835 		add_to_valid_bitfield(&ui64Type, 0);
836 	} else {
837 		error_info_cper->TransactionType = 0;
838 	}
839 	if (json_object_object_get_ex(error_information, "operation", &obj)) {
840 		error_info_cper->Operation = readable_pair_to_integer(obj);
841 		add_to_valid_bitfield(&ui64Type, 1);
842 	} else {
843 		error_info_cper->Operation = 0;
844 	}
845 	if (json_object_object_get_ex(error_information, "level", &obj)) {
846 		error_info_cper->Level = json_object_get_uint64(obj);
847 		add_to_valid_bitfield(&ui64Type, 2);
848 	} else {
849 		error_info_cper->Level = 0;
850 	}
851 	if (json_object_object_get_ex(error_information,
852 				      "processorContextCorrupt", &obj)) {
853 		error_info_cper->ProcessorContextCorrupt =
854 			json_object_get_boolean(obj);
855 		add_to_valid_bitfield(&ui64Type, 3);
856 	} else {
857 		error_info_cper->ProcessorContextCorrupt = 0;
858 	}
859 	if (json_object_object_get_ex(error_information, "corrected", &obj)) {
860 		error_info_cper->Corrected = json_object_get_boolean(obj);
861 		add_to_valid_bitfield(&ui64Type, 4);
862 	} else {
863 		error_info_cper->Corrected = 0;
864 	}
865 	if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
866 		error_info_cper->PrecisePC = json_object_get_boolean(obj);
867 		add_to_valid_bitfield(&ui64Type, 5);
868 	} else {
869 		error_info_cper->PrecisePC = 0;
870 	}
871 	if (json_object_object_get_ex(error_information, "restartablePC",
872 				      &obj)) {
873 		error_info_cper->RestartablePC = json_object_get_boolean(obj);
874 		add_to_valid_bitfield(&ui64Type, 6);
875 	} else {
876 		error_info_cper->RestartablePC = 0;
877 	}
878 	if (json_object_object_get_ex(error_information, "participationType",
879 				      &obj)) {
880 		error_info_cper->ParticipationType =
881 			readable_pair_to_integer(obj);
882 		add_to_valid_bitfield(&ui64Type, 7);
883 	} else {
884 		error_info_cper->ParticipationType = 0;
885 	}
886 	if (json_object_object_get_ex(error_information, "timedOut", &obj)) {
887 		error_info_cper->TimeOut = json_object_get_boolean(obj);
888 		add_to_valid_bitfield(&ui64Type, 8);
889 	} else {
890 		error_info_cper->TimeOut = 0;
891 	}
892 	if (json_object_object_get_ex(error_information, "addressSpace",
893 				      &obj)) {
894 		error_info_cper->AddressSpace = readable_pair_to_integer(obj);
895 		add_to_valid_bitfield(&ui64Type, 9);
896 	} else {
897 		error_info_cper->AddressSpace = 0;
898 	}
899 	if (json_object_object_get_ex(error_information, "accessMode", &obj)) {
900 		error_info_cper->AccessMode = readable_pair_to_integer(obj);
901 		add_to_valid_bitfield(&ui64Type, 11);
902 	} else {
903 		error_info_cper->AccessMode = 0;
904 	}
905 	if (json_object_object_get_ex(error_information, "memoryAttributes",
906 				      &obj)) {
907 		error_info_cper->MemoryAddressAttributes =
908 			json_object_get_uint64(obj);
909 		add_to_valid_bitfield(&ui64Type, 10);
910 	} else {
911 		error_info_cper->MemoryAddressAttributes = 0;
912 	}
913 	error_info_cper->Reserved = 0;
914 	error_info_cper->ValidationBits = ui64Type.value.ui64;
915 }
916 
917 //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)918 void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
919 {
920 	EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
921 
922 	//Version, array size, context type.
923 	info_header.Version = json_object_get_int(
924 		json_object_object_get(context_info, "version"));
925 	info_header.RegisterArraySize = json_object_get_int(
926 		json_object_object_get(context_info, "registerArraySize"));
927 	info_header.RegisterContextType = readable_pair_to_integer(
928 		json_object_object_get(context_info, "registerContextType"));
929 
930 	//Flush to stream, write the register array itself.
931 	fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
932 	       out);
933 	fflush(out);
934 
935 	json_object *register_array =
936 		json_object_object_get(context_info, "registerArray");
937 	switch (info_header.RegisterContextType) {
938 	case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
939 		ir_arm_aarch32_gpr_to_cper(register_array, out);
940 		break;
941 	case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
942 		ir_arm_aarch32_el1_to_cper(register_array, out);
943 		break;
944 	case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
945 		ir_arm_aarch32_el2_to_cper(register_array, out);
946 		break;
947 	case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
948 		ir_arm_aarch32_secure_to_cper(register_array, out);
949 		break;
950 	case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
951 		ir_arm_aarch64_gpr_to_cper(register_array, out);
952 		break;
953 	case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
954 		ir_arm_aarch64_el1_to_cper(register_array, out);
955 		break;
956 	case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
957 		ir_arm_aarch64_el2_to_cper(register_array, out);
958 		break;
959 	case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
960 		ir_arm_aarch64_el3_to_cper(register_array, out);
961 		break;
962 	case EFI_ARM_CONTEXT_TYPE_MISC:
963 		ir_arm_misc_registers_to_cper(register_array, out);
964 		break;
965 	default:
966 		//Unknown register structure.
967 		ir_arm_unknown_register_to_cper(register_array, out);
968 		break;
969 	}
970 }
971 
972 //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)973 void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
974 {
975 	//Get uniform register array.
976 	EFI_ARM_V8_AARCH32_GPR reg_array;
977 	ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
978 			     sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
979 			     ARM_AARCH32_GPR_NAMES);
980 
981 	//Flush to stream.
982 	fwrite(&reg_array, sizeof(reg_array), 1, out);
983 	fflush(out);
984 }
985 
986 //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)987 void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
988 {
989 	//Get uniform register array.
990 	EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
991 	ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
992 			     sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
993 				     sizeof(UINT32),
994 			     ARM_AARCH32_EL1_REGISTER_NAMES);
995 
996 	//Flush to stream.
997 	fwrite(&reg_array, sizeof(reg_array), 1, out);
998 	fflush(out);
999 }
1000 
1001 //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)1002 void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
1003 {
1004 	//Get uniform register array.
1005 	EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1006 	ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1007 			     sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1008 				     sizeof(UINT32),
1009 			     ARM_AARCH32_EL2_REGISTER_NAMES);
1010 
1011 	//Flush to stream.
1012 	fwrite(&reg_array, sizeof(reg_array), 1, out);
1013 	fflush(out);
1014 }
1015 
1016 //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)1017 void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
1018 {
1019 	//Get uniform register array.
1020 	EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
1021 	ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1022 			     sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1023 				     sizeof(UINT32),
1024 			     ARM_AARCH32_SECURE_REGISTER_NAMES);
1025 
1026 	//Flush to stream.
1027 	fwrite(&reg_array, sizeof(reg_array), 1, out);
1028 	fflush(out);
1029 }
1030 
1031 //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)1032 void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
1033 {
1034 	//Get uniform register array.
1035 	EFI_ARM_V8_AARCH64_GPR reg_array;
1036 	ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1037 			       sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1038 			       ARM_AARCH64_GPR_NAMES);
1039 
1040 	//Flush to stream.
1041 	fwrite(&reg_array, sizeof(reg_array), 1, out);
1042 	fflush(out);
1043 }
1044 
1045 //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)1046 void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
1047 {
1048 	//Get uniform register array.
1049 	EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1050 	ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1051 			       sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1052 				       sizeof(UINT64),
1053 			       ARM_AARCH64_EL1_REGISTER_NAMES);
1054 
1055 	//Flush to stream.
1056 	fwrite(&reg_array, sizeof(reg_array), 1, out);
1057 	fflush(out);
1058 }
1059 
1060 //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)1061 void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
1062 {
1063 	//Get uniform register array.
1064 	EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1065 	ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1066 			       sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1067 				       sizeof(UINT64),
1068 			       ARM_AARCH64_EL2_REGISTER_NAMES);
1069 
1070 	//Flush to stream.
1071 	fwrite(&reg_array, sizeof(reg_array), 1, out);
1072 	fflush(out);
1073 }
1074 
1075 //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)1076 void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
1077 {
1078 	//Get uniform register array.
1079 	EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
1080 	ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1081 			       sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1082 				       sizeof(UINT64),
1083 			       ARM_AARCH64_EL3_REGISTER_NAMES);
1084 
1085 	//Flush to stream.
1086 	fwrite(&reg_array, sizeof(reg_array), 1, out);
1087 	fflush(out);
1088 }
1089 
1090 //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)1091 void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
1092 {
1093 	EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
1094 
1095 	//MRS encoding information.
1096 	json_object *mrs_encoding =
1097 		json_object_object_get(registers, "mrsEncoding");
1098 	reg_array.MrsOp2 = json_object_get_uint64(
1099 		json_object_object_get(mrs_encoding, "op2"));
1100 	reg_array.MrsCrm = json_object_get_uint64(
1101 		json_object_object_get(mrs_encoding, "crm"));
1102 	reg_array.MrsCrn = json_object_get_uint64(
1103 		json_object_object_get(mrs_encoding, "crn"));
1104 	reg_array.MrsOp1 = json_object_get_uint64(
1105 		json_object_object_get(mrs_encoding, "op1"));
1106 	reg_array.MrsO0 = json_object_get_uint64(
1107 		json_object_object_get(mrs_encoding, "o0"));
1108 
1109 	//Actual register value.
1110 	reg_array.Value = json_object_get_uint64(
1111 		json_object_object_get(registers, "value"));
1112 
1113 	//Flush to stream.
1114 	fwrite(&reg_array, sizeof(reg_array), 1, out);
1115 	fflush(out);
1116 }
1117 
1118 //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)1119 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
1120 {
1121 	//Get base64 represented data.
1122 	json_object *encoded = json_object_object_get(registers, "data");
1123 
1124 	int32_t decoded_len = 0;
1125 
1126 	UINT8 *decoded = base64_decode(json_object_get_string(encoded),
1127 				       json_object_get_string_len(encoded),
1128 				       &decoded_len);
1129 
1130 	if (decoded == NULL) {
1131 		printf("Failed to allocate decode output buffer. \n");
1132 	} else {
1133 		//Flush out to stream.
1134 		fwrite(&decoded, decoded_len, 1, out);
1135 		fflush(out);
1136 		free(decoded);
1137 	}
1138 }
1139