14795d4aeSLawrence Tang /**
24795d4aeSLawrence Tang  * Describes functions for converting generic DMAr CPER sections from binary and JSON format
34795d4aeSLawrence Tang  * into an intermediate format.
44795d4aeSLawrence Tang  *
54795d4aeSLawrence Tang  * Author: Lawrence.Tang@arm.com
64795d4aeSLawrence Tang  **/
74795d4aeSLawrence Tang #include <stdio.h>
84795d4aeSLawrence Tang #include "json.h"
94795d4aeSLawrence Tang #include "../edk/Cper.h"
104795d4aeSLawrence Tang #include "../cper-utils.h"
114795d4aeSLawrence Tang #include "cper-section-dmar-generic.h"
124795d4aeSLawrence Tang 
134795d4aeSLawrence Tang //Converts a single generic DMAr CPER section into JSON IR.
14*e407b4c8SLawrence Tang json_object *
15*e407b4c8SLawrence Tang cper_section_dmar_generic_to_ir(void *section,
16*e407b4c8SLawrence Tang 				EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
174795d4aeSLawrence Tang {
18*e407b4c8SLawrence Tang 	EFI_DMAR_GENERIC_ERROR_DATA *firmware_error =
19*e407b4c8SLawrence Tang 		(EFI_DMAR_GENERIC_ERROR_DATA *)section;
204795d4aeSLawrence Tang 	json_object *section_ir = json_object_new_object();
214795d4aeSLawrence Tang 
224795d4aeSLawrence Tang 	//Requester ID, segment.
23*e407b4c8SLawrence Tang 	json_object_object_add(
24*e407b4c8SLawrence Tang 		section_ir, "requesterID",
25*e407b4c8SLawrence Tang 		json_object_new_int(firmware_error->RequesterId));
26*e407b4c8SLawrence Tang 	json_object_object_add(
27*e407b4c8SLawrence Tang 		section_ir, "segmentNumber",
28*e407b4c8SLawrence Tang 		json_object_new_int(firmware_error->SegmentNumber));
294795d4aeSLawrence Tang 
304795d4aeSLawrence Tang 	//Fault reason.
31*e407b4c8SLawrence Tang 	json_object *fault_reason = integer_to_readable_pair_with_desc(
32*e407b4c8SLawrence Tang 		firmware_error->FaultReason, 11,
334795d4aeSLawrence Tang 		DMAR_GENERIC_ERROR_FAULT_REASON_TYPES_KEYS,
344795d4aeSLawrence Tang 		DMAR_GENERIC_ERROR_FAULT_REASON_TYPES_VALUES,
354795d4aeSLawrence Tang 		DMAR_GENERIC_ERROR_FAULT_REASON_TYPES_DESCRIPTIONS,
364795d4aeSLawrence Tang 		"Unknown (Reserved)");
374795d4aeSLawrence Tang 	json_object_object_add(section_ir, "faultReason", fault_reason);
384795d4aeSLawrence Tang 
394795d4aeSLawrence Tang 	//Access type.
40*e407b4c8SLawrence Tang 	json_object *access_type = integer_to_readable_pair(
41*e407b4c8SLawrence Tang 		firmware_error->AccessType, 2,
424795d4aeSLawrence Tang 		DMAR_GENERIC_ERROR_ACCESS_TYPES_KEYS,
43*e407b4c8SLawrence Tang 		DMAR_GENERIC_ERROR_ACCESS_TYPES_VALUES, "Unknown (Reserved)");
444795d4aeSLawrence Tang 	json_object_object_add(section_ir, "accessType", access_type);
454795d4aeSLawrence Tang 
464795d4aeSLawrence Tang 	//Address type.
47*e407b4c8SLawrence Tang 	json_object *address_type = integer_to_readable_pair(
48*e407b4c8SLawrence Tang 		firmware_error->AddressType, 2,
494795d4aeSLawrence Tang 		DMAR_GENERIC_ERROR_ADDRESS_TYPES_KEYS,
50*e407b4c8SLawrence Tang 		DMAR_GENERIC_ERROR_ADDRESS_TYPES_VALUES, "Unknown (Reserved)");
514795d4aeSLawrence Tang 	json_object_object_add(section_ir, "addressType", address_type);
524795d4aeSLawrence Tang 
534795d4aeSLawrence Tang 	//Architecture type.
54*e407b4c8SLawrence Tang 	json_object *arch_type = integer_to_readable_pair(
55*e407b4c8SLawrence Tang 		firmware_error->ArchType, 2, DMAR_GENERIC_ERROR_ARCH_TYPES_KEYS,
56*e407b4c8SLawrence Tang 		DMAR_GENERIC_ERROR_ARCH_TYPES_VALUES, "Unknown (Reserved)");
574795d4aeSLawrence Tang 	json_object_object_add(section_ir, "architectureType", arch_type);
584795d4aeSLawrence Tang 
594795d4aeSLawrence Tang 	//Device address.
60*e407b4c8SLawrence Tang 	json_object_object_add(
61*e407b4c8SLawrence Tang 		section_ir, "deviceAddress",
62*e407b4c8SLawrence Tang 		json_object_new_uint64(firmware_error->DeviceAddr));
634795d4aeSLawrence Tang 
644795d4aeSLawrence Tang 	return section_ir;
654795d4aeSLawrence Tang }
66205dd1d7SLawrence Tang 
67205dd1d7SLawrence Tang //Converts a single generic DMAR CPER-JSON section into CPER binary, outputting to the given stream.
68205dd1d7SLawrence Tang void ir_section_dmar_generic_to_cper(json_object *section, FILE *out)
69205dd1d7SLawrence Tang {
70205dd1d7SLawrence Tang 	EFI_DMAR_GENERIC_ERROR_DATA *section_cper =
71*e407b4c8SLawrence Tang 		(EFI_DMAR_GENERIC_ERROR_DATA *)calloc(
72*e407b4c8SLawrence Tang 			1, sizeof(EFI_DMAR_GENERIC_ERROR_DATA));
73205dd1d7SLawrence Tang 
74205dd1d7SLawrence Tang 	//Record fields.
75*e407b4c8SLawrence Tang 	section_cper->RequesterId = (UINT16)json_object_get_int(
76*e407b4c8SLawrence Tang 		json_object_object_get(section, "requesterID"));
77*e407b4c8SLawrence Tang 	section_cper->SegmentNumber = (UINT16)json_object_get_int(
78*e407b4c8SLawrence Tang 		json_object_object_get(section, "segmentNumber"));
79*e407b4c8SLawrence Tang 	section_cper->FaultReason = (UINT8)readable_pair_to_integer(
80*e407b4c8SLawrence Tang 		json_object_object_get(section, "faultReason"));
81*e407b4c8SLawrence Tang 	section_cper->AccessType = (UINT8)readable_pair_to_integer(
82*e407b4c8SLawrence Tang 		json_object_object_get(section, "accessType"));
83*e407b4c8SLawrence Tang 	section_cper->AddressType = (UINT8)readable_pair_to_integer(
84*e407b4c8SLawrence Tang 		json_object_object_get(section, "addressType"));
85*e407b4c8SLawrence Tang 	section_cper->ArchType = (UINT8)readable_pair_to_integer(
86*e407b4c8SLawrence Tang 		json_object_object_get(section, "architectureType"));
87*e407b4c8SLawrence Tang 	section_cper->DeviceAddr = json_object_get_uint64(
88*e407b4c8SLawrence Tang 		json_object_object_get(section, "deviceAddress"));
89205dd1d7SLawrence Tang 
90205dd1d7SLawrence Tang 	//Write to stream, free resources.
913ab351feSLawrence Tang 	fwrite(section_cper, sizeof(EFI_DMAR_GENERIC_ERROR_DATA), 1, out);
92205dd1d7SLawrence Tang 	fflush(out);
93205dd1d7SLawrence Tang 	free(section_cper);
94205dd1d7SLawrence Tang }