blob: e51b33581fb3f98ebc5d1cbcc7eb25e4b8c48ec0 [file] [log] [blame]
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +01001/**
2 * Describes functions for converting VT-d 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>
Lawrence Tang205dd1d2022-07-14 16:23:38 +01008#include <string.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01009#include <json.h>
John Chungf8fc7052024-05-03 20:05:29 +080010#include "libbase64.h"
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010011#include "../edk/Cper.h"
12#include "../cper-utils.h"
13#include "cper-section-dmar-vtd.h"
14
15//Converts a single VT-d specific DMAr CPER section into JSON IR.
John Chungf8fc7052024-05-03 20:05:29 +080016json_object *cper_section_dmar_vtd_to_ir(void *section)
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010017{
Lawrence Tange407b4c2022-07-21 13:54:01 +010018 EFI_DIRECTED_IO_DMAR_ERROR_DATA *vtd_error =
19 (EFI_DIRECTED_IO_DMAR_ERROR_DATA *)section;
20 json_object *section_ir = json_object_new_object();
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010021
Lawrence Tange407b4c2022-07-21 13:54:01 +010022 //Version, revision and OEM ID, as defined in the VT-d architecture.
23 UINT64 oem_id = 0;
John Chungf8fc7052024-05-03 20:05:29 +080024 for (int i = 0; i < 6; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +010025 oem_id |= (UINT64)vtd_error->OemId[i] << (i * 8);
John Chungf8fc7052024-05-03 20:05:29 +080026 }
Lawrence Tange407b4c2022-07-21 13:54:01 +010027 json_object_object_add(section_ir, "version",
28 json_object_new_int(vtd_error->Version));
29 json_object_object_add(section_ir, "revision",
30 json_object_new_int(vtd_error->Revision));
31 json_object_object_add(section_ir, "oemID",
32 json_object_new_uint64(oem_id));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010033
Lawrence Tange407b4c2022-07-21 13:54:01 +010034 //Registers.
35 json_object_object_add(section_ir, "capabilityRegister",
36 json_object_new_uint64(vtd_error->Capability));
37 json_object_object_add(section_ir, "extendedCapabilityRegister",
38 json_object_new_uint64(vtd_error->CapabilityEx));
39 json_object_object_add(
40 section_ir, "globalCommandRegister",
41 json_object_new_uint64(vtd_error->GlobalCommand));
42 json_object_object_add(section_ir, "globalStatusRegister",
43 json_object_new_uint64(vtd_error->GlobalStatus));
44 json_object_object_add(section_ir, "faultStatusRegister",
45 json_object_new_uint64(vtd_error->FaultStatus));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010046
Lawrence Tange407b4c2022-07-21 13:54:01 +010047 //Fault record basic fields.
48 json_object *fault_record_ir = json_object_new_object();
49 EFI_VTD_FAULT_RECORD *fault_record =
50 (EFI_VTD_FAULT_RECORD *)vtd_error->FaultRecord;
51 json_object_object_add(
52 fault_record_ir, "faultInformation",
53 json_object_new_uint64(fault_record->FaultInformation));
54 json_object_object_add(
55 fault_record_ir, "sourceIdentifier",
56 json_object_new_uint64(fault_record->SourceIdentifier));
57 json_object_object_add(
58 fault_record_ir, "privelegeModeRequested",
59 json_object_new_boolean(fault_record->PrivelegeModeRequested));
60 json_object_object_add(
61 fault_record_ir, "executePermissionRequested",
62 json_object_new_boolean(
63 fault_record->ExecutePermissionRequested));
64 json_object_object_add(
65 fault_record_ir, "pasidPresent",
66 json_object_new_boolean(fault_record->PasidPresent));
67 json_object_object_add(
68 fault_record_ir, "faultReason",
69 json_object_new_uint64(fault_record->FaultReason));
70 json_object_object_add(
71 fault_record_ir, "pasidValue",
72 json_object_new_uint64(fault_record->PasidValue));
73 json_object_object_add(
74 fault_record_ir, "addressType",
75 json_object_new_uint64(fault_record->AddressType));
Lawrence Tangce0f82b2022-07-07 16:14:28 +010076
Lawrence Tange407b4c2022-07-21 13:54:01 +010077 //Fault record type.
78 json_object *fault_record_type = integer_to_readable_pair(
79 fault_record->Type, 2, VTD_FAULT_RECORD_TYPES_KEYS,
80 VTD_FAULT_RECORD_TYPES_VALUES, "Unknown");
81 json_object_object_add(fault_record_ir, "type", fault_record_type);
82 json_object_object_add(section_ir, "faultRecord", fault_record_ir);
Lawrence Tangce0f82b2022-07-07 16:14:28 +010083
Lawrence Tange407b4c2022-07-21 13:54:01 +010084 //Root entry.
John Chungf8fc7052024-05-03 20:05:29 +080085 char *encoded = malloc(2 * 16);
86 size_t encoded_len = 0;
87 if (!encoded) {
88 printf("Failed to allocate encode output buffer. \n");
89 } else {
90 base64_encode((const char *)vtd_error->RootEntry, 16, encoded,
91 &encoded_len, 0);
92 json_object_object_add(section_ir, "rootEntry",
93 json_object_new_string_len(encoded,
94 encoded_len));
95 free(encoded);
96 }
Lawrence Tangce0f82b2022-07-07 16:14:28 +010097
Lawrence Tange407b4c2022-07-21 13:54:01 +010098 //Context entry.
John Chungf8fc7052024-05-03 20:05:29 +080099 encoded = malloc(2 * 16);
100 encoded_len = 0;
101 if (!encoded) {
102 printf("Failed to allocate encode output buffer. \n");
103 } else {
104 base64_encode((const char *)vtd_error->ContextEntry, 16,
105 encoded, &encoded_len, 0);
106 json_object_object_add(section_ir, "contextEntry",
107 json_object_new_string_len(encoded,
108 encoded_len));
109 free(encoded);
110 }
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +0100111
Lawrence Tange407b4c2022-07-21 13:54:01 +0100112 //PTE entry for all page levels.
113 json_object_object_add(section_ir, "pageTableEntry_Level6",
114 json_object_new_uint64(vtd_error->PteL6));
115 json_object_object_add(section_ir, "pageTableEntry_Level5",
116 json_object_new_uint64(vtd_error->PteL5));
117 json_object_object_add(section_ir, "pageTableEntry_Level4",
118 json_object_new_uint64(vtd_error->PteL4));
119 json_object_object_add(section_ir, "pageTableEntry_Level3",
120 json_object_new_uint64(vtd_error->PteL3));
121 json_object_object_add(section_ir, "pageTableEntry_Level2",
122 json_object_new_uint64(vtd_error->PteL2));
123 json_object_object_add(section_ir, "pageTableEntry_Level1",
124 json_object_new_uint64(vtd_error->PteL1));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +0100125
Lawrence Tange407b4c2022-07-21 13:54:01 +0100126 return section_ir;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100127}
128
129//Converts a single VT-d DMAR CPER-JSON segment into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100130void ir_section_dmar_vtd_to_cper(json_object *section, FILE *out)
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100131{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100132 EFI_DIRECTED_IO_DMAR_ERROR_DATA *section_cper =
133 (EFI_DIRECTED_IO_DMAR_ERROR_DATA *)calloc(
134 1, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100135
Lawrence Tange407b4c2022-07-21 13:54:01 +0100136 //OEM ID.
137 UINT64 oem_id = json_object_get_uint64(
138 json_object_object_get(section, "oemID"));
John Chungf8fc7052024-05-03 20:05:29 +0800139 for (int i = 0; i < 6; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100140 section_cper->OemId[i] = (oem_id >> (i * 8)) & 0xFF;
John Chungf8fc7052024-05-03 20:05:29 +0800141 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100142
Lawrence Tange407b4c2022-07-21 13:54:01 +0100143 //Registers & basic numeric fields.
144 section_cper->Version = (UINT8)json_object_get_int(
145 json_object_object_get(section, "version"));
146 section_cper->Revision = (UINT8)json_object_get_int(
147 json_object_object_get(section, "revision"));
148 section_cper->Capability = json_object_get_uint64(
149 json_object_object_get(section, "capabilityRegister"));
150 section_cper->CapabilityEx = json_object_get_uint64(
151 json_object_object_get(section, "extendedCapabilityRegister"));
152 section_cper->GlobalCommand = json_object_get_uint64(
153 json_object_object_get(section, "globalCommandRegister"));
154 section_cper->GlobalStatus = json_object_get_uint64(
155 json_object_object_get(section, "globalStatusRegister"));
156 section_cper->FaultStatus = json_object_get_uint64(
157 json_object_object_get(section, "faultStatusRegister"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100158
Lawrence Tange407b4c2022-07-21 13:54:01 +0100159 //Fault record.
160 json_object *fault_record =
161 json_object_object_get(section, "faultRecord");
162 EFI_VTD_FAULT_RECORD *fault_record_cper =
163 (EFI_VTD_FAULT_RECORD *)section_cper->FaultRecord;
164 fault_record_cper->FaultInformation = json_object_get_uint64(
165 json_object_object_get(fault_record, "faultInformation"));
166 fault_record_cper->SourceIdentifier = json_object_get_uint64(
167 json_object_object_get(fault_record, "sourceIdentifier"));
168 fault_record_cper->PrivelegeModeRequested = json_object_get_boolean(
169 json_object_object_get(fault_record, "privelegeModeRequested"));
170 fault_record_cper->ExecutePermissionRequested = json_object_get_boolean(
171 json_object_object_get(fault_record,
172 "executePermissionRequested"));
173 fault_record_cper->PasidPresent = json_object_get_boolean(
174 json_object_object_get(fault_record, "pasidPresent"));
175 fault_record_cper->FaultReason = json_object_get_uint64(
176 json_object_object_get(fault_record, "faultReason"));
177 fault_record_cper->PasidValue = json_object_get_uint64(
178 json_object_object_get(fault_record, "pasidValue"));
179 fault_record_cper->AddressType = json_object_get_uint64(
180 json_object_object_get(fault_record, "addressType"));
181 fault_record_cper->Type = readable_pair_to_integer(
182 json_object_object_get(fault_record, "type"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100183
Lawrence Tange407b4c2022-07-21 13:54:01 +0100184 //Root entry.
185 json_object *encoded = json_object_object_get(section, "rootEntry");
John Chungf8fc7052024-05-03 20:05:29 +0800186 char *decoded = malloc(json_object_get_string_len(encoded));
187 size_t decoded_len = 0;
188 if (!decoded) {
189 printf("Failed to allocate decode output buffer. \n");
190 } else {
191 base64_decode(json_object_get_string(encoded),
192 json_object_get_string_len(encoded), decoded,
193 &decoded_len, 0);
194 memcpy(section_cper->RootEntry, decoded, decoded_len);
195 free(decoded);
196 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100197 //Context entry.
198 encoded = json_object_object_get(section, "contextEntry");
John Chungf8fc7052024-05-03 20:05:29 +0800199 decoded = malloc(json_object_get_string_len(encoded));
200 decoded_len = 0;
201 if (!decoded) {
202 printf("Failed to allocate decode output buffer. \n");
203 } else {
204 base64_decode(json_object_get_string(encoded),
205 json_object_get_string_len(encoded), decoded,
206 &decoded_len, 0);
207 memcpy(section_cper->ContextEntry, decoded, decoded_len);
208 free(decoded);
209 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100210
Lawrence Tange407b4c2022-07-21 13:54:01 +0100211 //Page table entries.
212 section_cper->PteL1 = json_object_get_uint64(
213 json_object_object_get(section, "pageTableEntry_Level1"));
214 section_cper->PteL2 = json_object_get_uint64(
215 json_object_object_get(section, "pageTableEntry_Level2"));
216 section_cper->PteL3 = json_object_get_uint64(
217 json_object_object_get(section, "pageTableEntry_Level3"));
218 section_cper->PteL4 = json_object_get_uint64(
219 json_object_object_get(section, "pageTableEntry_Level4"));
220 section_cper->PteL5 = json_object_get_uint64(
221 json_object_object_get(section, "pageTableEntry_Level5"));
222 section_cper->PteL6 = json_object_get_uint64(
223 json_object_object_get(section, "pageTableEntry_Level6"));
224
225 //Write to stream, free resources.
226 fwrite(section_cper, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA), 1, out);
227 fflush(out);
228 free(section_cper);
John Chungf8fc7052024-05-03 20:05:29 +0800229}