blob: 73fb2fc26f17cb574943743e71f735479ae3f8f4 [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 Tangdb1b7ce2022-07-06 15:40:26 +01009#include "json.h"
Lawrence Tangce0f82b2022-07-07 16:14:28 +010010#include "b64.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.
Lawrence Tange407b4c2022-07-21 13:54:01 +010016json_object *
17cper_section_dmar_vtd_to_ir(void *section,
18 EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010019{
Lawrence Tange407b4c2022-07-21 13:54:01 +010020 EFI_DIRECTED_IO_DMAR_ERROR_DATA *vtd_error =
21 (EFI_DIRECTED_IO_DMAR_ERROR_DATA *)section;
22 json_object *section_ir = json_object_new_object();
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010023
Lawrence Tange407b4c2022-07-21 13:54:01 +010024 //Version, revision and OEM ID, as defined in the VT-d architecture.
25 UINT64 oem_id = 0;
26 for (int i = 0; i < 6; i++)
27 oem_id |= (UINT64)vtd_error->OemId[i] << (i * 8);
28 json_object_object_add(section_ir, "version",
29 json_object_new_int(vtd_error->Version));
30 json_object_object_add(section_ir, "revision",
31 json_object_new_int(vtd_error->Revision));
32 json_object_object_add(section_ir, "oemID",
33 json_object_new_uint64(oem_id));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010034
Lawrence Tange407b4c2022-07-21 13:54:01 +010035 //Registers.
36 json_object_object_add(section_ir, "capabilityRegister",
37 json_object_new_uint64(vtd_error->Capability));
38 json_object_object_add(section_ir, "extendedCapabilityRegister",
39 json_object_new_uint64(vtd_error->CapabilityEx));
40 json_object_object_add(
41 section_ir, "globalCommandRegister",
42 json_object_new_uint64(vtd_error->GlobalCommand));
43 json_object_object_add(section_ir, "globalStatusRegister",
44 json_object_new_uint64(vtd_error->GlobalStatus));
45 json_object_object_add(section_ir, "faultStatusRegister",
46 json_object_new_uint64(vtd_error->FaultStatus));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010047
Lawrence Tange407b4c2022-07-21 13:54:01 +010048 //Fault record basic fields.
49 json_object *fault_record_ir = json_object_new_object();
50 EFI_VTD_FAULT_RECORD *fault_record =
51 (EFI_VTD_FAULT_RECORD *)vtd_error->FaultRecord;
52 json_object_object_add(
53 fault_record_ir, "faultInformation",
54 json_object_new_uint64(fault_record->FaultInformation));
55 json_object_object_add(
56 fault_record_ir, "sourceIdentifier",
57 json_object_new_uint64(fault_record->SourceIdentifier));
58 json_object_object_add(
59 fault_record_ir, "privelegeModeRequested",
60 json_object_new_boolean(fault_record->PrivelegeModeRequested));
61 json_object_object_add(
62 fault_record_ir, "executePermissionRequested",
63 json_object_new_boolean(
64 fault_record->ExecutePermissionRequested));
65 json_object_object_add(
66 fault_record_ir, "pasidPresent",
67 json_object_new_boolean(fault_record->PasidPresent));
68 json_object_object_add(
69 fault_record_ir, "faultReason",
70 json_object_new_uint64(fault_record->FaultReason));
71 json_object_object_add(
72 fault_record_ir, "pasidValue",
73 json_object_new_uint64(fault_record->PasidValue));
74 json_object_object_add(
75 fault_record_ir, "addressType",
76 json_object_new_uint64(fault_record->AddressType));
Lawrence Tangce0f82b2022-07-07 16:14:28 +010077
Lawrence Tange407b4c2022-07-21 13:54:01 +010078 //Fault record type.
79 json_object *fault_record_type = integer_to_readable_pair(
80 fault_record->Type, 2, VTD_FAULT_RECORD_TYPES_KEYS,
81 VTD_FAULT_RECORD_TYPES_VALUES, "Unknown");
82 json_object_object_add(fault_record_ir, "type", fault_record_type);
83 json_object_object_add(section_ir, "faultRecord", fault_record_ir);
Lawrence Tangce0f82b2022-07-07 16:14:28 +010084
Lawrence Tange407b4c2022-07-21 13:54:01 +010085 //Root entry.
86 char *encoded = b64_encode((unsigned char *)vtd_error->RootEntry, 16);
87 json_object_object_add(section_ir, "rootEntry",
88 json_object_new_string(encoded));
89 free(encoded);
Lawrence Tangce0f82b2022-07-07 16:14:28 +010090
Lawrence Tange407b4c2022-07-21 13:54:01 +010091 //Context entry.
92 encoded = b64_encode((unsigned char *)vtd_error->ContextEntry, 16);
93 json_object_object_add(section_ir, "contextEntry",
94 json_object_new_string(encoded));
95 free(encoded);
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010096
Lawrence Tange407b4c2022-07-21 13:54:01 +010097 //PTE entry for all page levels.
98 json_object_object_add(section_ir, "pageTableEntry_Level6",
99 json_object_new_uint64(vtd_error->PteL6));
100 json_object_object_add(section_ir, "pageTableEntry_Level5",
101 json_object_new_uint64(vtd_error->PteL5));
102 json_object_object_add(section_ir, "pageTableEntry_Level4",
103 json_object_new_uint64(vtd_error->PteL4));
104 json_object_object_add(section_ir, "pageTableEntry_Level3",
105 json_object_new_uint64(vtd_error->PteL3));
106 json_object_object_add(section_ir, "pageTableEntry_Level2",
107 json_object_new_uint64(vtd_error->PteL2));
108 json_object_object_add(section_ir, "pageTableEntry_Level1",
109 json_object_new_uint64(vtd_error->PteL1));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +0100110
Lawrence Tange407b4c2022-07-21 13:54:01 +0100111 return section_ir;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100112}
113
114//Converts a single VT-d DMAR CPER-JSON segment into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100115void ir_section_dmar_vtd_to_cper(json_object *section, FILE *out)
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100116{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100117 EFI_DIRECTED_IO_DMAR_ERROR_DATA *section_cper =
118 (EFI_DIRECTED_IO_DMAR_ERROR_DATA *)calloc(
119 1, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100120
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 //OEM ID.
122 UINT64 oem_id = json_object_get_uint64(
123 json_object_object_get(section, "oemID"));
124 for (int i = 0; i < 6; i++)
125 section_cper->OemId[i] = (oem_id >> (i * 8)) & 0xFF;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100126
Lawrence Tange407b4c2022-07-21 13:54:01 +0100127 //Registers & basic numeric fields.
128 section_cper->Version = (UINT8)json_object_get_int(
129 json_object_object_get(section, "version"));
130 section_cper->Revision = (UINT8)json_object_get_int(
131 json_object_object_get(section, "revision"));
132 section_cper->Capability = json_object_get_uint64(
133 json_object_object_get(section, "capabilityRegister"));
134 section_cper->CapabilityEx = json_object_get_uint64(
135 json_object_object_get(section, "extendedCapabilityRegister"));
136 section_cper->GlobalCommand = json_object_get_uint64(
137 json_object_object_get(section, "globalCommandRegister"));
138 section_cper->GlobalStatus = json_object_get_uint64(
139 json_object_object_get(section, "globalStatusRegister"));
140 section_cper->FaultStatus = json_object_get_uint64(
141 json_object_object_get(section, "faultStatusRegister"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100142
Lawrence Tange407b4c2022-07-21 13:54:01 +0100143 //Fault record.
144 json_object *fault_record =
145 json_object_object_get(section, "faultRecord");
146 EFI_VTD_FAULT_RECORD *fault_record_cper =
147 (EFI_VTD_FAULT_RECORD *)section_cper->FaultRecord;
148 fault_record_cper->FaultInformation = json_object_get_uint64(
149 json_object_object_get(fault_record, "faultInformation"));
150 fault_record_cper->SourceIdentifier = json_object_get_uint64(
151 json_object_object_get(fault_record, "sourceIdentifier"));
152 fault_record_cper->PrivelegeModeRequested = json_object_get_boolean(
153 json_object_object_get(fault_record, "privelegeModeRequested"));
154 fault_record_cper->ExecutePermissionRequested = json_object_get_boolean(
155 json_object_object_get(fault_record,
156 "executePermissionRequested"));
157 fault_record_cper->PasidPresent = json_object_get_boolean(
158 json_object_object_get(fault_record, "pasidPresent"));
159 fault_record_cper->FaultReason = json_object_get_uint64(
160 json_object_object_get(fault_record, "faultReason"));
161 fault_record_cper->PasidValue = json_object_get_uint64(
162 json_object_object_get(fault_record, "pasidValue"));
163 fault_record_cper->AddressType = json_object_get_uint64(
164 json_object_object_get(fault_record, "addressType"));
165 fault_record_cper->Type = readable_pair_to_integer(
166 json_object_object_get(fault_record, "type"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100167
Lawrence Tange407b4c2022-07-21 13:54:01 +0100168 //Root entry.
169 json_object *encoded = json_object_object_get(section, "rootEntry");
170 UINT8 *decoded = b64_decode(json_object_get_string(encoded),
171 json_object_get_string_len(encoded));
172 memcpy(section_cper->RootEntry, decoded, 16);
173 free(decoded);
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100174
Lawrence Tange407b4c2022-07-21 13:54:01 +0100175 //Context entry.
176 encoded = json_object_object_get(section, "contextEntry");
177 decoded = b64_decode(json_object_get_string(encoded),
178 json_object_get_string_len(encoded));
179 memcpy(section_cper->ContextEntry, decoded, 16);
180 free(decoded);
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100181
Lawrence Tange407b4c2022-07-21 13:54:01 +0100182 //Page table entries.
183 section_cper->PteL1 = json_object_get_uint64(
184 json_object_object_get(section, "pageTableEntry_Level1"));
185 section_cper->PteL2 = json_object_get_uint64(
186 json_object_object_get(section, "pageTableEntry_Level2"));
187 section_cper->PteL3 = json_object_get_uint64(
188 json_object_object_get(section, "pageTableEntry_Level3"));
189 section_cper->PteL4 = json_object_get_uint64(
190 json_object_object_get(section, "pageTableEntry_Level4"));
191 section_cper->PteL5 = json_object_get_uint64(
192 json_object_object_get(section, "pageTableEntry_Level5"));
193 section_cper->PteL6 = json_object_get_uint64(
194 json_object_object_get(section, "pageTableEntry_Level6"));
195
196 //Write to stream, free resources.
197 fwrite(section_cper, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA), 1, out);
198 fflush(out);
199 free(section_cper);
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +0100200}