blob: 8713d038ad926e7b399209962a6b32ccb2060384 [file] [log] [blame]
Lawrence Tang1b0b00e2022-07-05 10:33:10 +01001/**
Lawrence Tang2800cd82022-07-05 16:08:20 +01002 * Describes high level functions for converting an entire CPER log, and functions for parsing
3 * CPER headers and section descriptions into an intermediate JSON format.
Lawrence Tang1b0b00e2022-07-05 10:33:10 +01004 *
5 * Author: Lawrence.Tang@arm.com
6 **/
7
8#include <stdio.h>
9#include "json.h"
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010010#include "b64.h"
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010011#include "edk/Cper.h"
12#include "cper-parse.h"
13#include "cper-utils.h"
14#include "sections/cper-section-generic.h"
Lawrence Tang794312c2022-07-05 14:46:10 +010015#include "sections/cper-section-ia32x64.h"
Lawrence Tang2800cd82022-07-05 16:08:20 +010016#include "sections/cper-section-arm.h"
Lawrence Tanga0865e32022-07-06 11:59:52 +010017#include "sections/cper-section-memory.h"
Lawrence Tang4dbe3d72022-07-06 13:51:01 +010018#include "sections/cper-section-pcie.h"
Lawrence Tang214a1542022-07-06 14:11:28 +010019#include "sections/cper-section-pci-bus.h"
Lawrence Tanga416ec92022-07-06 14:34:40 +010020#include "sections/cper-section-pci-dev.h"
Lawrence Tangc60a2432022-07-06 14:58:33 +010021#include "sections/cper-section-firmware.h"
Lawrence Tang4795d4a2022-07-06 15:19:31 +010022#include "sections/cper-section-dmar-generic.h"
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010023#include "sections/cper-section-dmar-vtd.h"
24#include "sections/cper-section-dmar-iommu.h"
Lawrence Tang864c0da2022-07-06 15:55:40 +010025#include "sections/cper-section-ccix-per.h"
Lawrence Tangb98ec662022-07-06 16:50:21 +010026#include "sections/cper-section-cxl-protocol.h"
Lawrence Tangcc0f5f32022-07-06 17:17:26 +010027#include "sections/cper-section-ipf.h"
Lawrence Tangd7e8ca32022-07-07 10:25:53 +010028#include "sections/cper-section-cxl-component.h"
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010029
30//Private pre-definitions.
Lawrence Tange407b4c2022-07-21 13:54:01 +010031json_object *cper_header_to_ir(EFI_COMMON_ERROR_RECORD_HEADER *header);
32json_object *
33cper_section_descriptor_to_ir(EFI_ERROR_SECTION_DESCRIPTOR *section_descriptor);
34json_object *cper_section_to_ir(FILE *handle,
35 EFI_ERROR_SECTION_DESCRIPTOR *descriptor);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010036
37//Reads a CPER log file at the given file location, and returns an intermediate
38//JSON representation of this CPER record.
Lawrence Tange407b4c2022-07-21 13:54:01 +010039json_object *cper_to_ir(FILE *cper_file)
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010040{
Lawrence Tange407b4c2022-07-21 13:54:01 +010041 //Ensure this is really a CPER log.
42 EFI_COMMON_ERROR_RECORD_HEADER header;
43 fseek(cper_file, 0, SEEK_SET);
44 if (fread(&header, sizeof(EFI_COMMON_ERROR_RECORD_HEADER), 1,
45 cper_file) != 1) {
46 printf("Invalid CPER file: Invalid length (log too short).\n");
47 return NULL;
48 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010049
Lawrence Tange407b4c2022-07-21 13:54:01 +010050 //Check if the header contains the magic bytes ("CPER").
51 if (header.SignatureStart != EFI_ERROR_RECORD_SIGNATURE_START) {
52 printf("Invalid CPER file: Invalid header (incorrect signature).\n");
53 return NULL;
54 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010055
Lawrence Tange407b4c2022-07-21 13:54:01 +010056 //Create the header JSON object from the read bytes.
57 json_object *header_ir = cper_header_to_ir(&header);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010058
Lawrence Tange407b4c2022-07-21 13:54:01 +010059 //Read the appropriate number of section descriptors & sections, and convert them into IR format.
60 json_object *section_descriptors_ir = json_object_new_array();
61 json_object *sections_ir = json_object_new_array();
62 for (int i = 0; i < header.SectionCount; i++) {
63 //Create the section descriptor.
64 EFI_ERROR_SECTION_DESCRIPTOR section_descriptor;
65 if (fread(&section_descriptor,
66 sizeof(EFI_ERROR_SECTION_DESCRIPTOR), 1,
67 cper_file) != 1) {
68 printf("Invalid number of section headers: Header states %d sections, could not read section %d.\n",
69 header.SectionCount, i + 1);
70 return NULL;
71 }
72 json_object_array_add(
73 section_descriptors_ir,
74 cper_section_descriptor_to_ir(&section_descriptor));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010075
Lawrence Tange407b4c2022-07-21 13:54:01 +010076 //Read the section itself.
77 json_object_array_add(sections_ir,
78 cper_section_to_ir(cper_file,
79 &section_descriptor));
80 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010081
Lawrence Tange407b4c2022-07-21 13:54:01 +010082 //Add the header, section descriptors, and sections to a parent object.
83 json_object *parent = json_object_new_object();
84 json_object_object_add(parent, "header", header_ir);
85 json_object_object_add(parent, "sectionDescriptors",
86 section_descriptors_ir);
87 json_object_object_add(parent, "sections", sections_ir);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010088
Lawrence Tange407b4c2022-07-21 13:54:01 +010089 return parent;
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010090}
91
92//Converts a parsed CPER record header into intermediate JSON object format.
Lawrence Tange407b4c2022-07-21 13:54:01 +010093json_object *cper_header_to_ir(EFI_COMMON_ERROR_RECORD_HEADER *header)
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010094{
Lawrence Tange407b4c2022-07-21 13:54:01 +010095 json_object *header_ir = json_object_new_object();
Lawrence Tang1b0b00e2022-07-05 10:33:10 +010096
Lawrence Tange407b4c2022-07-21 13:54:01 +010097 //Revision/version information.
98 json_object_object_add(header_ir, "revision",
99 revision_to_ir(header->Revision));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100100
Lawrence Tange407b4c2022-07-21 13:54:01 +0100101 //Section count.
102 json_object_object_add(header_ir, "sectionCount",
103 json_object_new_int(header->SectionCount));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100104
Lawrence Tange407b4c2022-07-21 13:54:01 +0100105 //Error severity (with interpreted string version).
106 json_object *error_severity = json_object_new_object();
107 json_object_object_add(error_severity, "code",
108 json_object_new_uint64(header->ErrorSeverity));
109 json_object_object_add(error_severity, "name",
110 json_object_new_string(severity_to_string(
111 header->ErrorSeverity)));
112 json_object_object_add(header_ir, "severity", error_severity);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100113
Lawrence Tange407b4c2022-07-21 13:54:01 +0100114 //The validation bits for each section.
115 json_object *validation_bits = bitfield_to_ir(
116 header->ValidationBits, 3, CPER_HEADER_VALID_BITFIELD_NAMES);
117 json_object_object_add(header_ir, "validationBits", validation_bits);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100118
Lawrence Tange407b4c2022-07-21 13:54:01 +0100119 //Total length of the record (including headers) in bytes.
120 json_object_object_add(header_ir, "recordLength",
121 json_object_new_uint64(header->RecordLength));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100122
Lawrence Tange407b4c2022-07-21 13:54:01 +0100123 //If a timestamp exists according to validation bits, then add it.
124 if (header->ValidationBits & 0b10) {
125 char timestamp_string[TIMESTAMP_LENGTH];
126 timestamp_to_string(timestamp_string, &header->TimeStamp);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100127
Lawrence Tange407b4c2022-07-21 13:54:01 +0100128 json_object_object_add(
129 header_ir, "timestamp",
130 json_object_new_string(timestamp_string));
131 json_object_object_add(
132 header_ir, "timestampIsPrecise",
133 json_object_new_boolean(header->TimeStamp.Flag));
134 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100135
Lawrence Tange407b4c2022-07-21 13:54:01 +0100136 //If a platform ID exists according to the validation bits, then add it.
137 if (header->ValidationBits & 0b1) {
138 char platform_string[GUID_STRING_LENGTH];
139 guid_to_string(platform_string, &header->PlatformID);
140 json_object_object_add(header_ir, "platformID",
141 json_object_new_string(platform_string));
142 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100143
Lawrence Tange407b4c2022-07-21 13:54:01 +0100144 //If a partition ID exists according to the validation bits, then add it.
145 if (header->ValidationBits & 0b100) {
146 char partition_string[GUID_STRING_LENGTH];
147 guid_to_string(partition_string, &header->PartitionID);
148 json_object_object_add(
149 header_ir, "partitionID",
150 json_object_new_string(partition_string));
151 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100152
Lawrence Tange407b4c2022-07-21 13:54:01 +0100153 //Creator ID of the header.
154 char creator_string[GUID_STRING_LENGTH];
155 guid_to_string(creator_string, &header->CreatorID);
156 json_object_object_add(header_ir, "creatorID",
157 json_object_new_string(creator_string));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100158
Lawrence Tange407b4c2022-07-21 13:54:01 +0100159 //Notification type for the header. Some defined types are available.
160 json_object *notification_type = json_object_new_object();
161 char notification_type_string[GUID_STRING_LENGTH];
162 guid_to_string(notification_type_string, &header->NotificationType);
163 json_object_object_add(
164 notification_type, "guid",
165 json_object_new_string(notification_type_string));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100166
Lawrence Tange407b4c2022-07-21 13:54:01 +0100167 //Add the human readable notification type if possible.
168 char *notification_type_readable = "Unknown";
169 if (guid_equal(&header->NotificationType,
170 &gEfiEventNotificationTypeCmcGuid))
171 notification_type_readable = "CMC";
172 else if (guid_equal(&header->NotificationType,
173 &gEfiEventNotificationTypeCpeGuid))
174 notification_type_readable = "CPE";
175 else if (guid_equal(&header->NotificationType,
176 &gEfiEventNotificationTypeMceGuid))
177 notification_type_readable = "MCE";
178 else if (guid_equal(&header->NotificationType,
179 &gEfiEventNotificationTypePcieGuid))
180 notification_type_readable = "PCIe";
181 else if (guid_equal(&header->NotificationType,
182 &gEfiEventNotificationTypeInitGuid))
183 notification_type_readable = "INIT";
184 else if (guid_equal(&header->NotificationType,
185 &gEfiEventNotificationTypeNmiGuid))
186 notification_type_readable = "NMI";
187 else if (guid_equal(&header->NotificationType,
188 &gEfiEventNotificationTypeBootGuid))
189 notification_type_readable = "Boot";
190 else if (guid_equal(&header->NotificationType,
191 &gEfiEventNotificationTypeDmarGuid))
192 notification_type_readable = "DMAr";
193 else if (guid_equal(&header->NotificationType,
194 &gEfiEventNotificationTypeSeaGuid))
195 notification_type_readable = "SEA";
196 else if (guid_equal(&header->NotificationType,
197 &gEfiEventNotificationTypeSeiGuid))
198 notification_type_readable = "SEI";
199 else if (guid_equal(&header->NotificationType,
200 &gEfiEventNotificationTypePeiGuid))
201 notification_type_readable = "PEI";
202 else if (guid_equal(&header->NotificationType,
203 &gEfiEventNotificationTypeCxlGuid))
204 notification_type_readable = "CXL Component";
205 json_object_object_add(
206 notification_type, "type",
207 json_object_new_string(notification_type_readable));
208 json_object_object_add(header_ir, "notificationType",
209 notification_type);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100210
Lawrence Tange407b4c2022-07-21 13:54:01 +0100211 //The record ID for this record, unique on a given system.
212 json_object_object_add(header_ir, "recordID",
213 json_object_new_uint64(header->RecordID));
214
215 //Flag for the record, and a human readable form.
216 json_object *flags = integer_to_readable_pair(
217 header->Flags,
218 sizeof(CPER_HEADER_FLAG_TYPES_KEYS) / sizeof(int),
219 CPER_HEADER_FLAG_TYPES_KEYS, CPER_HEADER_FLAG_TYPES_VALUES,
220 "Unknown");
221 json_object_object_add(header_ir, "flags", flags);
222
223 //Persistence information. Outside the scope of specification, so just a uint32 here.
224 json_object_object_add(header_ir, "persistenceInfo",
225 json_object_new_uint64(header->PersistenceInfo));
226 return header_ir;
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100227}
228
229//Converts the given EFI section descriptor into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100230json_object *
231cper_section_descriptor_to_ir(EFI_ERROR_SECTION_DESCRIPTOR *section_descriptor)
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100232{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100233 json_object *section_descriptor_ir = json_object_new_object();
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100234
Lawrence Tange407b4c2022-07-21 13:54:01 +0100235 //The offset of the section from the base of the record header, length.
236 json_object_object_add(
237 section_descriptor_ir, "sectionOffset",
238 json_object_new_uint64(section_descriptor->SectionOffset));
239 json_object_object_add(
240 section_descriptor_ir, "sectionLength",
241 json_object_new_uint64(section_descriptor->SectionLength));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100242
Lawrence Tange407b4c2022-07-21 13:54:01 +0100243 //Revision.
244 json_object_object_add(section_descriptor_ir, "revision",
245 revision_to_ir(section_descriptor->Revision));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100246
Lawrence Tange407b4c2022-07-21 13:54:01 +0100247 //Validation bits.
248 json_object *validation_bits =
249 bitfield_to_ir(section_descriptor->SecValidMask, 2,
250 CPER_SECTION_DESCRIPTOR_VALID_BITFIELD_NAMES);
251 json_object_object_add(section_descriptor_ir, "validationBits",
252 validation_bits);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100253
Lawrence Tange407b4c2022-07-21 13:54:01 +0100254 //Flag bits.
255 json_object *flags =
256 bitfield_to_ir(section_descriptor->SectionFlags, 8,
257 CPER_SECTION_DESCRIPTOR_FLAGS_BITFIELD_NAMES);
258 json_object_object_add(section_descriptor_ir, "flags", flags);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100259
Lawrence Tange407b4c2022-07-21 13:54:01 +0100260 //Section type (GUID).
261 json_object *section_type = json_object_new_object();
262 char section_type_string[GUID_STRING_LENGTH];
263 guid_to_string(section_type_string, &section_descriptor->SectionType);
264 json_object_object_add(section_type, "data",
265 json_object_new_string(section_type_string));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100266
Lawrence Tange407b4c2022-07-21 13:54:01 +0100267 //Readable section type, if possible.
268 char *section_type_readable = "Unknown";
269 if (guid_equal(&section_descriptor->SectionType,
270 &gEfiProcessorGenericErrorSectionGuid))
271 section_type_readable = "Processor Generic";
272 else if (guid_equal(&section_descriptor->SectionType,
273 &gEfiIa32X64ProcessorErrorSectionGuid))
274 section_type_readable = "IA32/X64";
275 else if (guid_equal(&section_descriptor->SectionType,
276 &gEfiIpfProcessorErrorSectionGuid))
277 section_type_readable = "IPF";
278 else if (guid_equal(&section_descriptor->SectionType,
279 &gEfiArmProcessorErrorSectionGuid))
280 section_type_readable = "ARM";
281 else if (guid_equal(&section_descriptor->SectionType,
282 &gEfiPlatformMemoryErrorSectionGuid) ||
283 guid_equal(&section_descriptor->SectionType,
284 &gEfiPlatformMemoryError2SectionGuid))
285 section_type_readable = "Platform Memory";
286 else if (guid_equal(&section_descriptor->SectionType,
287 &gEfiPcieErrorSectionGuid))
288 section_type_readable = "PCIe";
289 else if (guid_equal(&section_descriptor->SectionType,
290 &gEfiFirmwareErrorSectionGuid))
291 section_type_readable = "Firmware Error Record Reference";
292 else if (guid_equal(&section_descriptor->SectionType,
293 &gEfiPciBusErrorSectionGuid))
294 section_type_readable = "PCI/PCI-X Bus";
295 else if (guid_equal(&section_descriptor->SectionType,
296 &gEfiPciDevErrorSectionGuid))
297 section_type_readable = "PCI Component/Device";
298 else if (guid_equal(&section_descriptor->SectionType,
299 &gEfiDMArGenericErrorSectionGuid))
300 section_type_readable = "DMAr Generic";
301 else if (guid_equal(&section_descriptor->SectionType,
302 &gEfiDirectedIoDMArErrorSectionGuid))
303 section_type_readable =
304 "Intel VT for Directed I/O specific DMAr section";
305 else if (guid_equal(&section_descriptor->SectionType,
306 &gEfiIommuDMArErrorSectionGuid))
307 section_type_readable = "IOMMU specific DMAr section";
308 else if (guid_equal(&section_descriptor->SectionType,
309 &gEfiCcixPerLogErrorSectionGuid))
310 section_type_readable = "CCIX PER Log Error";
311 else if (guid_equal(&section_descriptor->SectionType,
312 &gEfiCxlProtocolErrorSectionGuid))
313 section_type_readable = "CXL Protocol Error";
314 else if (guid_equal(&section_descriptor->SectionType,
315 &gEfiCxlGeneralMediaErrorSectionGuid))
316 section_type_readable = "CXL General Media Component Error";
317 else if (guid_equal(&section_descriptor->SectionType,
318 &gEfiCxlDramEventErrorSectionGuid))
319 section_type_readable = "CXL DRAM Component Error";
320 else if (guid_equal(&section_descriptor->SectionType,
321 &gEfiCxlPhysicalSwitchErrorSectionGuid))
322 section_type_readable = "CXL Physical Switch Component Error";
323 else if (guid_equal(&section_descriptor->SectionType,
324 &gEfiCxlVirtualSwitchErrorSectionGuid))
325 section_type_readable = "CXL Virtual Switch Component Error";
326 else if (guid_equal(&section_descriptor->SectionType,
327 &gEfiCxlMldPortErrorSectionGuid))
328 section_type_readable = "CXL MLD Port Component Error";
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100329
Lawrence Tange407b4c2022-07-21 13:54:01 +0100330 json_object_object_add(section_type, "type",
331 json_object_new_string(section_type_readable));
332 json_object_object_add(section_descriptor_ir, "sectionType",
333 section_type);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100334
Lawrence Tange407b4c2022-07-21 13:54:01 +0100335 //If validation bits indicate it exists, add FRU ID.
336 if (section_descriptor->SecValidMask & 0b1) {
337 char fru_id_string[GUID_STRING_LENGTH];
338 guid_to_string(fru_id_string, &section_descriptor->FruId);
339 json_object_object_add(section_descriptor_ir, "fruID",
340 json_object_new_string(fru_id_string));
341 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100342
Lawrence Tange407b4c2022-07-21 13:54:01 +0100343 //If validation bits indicate it exists, add FRU text.
344 if ((section_descriptor->SecValidMask & 0b10) >> 1)
345 json_object_object_add(
346 section_descriptor_ir, "fruText",
347 json_object_new_string(section_descriptor->FruString));
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100348
Lawrence Tange407b4c2022-07-21 13:54:01 +0100349 //Section severity.
350 json_object *section_severity = json_object_new_object();
351 json_object_object_add(
352 section_severity, "code",
353 json_object_new_uint64(section_descriptor->Severity));
354 json_object_object_add(section_severity, "name",
355 json_object_new_string(severity_to_string(
356 section_descriptor->Severity)));
357 json_object_object_add(section_descriptor_ir, "severity",
358 section_severity);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100359
Lawrence Tange407b4c2022-07-21 13:54:01 +0100360 return section_descriptor_ir;
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100361}
362
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100363//Converts the section described by a single given section descriptor.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100364json_object *cper_section_to_ir(FILE *handle,
365 EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100366{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100367 //Save our current position in the stream.
368 long position = ftell(handle);
Lawrence Tangde9707f2022-07-19 10:54:31 +0100369
Lawrence Tange407b4c2022-07-21 13:54:01 +0100370 //Read section as described by the section descriptor.
371 fseek(handle, descriptor->SectionOffset, SEEK_SET);
372 void *section = malloc(descriptor->SectionLength);
373 if (fread(section, descriptor->SectionLength, 1, handle) != 1) {
374 printf("Section read failed: Could not read %d bytes from global offset %d.\n",
375 descriptor->SectionLength, descriptor->SectionOffset);
376 free(section);
377 return NULL;
378 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100379
Lawrence Tange407b4c2022-07-21 13:54:01 +0100380 //Seek back to our original position.
381 fseek(handle, position, SEEK_SET);
Lawrence Tangde9707f2022-07-19 10:54:31 +0100382
Lawrence Tange407b4c2022-07-21 13:54:01 +0100383 //Parse section to IR based on GUID.
384 json_object *result = NULL;
385 if (guid_equal(&descriptor->SectionType,
386 &gEfiProcessorGenericErrorSectionGuid))
387 result = cper_section_generic_to_ir(section, descriptor);
388 else if (guid_equal(&descriptor->SectionType,
389 &gEfiIa32X64ProcessorErrorSectionGuid))
390 result = cper_section_ia32x64_to_ir(section, descriptor);
391 else if (guid_equal(&descriptor->SectionType,
392 &gEfiIpfProcessorErrorSectionGuid))
393 result = cper_section_ipf_to_ir(section, descriptor);
394 else if (guid_equal(&descriptor->SectionType,
395 &gEfiArmProcessorErrorSectionGuid))
396 result = cper_section_arm_to_ir(section, descriptor);
397 else if (guid_equal(&descriptor->SectionType,
398 &gEfiPlatformMemoryErrorSectionGuid))
399 result =
400 cper_section_platform_memory_to_ir(section, descriptor);
401 else if (guid_equal(&descriptor->SectionType,
402 &gEfiPlatformMemoryError2SectionGuid))
403 result = cper_section_platform_memory2_to_ir(section,
404 descriptor);
405 else if (guid_equal(&descriptor->SectionType,
406 &gEfiPcieErrorSectionGuid))
407 result = cper_section_pcie_to_ir(section, descriptor);
408 else if (guid_equal(&descriptor->SectionType,
409 &gEfiFirmwareErrorSectionGuid))
410 result = cper_section_firmware_to_ir(section, descriptor);
411 else if (guid_equal(&descriptor->SectionType,
412 &gEfiPciBusErrorSectionGuid))
413 result = cper_section_pci_bus_to_ir(section, descriptor);
414 else if (guid_equal(&descriptor->SectionType,
415 &gEfiPciDevErrorSectionGuid))
416 result = cper_section_pci_dev_to_ir(section, descriptor);
417 else if (guid_equal(&descriptor->SectionType,
418 &gEfiDMArGenericErrorSectionGuid))
419 result = cper_section_dmar_generic_to_ir(section, descriptor);
420 else if (guid_equal(&descriptor->SectionType,
421 &gEfiDirectedIoDMArErrorSectionGuid))
422 result = cper_section_dmar_vtd_to_ir(section, descriptor);
423 else if (guid_equal(&descriptor->SectionType,
424 &gEfiIommuDMArErrorSectionGuid))
425 result = cper_section_dmar_iommu_to_ir(section, descriptor);
426 else if (guid_equal(&descriptor->SectionType,
427 &gEfiCcixPerLogErrorSectionGuid))
428 result = cper_section_ccix_per_to_ir(section, descriptor);
429 else if (guid_equal(&descriptor->SectionType,
430 &gEfiCxlProtocolErrorSectionGuid))
431 result = cper_section_cxl_protocol_to_ir(section, descriptor);
432 else if (guid_equal(&descriptor->SectionType,
433 &gEfiCxlGeneralMediaErrorSectionGuid) ||
434 guid_equal(&descriptor->SectionType,
435 &gEfiCxlDramEventErrorSectionGuid) ||
436 guid_equal(&descriptor->SectionType,
437 &gEfiCxlPhysicalSwitchErrorSectionGuid) ||
438 guid_equal(&descriptor->SectionType,
439 &gEfiCxlVirtualSwitchErrorSectionGuid) ||
440 guid_equal(&descriptor->SectionType,
441 &gEfiCxlMldPortErrorSectionGuid)) {
442 result = cper_section_cxl_component_to_ir(section, descriptor);
443 } else {
444 //Failed read, unknown GUID.
445 //Output the data as formatted base64.
446 result = json_object_new_object();
447 char *encoded = b64_encode((unsigned char *)section,
448 descriptor->SectionLength);
449 json_object_object_add(result, "data",
450 json_object_new_string(encoded));
451 free(encoded);
452 }
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100453
Lawrence Tange407b4c2022-07-21 13:54:01 +0100454 //Free section memory, return result.
455 free(section);
456 return result;
Lawrence Tang617949e2022-08-08 14:21:42 +0100457}
458
459//Converts a single CPER section, without a header but with a section descriptor, to JSON.
460json_object *cper_single_section_to_ir(FILE *cper_section_file)
461{
462 json_object *ir = json_object_new_object();
463
464 //Read the section descriptor out.
465 EFI_ERROR_SECTION_DESCRIPTOR section_descriptor;
466 if (fread(&section_descriptor, sizeof(EFI_ERROR_SECTION_DESCRIPTOR), 1,
467 cper_section_file) != 1) {
468 printf("Failed to read section descriptor for CPER single section (fread() returned an unexpected value).\n");
469 return NULL;
470 }
471
472 //Convert the section descriptor to IR.
473 json_object *section_descriptor_ir =
474 cper_section_descriptor_to_ir(&section_descriptor);
475 json_object_object_add(ir, "sectionDescriptor", section_descriptor_ir);
476
477 //Parse the single section.
478 json_object *section_ir =
479 cper_section_to_ir(cper_section_file, &section_descriptor);
480 json_object_object_add(ir, "section", section_ir);
481
482 return ir;
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100483}