1 /**
2  * Describes functions for converting IOMMU specific DMAr CPER sections from binary and JSON format
3  * into an intermediate format.
4  *
5  * Author: Lawrence.Tang@arm.com
6  **/
7 #include <stdio.h>
8 #include <string.h>
9 #include "json.h"
10 #include "b64.h"
11 #include "../edk/Cper.h"
12 #include "../cper-utils.h"
13 #include "cper-section-dmar-iommu.h"
14 
15 //Converts a single IOMMU specific DMAr CPER section into JSON IR.
16 json_object *
17 cper_section_dmar_iommu_to_ir(void *section,
18 			      EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
19 {
20 	EFI_IOMMU_DMAR_ERROR_DATA *iommu_error =
21 		(EFI_IOMMU_DMAR_ERROR_DATA *)section;
22 	json_object *section_ir = json_object_new_object();
23 
24 	//Revision.
25 	json_object_object_add(section_ir, "revision",
26 			       json_object_new_int(iommu_error->Revision));
27 
28 	//IOMMU registers.
29 	json_object_object_add(section_ir, "controlRegister",
30 			       json_object_new_uint64(iommu_error->Control));
31 	json_object_object_add(section_ir, "statusRegister",
32 			       json_object_new_uint64(iommu_error->Status));
33 
34 	//IOMMU event log entry.
35 	//The format of these entries differ widely by the type of error.
36 	char *encoded =
37 		b64_encode((unsigned char *)iommu_error->EventLogEntry, 16);
38 	json_object_object_add(section_ir, "eventLogEntry",
39 			       json_object_new_string(encoded));
40 	free(encoded);
41 
42 	//Device table entry (as base64).
43 	encoded =
44 		b64_encode((unsigned char *)iommu_error->DeviceTableEntry, 32);
45 	json_object_object_add(section_ir, "deviceTableEntry",
46 			       json_object_new_string(encoded));
47 	free(encoded);
48 
49 	//Page table entries.
50 	json_object_object_add(section_ir, "pageTableEntry_Level6",
51 			       json_object_new_uint64(iommu_error->PteL6));
52 	json_object_object_add(section_ir, "pageTableEntry_Level5",
53 			       json_object_new_uint64(iommu_error->PteL5));
54 	json_object_object_add(section_ir, "pageTableEntry_Level4",
55 			       json_object_new_uint64(iommu_error->PteL4));
56 	json_object_object_add(section_ir, "pageTableEntry_Level3",
57 			       json_object_new_uint64(iommu_error->PteL3));
58 	json_object_object_add(section_ir, "pageTableEntry_Level2",
59 			       json_object_new_uint64(iommu_error->PteL2));
60 	json_object_object_add(section_ir, "pageTableEntry_Level1",
61 			       json_object_new_uint64(iommu_error->PteL1));
62 
63 	return section_ir;
64 }
65 
66 //Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream.
67 void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out)
68 {
69 	EFI_IOMMU_DMAR_ERROR_DATA *section_cper =
70 		(EFI_IOMMU_DMAR_ERROR_DATA *)calloc(
71 			1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA));
72 
73 	//Revision, registers.
74 	section_cper->Revision = (UINT8)json_object_get_int(
75 		json_object_object_get(section, "revision"));
76 	section_cper->Control = json_object_get_uint64(
77 		json_object_object_get(section, "controlRegister"));
78 	section_cper->Status = json_object_get_uint64(
79 		json_object_object_get(section, "statusRegister"));
80 
81 	//IOMMU event log entry.
82 	json_object *encoded = json_object_object_get(section, "eventLogEntry");
83 	UINT8 *decoded = b64_decode(json_object_get_string(encoded),
84 				    json_object_get_string_len(encoded));
85 	memcpy(section_cper->EventLogEntry, decoded, 16);
86 	free(decoded);
87 
88 	//Device table entry.
89 	encoded = json_object_object_get(section, "deviceTableEntry");
90 	decoded = b64_decode(json_object_get_string(encoded),
91 			     json_object_get_string_len(encoded));
92 	memcpy(section_cper->DeviceTableEntry, decoded, 32);
93 	free(decoded);
94 
95 	//Page table entries.
96 	section_cper->PteL1 = json_object_get_uint64(
97 		json_object_object_get(section, "pageTableEntry_Level1"));
98 	section_cper->PteL2 = json_object_get_uint64(
99 		json_object_object_get(section, "pageTableEntry_Level2"));
100 	section_cper->PteL3 = json_object_get_uint64(
101 		json_object_object_get(section, "pageTableEntry_Level3"));
102 	section_cper->PteL4 = json_object_get_uint64(
103 		json_object_object_get(section, "pageTableEntry_Level4"));
104 	section_cper->PteL5 = json_object_get_uint64(
105 		json_object_object_get(section, "pageTableEntry_Level5"));
106 	section_cper->PteL6 = json_object_get_uint64(
107 		json_object_object_get(section, "pageTableEntry_Level6"));
108 
109 	//Write to stream, free resources.
110 	fwrite(section_cper, sizeof(EFI_IOMMU_DMAR_ERROR_DATA), 1, out);
111 	fflush(out);
112 	free(section_cper);
113 }