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>
8*5202bbb4SLawrence 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.
14e407b4c8SLawrence Tang json_object *
15e407b4c8SLawrence Tang cper_section_dmar_generic_to_ir(void *section,
16e407b4c8SLawrence Tang 				EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
174795d4aeSLawrence Tang {
18e407b4c8SLawrence Tang 	EFI_DMAR_GENERIC_ERROR_DATA *firmware_error =
19e407b4c8SLawrence Tang 		(EFI_DMAR_GENERIC_ERROR_DATA *)section;
204795d4aeSLawrence Tang 	json_object *section_ir = json_object_new_object();
214795d4aeSLawrence Tang 
224795d4aeSLawrence Tang 	//Requester ID, segment.
23e407b4c8SLawrence Tang 	json_object_object_add(
24e407b4c8SLawrence Tang 		section_ir, "requesterID",
25e407b4c8SLawrence Tang 		json_object_new_int(firmware_error->RequesterId));
26e407b4c8SLawrence Tang 	json_object_object_add(
27e407b4c8SLawrence Tang 		section_ir, "segmentNumber",
28e407b4c8SLawrence Tang 		json_object_new_int(firmware_error->SegmentNumber));
294795d4aeSLawrence Tang 
304795d4aeSLawrence Tang 	//Fault reason.
31e407b4c8SLawrence Tang 	json_object *fault_reason = integer_to_readable_pair_with_desc(
32e407b4c8SLawrence 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.
40e407b4c8SLawrence Tang 	json_object *access_type = integer_to_readable_pair(
41e407b4c8SLawrence Tang 		firmware_error->AccessType, 2,
424795d4aeSLawrence Tang 		DMAR_GENERIC_ERROR_ACCESS_TYPES_KEYS,
43e407b4c8SLawrence 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.
47e407b4c8SLawrence Tang 	json_object *address_type = integer_to_readable_pair(
48e407b4c8SLawrence Tang 		firmware_error->AddressType, 2,
494795d4aeSLawrence Tang 		DMAR_GENERIC_ERROR_ADDRESS_TYPES_KEYS,
50e407b4c8SLawrence 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.
54e407b4c8SLawrence Tang 	json_object *arch_type = integer_to_readable_pair(
55e407b4c8SLawrence Tang 		firmware_error->ArchType, 2, DMAR_GENERIC_ERROR_ARCH_TYPES_KEYS,
56e407b4c8SLawrence 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.
60e407b4c8SLawrence Tang 	json_object_object_add(
61e407b4c8SLawrence Tang 		section_ir, "deviceAddress",
62e407b4c8SLawrence 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 =
71e407b4c8SLawrence Tang 		(EFI_DMAR_GENERIC_ERROR_DATA *)calloc(
72e407b4c8SLawrence Tang 			1, sizeof(EFI_DMAR_GENERIC_ERROR_DATA));
73205dd1d7SLawrence Tang 
74205dd1d7SLawrence Tang 	//Record fields.
75e407b4c8SLawrence Tang 	section_cper->RequesterId = (UINT16)json_object_get_int(
76e407b4c8SLawrence Tang 		json_object_object_get(section, "requesterID"));
77e407b4c8SLawrence Tang 	section_cper->SegmentNumber = (UINT16)json_object_get_int(
78e407b4c8SLawrence Tang 		json_object_object_get(section, "segmentNumber"));
79e407b4c8SLawrence Tang 	section_cper->FaultReason = (UINT8)readable_pair_to_integer(
80e407b4c8SLawrence Tang 		json_object_object_get(section, "faultReason"));
81e407b4c8SLawrence Tang 	section_cper->AccessType = (UINT8)readable_pair_to_integer(
82e407b4c8SLawrence Tang 		json_object_object_get(section, "accessType"));
83e407b4c8SLawrence Tang 	section_cper->AddressType = (UINT8)readable_pair_to_integer(
84e407b4c8SLawrence Tang 		json_object_object_get(section, "addressType"));
85e407b4c8SLawrence Tang 	section_cper->ArchType = (UINT8)readable_pair_to_integer(
86e407b4c8SLawrence Tang 		json_object_object_get(section, "architectureType"));
87e407b4c8SLawrence Tang 	section_cper->DeviceAddr = json_object_get_uint64(
88e407b4c8SLawrence 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 }