1db1b7ce2SLawrence Tang /**
2db1b7ce2SLawrence Tang  * Describes functions for converting IOMMU specific DMAr CPER sections from binary and JSON format
3db1b7ce2SLawrence Tang  * into an intermediate format.
4db1b7ce2SLawrence Tang  *
5db1b7ce2SLawrence Tang  * Author: Lawrence.Tang@arm.com
6db1b7ce2SLawrence Tang  **/
7db1b7ce2SLawrence Tang #include <stdio.h>
8205dd1d7SLawrence Tang #include <string.h>
9db1b7ce2SLawrence Tang #include "json.h"
10d7e8ca34SLawrence Tang #include "b64.h"
11db1b7ce2SLawrence Tang #include "../edk/Cper.h"
12db1b7ce2SLawrence Tang #include "../cper-utils.h"
13db1b7ce2SLawrence Tang #include "cper-section-dmar-iommu.h"
14db1b7ce2SLawrence Tang 
15db1b7ce2SLawrence Tang //Converts a single IOMMU specific DMAr CPER section into JSON IR.
16*e407b4c8SLawrence Tang json_object *
17*e407b4c8SLawrence Tang cper_section_dmar_iommu_to_ir(void *section,
18*e407b4c8SLawrence Tang 			      EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
19db1b7ce2SLawrence Tang {
20*e407b4c8SLawrence Tang 	EFI_IOMMU_DMAR_ERROR_DATA *iommu_error =
21*e407b4c8SLawrence Tang 		(EFI_IOMMU_DMAR_ERROR_DATA *)section;
22db1b7ce2SLawrence Tang 	json_object *section_ir = json_object_new_object();
23db1b7ce2SLawrence Tang 
24db1b7ce2SLawrence Tang 	//Revision.
25*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "revision",
26*e407b4c8SLawrence Tang 			       json_object_new_int(iommu_error->Revision));
27db1b7ce2SLawrence Tang 
28db1b7ce2SLawrence Tang 	//IOMMU registers.
29*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "controlRegister",
30*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->Control));
31*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "statusRegister",
32*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->Status));
33db1b7ce2SLawrence Tang 
34db1b7ce2SLawrence Tang 	//IOMMU event log entry.
35ce0f82bfSLawrence Tang 	//The format of these entries differ widely by the type of error.
36*e407b4c8SLawrence Tang 	char *encoded =
37*e407b4c8SLawrence Tang 		b64_encode((unsigned char *)iommu_error->EventLogEntry, 16);
38*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "eventLogEntry",
39*e407b4c8SLawrence Tang 			       json_object_new_string(encoded));
40ce0f82bfSLawrence Tang 	free(encoded);
41db1b7ce2SLawrence Tang 
42d7e8ca34SLawrence Tang 	//Device table entry (as base64).
43*e407b4c8SLawrence Tang 	encoded =
44*e407b4c8SLawrence Tang 		b64_encode((unsigned char *)iommu_error->DeviceTableEntry, 32);
45*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "deviceTableEntry",
46*e407b4c8SLawrence Tang 			       json_object_new_string(encoded));
47d7e8ca34SLawrence Tang 	free(encoded);
48db1b7ce2SLawrence Tang 
49db1b7ce2SLawrence Tang 	//Page table entries.
50*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "pageTableEntry_Level6",
51*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->PteL6));
52*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "pageTableEntry_Level5",
53*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->PteL5));
54*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "pageTableEntry_Level4",
55*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->PteL4));
56*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "pageTableEntry_Level3",
57*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->PteL3));
58*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "pageTableEntry_Level2",
59*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->PteL2));
60*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "pageTableEntry_Level1",
61*e407b4c8SLawrence Tang 			       json_object_new_uint64(iommu_error->PteL1));
62db1b7ce2SLawrence Tang 
63db1b7ce2SLawrence Tang 	return section_ir;
64db1b7ce2SLawrence Tang }
65205dd1d7SLawrence Tang 
66205dd1d7SLawrence Tang //Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream.
67205dd1d7SLawrence Tang void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out)
68205dd1d7SLawrence Tang {
69205dd1d7SLawrence Tang 	EFI_IOMMU_DMAR_ERROR_DATA *section_cper =
70*e407b4c8SLawrence Tang 		(EFI_IOMMU_DMAR_ERROR_DATA *)calloc(
71*e407b4c8SLawrence Tang 			1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA));
72205dd1d7SLawrence Tang 
73205dd1d7SLawrence Tang 	//Revision, registers.
74*e407b4c8SLawrence Tang 	section_cper->Revision = (UINT8)json_object_get_int(
75*e407b4c8SLawrence Tang 		json_object_object_get(section, "revision"));
76*e407b4c8SLawrence Tang 	section_cper->Control = json_object_get_uint64(
77*e407b4c8SLawrence Tang 		json_object_object_get(section, "controlRegister"));
78*e407b4c8SLawrence Tang 	section_cper->Status = json_object_get_uint64(
79*e407b4c8SLawrence Tang 		json_object_object_get(section, "statusRegister"));
80205dd1d7SLawrence Tang 
81205dd1d7SLawrence Tang 	//IOMMU event log entry.
82205dd1d7SLawrence Tang 	json_object *encoded = json_object_object_get(section, "eventLogEntry");
83*e407b4c8SLawrence Tang 	UINT8 *decoded = b64_decode(json_object_get_string(encoded),
84*e407b4c8SLawrence Tang 				    json_object_get_string_len(encoded));
85205dd1d7SLawrence Tang 	memcpy(section_cper->EventLogEntry, decoded, 16);
86205dd1d7SLawrence Tang 	free(decoded);
87205dd1d7SLawrence Tang 
88205dd1d7SLawrence Tang 	//Device table entry.
89205dd1d7SLawrence Tang 	encoded = json_object_object_get(section, "deviceTableEntry");
90*e407b4c8SLawrence Tang 	decoded = b64_decode(json_object_get_string(encoded),
91*e407b4c8SLawrence Tang 			     json_object_get_string_len(encoded));
92205dd1d7SLawrence Tang 	memcpy(section_cper->DeviceTableEntry, decoded, 32);
93205dd1d7SLawrence Tang 	free(decoded);
94205dd1d7SLawrence Tang 
95205dd1d7SLawrence Tang 	//Page table entries.
96*e407b4c8SLawrence Tang 	section_cper->PteL1 = json_object_get_uint64(
97*e407b4c8SLawrence Tang 		json_object_object_get(section, "pageTableEntry_Level1"));
98*e407b4c8SLawrence Tang 	section_cper->PteL2 = json_object_get_uint64(
99*e407b4c8SLawrence Tang 		json_object_object_get(section, "pageTableEntry_Level2"));
100*e407b4c8SLawrence Tang 	section_cper->PteL3 = json_object_get_uint64(
101*e407b4c8SLawrence Tang 		json_object_object_get(section, "pageTableEntry_Level3"));
102*e407b4c8SLawrence Tang 	section_cper->PteL4 = json_object_get_uint64(
103*e407b4c8SLawrence Tang 		json_object_object_get(section, "pageTableEntry_Level4"));
104*e407b4c8SLawrence Tang 	section_cper->PteL5 = json_object_get_uint64(
105*e407b4c8SLawrence Tang 		json_object_object_get(section, "pageTableEntry_Level5"));
106*e407b4c8SLawrence Tang 	section_cper->PteL6 = json_object_get_uint64(
107*e407b4c8SLawrence Tang 		json_object_object_get(section, "pageTableEntry_Level6"));
108205dd1d7SLawrence Tang 
109205dd1d7SLawrence Tang 	//Write to stream, free resources.
1103ab351feSLawrence Tang 	fwrite(section_cper, sizeof(EFI_IOMMU_DMAR_ERROR_DATA), 1, out);
111205dd1d7SLawrence Tang 	fflush(out);
112205dd1d7SLawrence Tang 	free(section_cper);
113205dd1d7SLawrence Tang }