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>
95202bbb4SLawrence Tang #include <json.h>
10e42fb487SThu Nguyen #include <libcper/base64.h>
11e42fb487SThu Nguyen #include <libcper/Cper.h>
12e42fb487SThu Nguyen #include <libcper/cper-utils.h>
13e42fb487SThu Nguyen #include <libcper/sections/cper-section-dmar-iommu.h>
14*50b966f7SEd Tanous #include <libcper/log.h>
15db1b7ce2SLawrence Tang
cper_section_dmar_iommu_to_ir(void * section)16db1b7ce2SLawrence Tang //Converts a single IOMMU specific DMAr CPER section into JSON IR.
1712dbd4fdSEd Tanous json_object *cper_section_dmar_iommu_to_ir(const UINT8 *section, UINT32 size)
18db1b7ce2SLawrence Tang {
1912dbd4fdSEd Tanous if (size < sizeof(EFI_IOMMU_DMAR_ERROR_DATA)) {
2012dbd4fdSEd Tanous return NULL;
2112dbd4fdSEd Tanous }
2212dbd4fdSEd Tanous
23e407b4c8SLawrence Tang EFI_IOMMU_DMAR_ERROR_DATA *iommu_error =
24e407b4c8SLawrence Tang (EFI_IOMMU_DMAR_ERROR_DATA *)section;
25db1b7ce2SLawrence Tang json_object *section_ir = json_object_new_object();
26db1b7ce2SLawrence Tang
27db1b7ce2SLawrence Tang //Revision.
28e407b4c8SLawrence Tang json_object_object_add(section_ir, "revision",
29e407b4c8SLawrence Tang json_object_new_int(iommu_error->Revision));
30db1b7ce2SLawrence Tang
31db1b7ce2SLawrence Tang //IOMMU registers.
32e407b4c8SLawrence Tang json_object_object_add(section_ir, "controlRegister",
33e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->Control));
34e407b4c8SLawrence Tang json_object_object_add(section_ir, "statusRegister",
35e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->Status));
36db1b7ce2SLawrence Tang
37db1b7ce2SLawrence Tang //IOMMU event log entry.
38ce0f82bfSLawrence Tang //The format of these entries differ widely by the type of error.
39a7d2cdddSEd Tanous int32_t encoded_len = 0;
40a7d2cdddSEd Tanous
41a7d2cdddSEd Tanous char *encoded = base64_encode((UINT8 *)iommu_error->EventLogEntry, 16,
42a7d2cdddSEd Tanous &encoded_len);
43a7d2cdddSEd Tanous if (encoded == NULL) {
44*50b966f7SEd Tanous cper_print_log("Failed to allocate encode output buffer. \n");
45a7d2cdddSEd Tanous
46a7d2cdddSEd Tanous return NULL;
47a7d2cdddSEd Tanous }
48e407b4c8SLawrence Tang json_object_object_add(section_ir, "eventLogEntry",
49f8fc7052SJohn Chung json_object_new_string_len(encoded,
50f8fc7052SJohn Chung encoded_len));
51ce0f82bfSLawrence Tang free(encoded);
52db1b7ce2SLawrence Tang
53d7e8ca34SLawrence Tang //Device table entry (as base64).
54f8fc7052SJohn Chung encoded_len = 0;
55a7d2cdddSEd Tanous
56a7d2cdddSEd Tanous encoded = base64_encode((UINT8 *)iommu_error->DeviceTableEntry, 32,
57a7d2cdddSEd Tanous &encoded_len);
58a7d2cdddSEd Tanous if (encoded == NULL) {
59*50b966f7SEd Tanous cper_print_log("Failed to allocate encode output buffer. \n");
60a7d2cdddSEd Tanous return NULL;
61a7d2cdddSEd Tanous }
62e407b4c8SLawrence Tang json_object_object_add(section_ir, "deviceTableEntry",
63f8fc7052SJohn Chung json_object_new_string_len(encoded,
64f8fc7052SJohn Chung encoded_len));
65d7e8ca34SLawrence Tang free(encoded);
66db1b7ce2SLawrence Tang
67db1b7ce2SLawrence Tang //Page table entries.
68e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level6",
69e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->PteL6));
70e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level5",
71e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->PteL5));
72e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level4",
73e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->PteL4));
74e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level3",
75e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->PteL3));
76e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level2",
77e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->PteL2));
78e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level1",
79e407b4c8SLawrence Tang json_object_new_uint64(iommu_error->PteL1));
80db1b7ce2SLawrence Tang
81db1b7ce2SLawrence Tang return section_ir;
82db1b7ce2SLawrence Tang }
83205dd1d7SLawrence Tang
84205dd1d7SLawrence Tang //Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream.
85205dd1d7SLawrence Tang void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out)
86205dd1d7SLawrence Tang {
87205dd1d7SLawrence Tang EFI_IOMMU_DMAR_ERROR_DATA *section_cper =
88e407b4c8SLawrence Tang (EFI_IOMMU_DMAR_ERROR_DATA *)calloc(
89e407b4c8SLawrence Tang 1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA));
90205dd1d7SLawrence Tang
91205dd1d7SLawrence Tang //Revision, registers.
92e407b4c8SLawrence Tang section_cper->Revision = (UINT8)json_object_get_int(
93e407b4c8SLawrence Tang json_object_object_get(section, "revision"));
94e407b4c8SLawrence Tang section_cper->Control = json_object_get_uint64(
95e407b4c8SLawrence Tang json_object_object_get(section, "controlRegister"));
96e407b4c8SLawrence Tang section_cper->Status = json_object_get_uint64(
97e407b4c8SLawrence Tang json_object_object_get(section, "statusRegister"));
98205dd1d7SLawrence Tang
99205dd1d7SLawrence Tang //IOMMU event log entry.
100205dd1d7SLawrence Tang json_object *encoded = json_object_object_get(section, "eventLogEntry");
101a7d2cdddSEd Tanous int32_t decoded_len = 0;
102a7d2cdddSEd Tanous
103a7d2cdddSEd Tanous UINT8 *decoded = base64_decode(json_object_get_string(encoded),
104a7d2cdddSEd Tanous json_object_get_string_len(encoded),
105a7d2cdddSEd Tanous &decoded_len);
106a7d2cdddSEd Tanous if (decoded == NULL) {
107*50b966f7SEd Tanous cper_print_log("Failed to allocate decode output buffer. \n");
108f8fc7052SJohn Chung } else {
109f8fc7052SJohn Chung memcpy(section_cper->EventLogEntry, decoded, decoded_len);
110205dd1d7SLawrence Tang free(decoded);
111f8fc7052SJohn Chung }
112205dd1d7SLawrence Tang //Device table entry.
113205dd1d7SLawrence Tang encoded = json_object_object_get(section, "deviceTableEntry");
114f8fc7052SJohn Chung decoded_len = 0;
115a7d2cdddSEd Tanous
116a7d2cdddSEd Tanous decoded = base64_decode(json_object_get_string(encoded),
117a7d2cdddSEd Tanous json_object_get_string_len(encoded),
118a7d2cdddSEd Tanous &decoded_len);
119a7d2cdddSEd Tanous if (decoded == NULL) {
120*50b966f7SEd Tanous cper_print_log("Failed to allocate decode output buffer. \n");
121f8fc7052SJohn Chung } else {
122f8fc7052SJohn Chung memcpy(section_cper->DeviceTableEntry, decoded, decoded_len);
123205dd1d7SLawrence Tang free(decoded);
124f8fc7052SJohn Chung }
125205dd1d7SLawrence Tang
126205dd1d7SLawrence Tang //Page table entries.
127e407b4c8SLawrence Tang section_cper->PteL1 = json_object_get_uint64(
128e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level1"));
129e407b4c8SLawrence Tang section_cper->PteL2 = json_object_get_uint64(
130e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level2"));
131e407b4c8SLawrence Tang section_cper->PteL3 = json_object_get_uint64(
132e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level3"));
133e407b4c8SLawrence Tang section_cper->PteL4 = json_object_get_uint64(
134e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level4"));
135e407b4c8SLawrence Tang section_cper->PteL5 = json_object_get_uint64(
136e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level5"));
137e407b4c8SLawrence Tang section_cper->PteL6 = json_object_get_uint64(
138e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level6"));
139205dd1d7SLawrence Tang
140205dd1d7SLawrence Tang //Write to stream, free resources.
1413ab351feSLawrence Tang fwrite(section_cper, sizeof(EFI_IOMMU_DMAR_ERROR_DATA), 1, out);
142205dd1d7SLawrence Tang fflush(out);
143205dd1d7SLawrence Tang free(section_cper);
144205dd1d7SLawrence Tang }
145