blob: 80b5986a00ae10ca5fa4eb1b6cd5251ac6c11382 [file] [log] [blame]
Lawrence Tangf0f95572022-07-07 16:56:22 +01001/**
2 * Describes functions for parsing JSON IR CPER data into binary CPER format.
3 *
4 * Author: Lawrence.Tang@arm.com
5 **/
6
7#include <stdio.h>
Lawrence Tang0cb33792022-07-13 13:51:39 +01008#include <string.h>
Lawrence Tangf0f95572022-07-07 16:56:22 +01009#include "json.h"
Lawrence Tang0cb33792022-07-13 13:51:39 +010010#include "b64.h"
Lawrence Tangb44314c2022-07-13 11:45:22 +010011#include "edk/Cper.h"
Lawrence Tangf0f95572022-07-07 16:56:22 +010012#include "cper-parse.h"
Lawrence Tangb44314c2022-07-13 11:45:22 +010013#include "cper-utils.h"
Lawrence Tang0cb33792022-07-13 13:51:39 +010014#include "sections/cper-section-generic.h"
15#include "sections/cper-section-ia32x64.h"
16#include "sections/cper-section-arm.h"
17#include "sections/cper-section-memory.h"
18#include "sections/cper-section-pcie.h"
19#include "sections/cper-section-pci-bus.h"
20#include "sections/cper-section-pci-dev.h"
21#include "sections/cper-section-firmware.h"
22#include "sections/cper-section-dmar-generic.h"
23#include "sections/cper-section-dmar-vtd.h"
24#include "sections/cper-section-dmar-iommu.h"
25#include "sections/cper-section-ccix-per.h"
26#include "sections/cper-section-cxl-protocol.h"
27#include "sections/cper-section-ipf.h"
28#include "sections/cper-section-cxl-component.h"
Lawrence Tangb44314c2022-07-13 11:45:22 +010029
30//Private pre-declarations.
31void ir_header_to_cper(json_object* header_ir, EFI_COMMON_ERROR_RECORD_HEADER* header);
Lawrence Tang0cb33792022-07-13 13:51:39 +010032void ir_section_descriptor_to_cper(json_object* section_descriptor_ir, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
Lawrence Tangf0f95572022-07-07 16:56:22 +010033
34//Converts the given JSON IR CPER representation into CPER binary format, piped to the provided file stream.
Lawrence Tang0cb33792022-07-13 13:51:39 +010035//This function performs no validation of the IR against the CPER-JSON specification. To ensure a safe call,
36//use validate_schema() from json-schema.h before attempting to call this function.
Lawrence Tangf0f95572022-07-07 16:56:22 +010037void ir_to_cper(json_object* ir, FILE* out)
38{
Lawrence Tangb44314c2022-07-13 11:45:22 +010039 //Create the CPER header.
40 EFI_COMMON_ERROR_RECORD_HEADER* header = (EFI_COMMON_ERROR_RECORD_HEADER*)calloc(1, sizeof(EFI_COMMON_ERROR_RECORD_HEADER));
41 ir_header_to_cper(json_object_object_get(ir, "header"), header);
42 fwrite(header, sizeof(EFI_COMMON_ERROR_RECORD_HEADER), 1, out);
Lawrence Tangb44314c2022-07-13 11:45:22 +010043 fflush(out);
Lawrence Tang0cb33792022-07-13 13:51:39 +010044
45 //Create the CPER section descriptors.
46 json_object* section_descriptors = json_object_object_get(ir, "sectionDescriptors");
47 int amt_descriptors = json_object_array_length(section_descriptors);
48 EFI_ERROR_SECTION_DESCRIPTOR* descriptors[amt_descriptors];
49 for (int i=0; i<amt_descriptors; i++)
50 {
51 descriptors[i] = (EFI_ERROR_SECTION_DESCRIPTOR*)calloc(1, sizeof(EFI_ERROR_SECTION_DESCRIPTOR));
52 ir_section_descriptor_to_cper(json_object_array_get_idx(section_descriptors, i), descriptors[i]);
53 fwrite(descriptors[i], sizeof(EFI_ERROR_SECTION_DESCRIPTOR), 1, out);
54 fflush(out);
55 }
56
57 //Run through each section in turn.
58 json_object* sections = json_object_object_get(ir, "sections");
59 int amt_sections = json_object_array_length(sections);
60 for (int i=0; i<amt_sections; i++)
61 {
62 //Get the section itself from the IR.
63 json_object* section = json_object_array_get_idx(sections, i);
64
65 //Find the correct section type, and parse.
66 if (guid_equal(&descriptors[i]->SectionType, &gEfiProcessorGenericErrorSectionGuid))
67 ir_section_generic_to_cper(section, out);
Lawrence Tangd0c88842022-07-13 14:51:17 +010068 else if (guid_equal(&descriptors[i]->SectionType, &gEfiIa32X64ProcessorErrorSectionGuid))
69 ir_section_ia32x64_to_cper(section, out);
Lawrence Tang0cb33792022-07-13 13:51:39 +010070 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiIpfProcessorErrorSectionGuid))
71 // ir_section_ipf_to_cper(section, out);
Lawrence Tang71570a22022-07-14 11:45:28 +010072 else if (guid_equal(&descriptors[i]->SectionType, &gEfiArmProcessorErrorSectionGuid))
73 ir_section_arm_to_cper(section, out);
Lawrence Tang0cb33792022-07-13 13:51:39 +010074 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiPlatformMemoryErrorSectionGuid))
75 // ir_section_platform_memory_to_cper(section, out);
76 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiPlatformMemoryError2SectionGuid))
77 // ir_section_platform_memory2_to_cper(section, out);
78 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiPcieErrorSectionGuid))
79 // ir_section_pcie_to_cper(section, out);
80 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiFirmwareErrorSectionGuid))
81 // ir_section_firmware_to_cper(section, out);
82 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiPciBusErrorSectionGuid))
83 // ir_section_pci_bus_to_cper(section, out);
84 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiPciDevErrorSectionGuid))
85 // ir_section_pci_dev_to_cper(section, out);
86 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiDMArGenericErrorSectionGuid))
87 // ir_section_dmar_generic_to_cper(section, out);
88 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiDirectedIoDMArErrorSectionGuid))
89 // ir_section_dmar_vtd_to_cper(section, out);
90 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiIommuDMArErrorSectionGuid))
91 // ir_section_dmar_iommu_to_cper(section, out);
92 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiCcixPerLogErrorSectionGuid))
93 // ir_section_ccix_per_to_cper(section, out);
94 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiCxlProtocolErrorSectionGuid))
95 // ir_section_cxl_protocol_to_cper(section, out);
96 // else if (guid_equal(&descriptors[i]->SectionType, &gEfiCxlGeneralMediaErrorSectionGuid)
97 // || guid_equal(&descriptors[i]->SectionType, &gEfiCxlDramEventErrorSectionGuid)
98 // || guid_equal(&descriptors[i]->SectionType, &gEfiCxlPhysicalSwitchErrorSectionGuid)
99 // || guid_equal(&descriptors[i]->SectionType, &gEfiCxlVirtualSwitchErrorSectionGuid)
100 // || guid_equal(&descriptors[i]->SectionType, &gEfiCxlMldPortErrorSectionGuid))
101 // {
102 // ir_section_cxl_component_to_cper(section, out);
103 // }
104 else
105 {
106 //Unknown GUID, so read as a base64 unknown section.
107 json_object* encoded = json_object_object_get(section, "data");
108 UINT8* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded));
109 fwrite(decoded, descriptors[i]->SectionLength, 1, out);
110 fflush(out);
111 free(decoded);
112 }
113 }
114
115 //Free all remaining resources.
Lawrence Tangb44314c2022-07-13 11:45:22 +0100116 free(header);
Lawrence Tang0cb33792022-07-13 13:51:39 +0100117 for (int i=0; i<amt_descriptors; i++)
118 free(descriptors[i]);
Lawrence Tangb44314c2022-07-13 11:45:22 +0100119}
120
121//Converts a CPER-JSON IR header to a CPER header structure.
122void ir_header_to_cper(json_object* header_ir, EFI_COMMON_ERROR_RECORD_HEADER* header)
123{
124 header->SignatureStart = 0x52455043; //CPER
Lawrence Tangb44314c2022-07-13 11:45:22 +0100125
126 //Revision.
127 json_object* revision = json_object_object_get(header_ir, "revision");
128 int minor = json_object_get_int(json_object_object_get(revision, "minor"));
129 int major = json_object_get_int(json_object_object_get(revision, "major"));
130 header->Revision = minor + (major << 8);
131
132 header->SignatureEnd = 0xFFFFFFFF;
133
134 //Section count.
135 int section_count = json_object_get_int(json_object_object_get(header_ir, "sectionCount"));
136 header->SectionCount = (UINT16)section_count;
137
138 //Error severity.
139 json_object* severity = json_object_object_get(header_ir, "severity");
140 header->ErrorSeverity = (UINT32)json_object_get_uint64(json_object_object_get(severity, "code"));
141
142 //Validation bits.
143 header->ValidationBits = ir_to_bitfield(json_object_object_get(header_ir, "validationBits"),
144 3, CPER_HEADER_VALID_BITFIELD_NAMES);
145
146 //Record length.
147 header->RecordLength = (UINT32)json_object_get_uint64(json_object_object_get(header_ir, "recordLength"));
148
149 //Timestamp, if present.
Lawrence Tangb44314c2022-07-13 11:45:22 +0100150 json_object* timestamp = json_object_object_get(header_ir, "timestamp");
151 if (timestamp != NULL)
152 {
153 string_to_timestamp(&header->TimeStamp, json_object_get_string(timestamp));
154 header->TimeStamp.Flag = json_object_get_boolean(json_object_object_get(header_ir, "timestampIsPrecise"));
155 }
156
157 //Various GUIDs.
Lawrence Tangb44314c2022-07-13 11:45:22 +0100158 json_object* platform_id = json_object_object_get(header_ir, "platformID");
159 json_object* partition_id = json_object_object_get(header_ir, "partitionID");
160 if (platform_id != NULL)
161 string_to_guid(&header->PlatformID, json_object_get_string(platform_id));
162 if (partition_id != NULL)
163 string_to_guid(&header->PartitionID, json_object_get_string(partition_id));
164 string_to_guid(&header->CreatorID, json_object_get_string(json_object_object_get(header_ir, "creatorID")));
165
166 //Notification type.
Lawrence Tangb44314c2022-07-13 11:45:22 +0100167 json_object* notification_type = json_object_object_get(header_ir, "notificationType");
168 string_to_guid(&header->NotificationType, json_object_get_string(json_object_object_get(notification_type, "guid")));
169
170 //Record ID, persistence info.
171 header->RecordID = json_object_get_uint64(json_object_object_get(header_ir, "recordID"));
172 header->PersistenceInfo = json_object_get_uint64(json_object_object_get(header_ir, "persistenceInfo"));
173
174 //Flags.
Lawrence Tangb44314c2022-07-13 11:45:22 +0100175 json_object* flags = json_object_object_get(header_ir, "flags");
176 header->Flags = (UINT32)json_object_get_uint64(json_object_object_get(flags, "value"));
Lawrence Tang0cb33792022-07-13 13:51:39 +0100177}
178
179//Converts a single CPER-JSON IR section descriptor into a CPER structure.
180void ir_section_descriptor_to_cper(json_object* section_descriptor_ir, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
181{
182 //Section offset, length.
183 descriptor->SectionOffset = (UINT32)json_object_get_uint64(json_object_object_get(section_descriptor_ir, "sectionOffset"));
184 descriptor->SectionLength = (UINT32)json_object_get_uint64(json_object_object_get(section_descriptor_ir, "sectionLength"));
185
186 //Revision.
187 json_object* revision = json_object_object_get(section_descriptor_ir, "revision");
188 int minor = json_object_get_int(json_object_object_get(revision, "minor"));
189 int major = json_object_get_int(json_object_object_get(revision, "major"));
190 descriptor->Revision = minor + (major << 8);
191
192 //Validation bits, flags.
193 descriptor->SecValidMask = ir_to_bitfield(json_object_object_get(section_descriptor_ir, "validationBits"),
194 2, CPER_SECTION_DESCRIPTOR_VALID_BITFIELD_NAMES);
195 descriptor->SectionFlags = ir_to_bitfield(json_object_object_get(section_descriptor_ir, "flags"),
196 8, CPER_SECTION_DESCRIPTOR_FLAGS_BITFIELD_NAMES);
197
198 //Section type.
199 json_object* section_type = json_object_object_get(section_descriptor_ir, "sectionType");
200 string_to_guid(&descriptor->SectionType, json_object_get_string(json_object_object_get(section_type, "data")));
201
202 //FRU ID, if present.
203 json_object* fru_id = json_object_object_get(section_descriptor_ir, "fruID");
204 if (fru_id != NULL)
205 string_to_guid(&descriptor->FruId, json_object_get_string(fru_id));
206
207 //Severity code.
208 json_object* severity = json_object_object_get(section_descriptor_ir, "severity");
209 descriptor->Severity = (UINT32)json_object_get_uint64(json_object_object_get(severity, "code"));
210
211 //FRU text, if present.
212 json_object* fru_text = json_object_object_get(section_descriptor_ir, "fruText");
213 if (fru_text != NULL)
214 strncpy(descriptor->FruString, json_object_get_string(fru_text), 20);
Lawrence Tangf0f95572022-07-07 16:56:22 +0100215}