blob: 8e89ee3681350d1ecacb13dc227cc1a56f16ae44 [file] [log] [blame]
Lawrence Tang794312c2022-07-05 14:46:10 +01001/**
2 * Describes functions for converting IA32/x64 CPER sections from binary and JSON format
3 * into an intermediate format.
Ed Tanousfedd4572024-07-12 13:56:00 -07004 *
Lawrence Tang794312c2022-07-05 14:46:10 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7
8#include <stdio.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01009#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000010#include <libcper/base64.h>
11#include <libcper/Cper.h>
12#include <libcper/cper-utils.h>
13#include <libcper/sections/cper-section-ia32x64.h>
Lawrence Tang794312c2022-07-05 14:46:10 +010014
15//Private pre-definitions.
Lawrence Tange407b4c2022-07-21 13:54:01 +010016json_object *cper_ia32x64_processor_error_info_to_ir(
17 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info);
18json_object *cper_ia32x64_cache_tlb_check_to_ir(
19 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check);
20json_object *
21cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check);
22json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check);
23json_object *cper_ia32x64_processor_context_info_to_ir(
24 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos);
25json_object *
26cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers);
27json_object *
28cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers);
29void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out);
30void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out);
31void ir_ia32x64_cache_tlb_check_error_to_cper(
32 json_object *check_info,
33 EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper);
34void ir_ia32x64_bus_check_error_to_cper(
35 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper);
36void ir_ia32x64_ms_check_error_to_cper(
37 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper);
38void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out);
39void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out);
Lawrence Tangd0c88842022-07-13 14:51:17 +010040
41//////////////////
42/// CPER TO IR ///
43//////////////////
Lawrence Tang794312c2022-07-05 14:46:10 +010044
45//Converts the IA32/x64 error section described in the given descriptor into intermediate format.
John Chungf8fc7052024-05-03 20:05:29 +080046json_object *cper_section_ia32x64_to_ir(void *section)
Lawrence Tang794312c2022-07-05 14:46:10 +010047{
Lawrence Tange407b4c2022-07-21 13:54:01 +010048 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *record =
49 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)section;
50 json_object *record_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +010051
Lawrence Tange407b4c2022-07-21 13:54:01 +010052 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080053 //validation bits contain information
54 //about processorErrorInfoNum and processorContextInfoNum.
55 //Ensure this is decoded properly in IR->CPER
John Chungf8fc7052024-05-03 20:05:29 +080056 int processor_error_info_num = (record->ValidFields >> 2) & 0x3F;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080057 json_object_object_add(record_ir, "processorErrorInfoNum",
Lawrence Tange407b4c2022-07-21 13:54:01 +010058 json_object_new_int(processor_error_info_num));
John Chungf8fc7052024-05-03 20:05:29 +080059 int processor_context_info_num = (record->ValidFields >> 8) & 0x3F;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080060 json_object_object_add(record_ir, "processorContextInfoNum",
Lawrence Tange407b4c2022-07-21 13:54:01 +010061 json_object_new_int(processor_context_info_num));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080062
63 ValidationTypes ui64Type = { UINT_64T,
64 .value.ui64 = record->ValidFields };
Lawrence Tang794312c2022-07-05 14:46:10 +010065
Lawrence Tange407b4c2022-07-21 13:54:01 +010066 //APIC ID.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080067 if (isvalid_prop_to_ir(&ui64Type, 0)) {
68 json_object_object_add(record_ir, "localAPICID",
69 json_object_new_uint64(record->ApicId));
70 }
Lawrence Tang794312c2022-07-05 14:46:10 +010071
Lawrence Tange407b4c2022-07-21 13:54:01 +010072 //CPUID information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080073 if (isvalid_prop_to_ir(&ui64Type, 1)) {
74 json_object *cpuid_info_ir = json_object_new_object();
75 EFI_IA32_X64_CPU_ID *cpuid_info =
76 (EFI_IA32_X64_CPU_ID *)record->CpuIdInfo;
77 json_object_object_add(cpuid_info_ir, "eax",
78 json_object_new_uint64(cpuid_info->Eax));
79 json_object_object_add(cpuid_info_ir, "ebx",
80 json_object_new_uint64(cpuid_info->Ebx));
81 json_object_object_add(cpuid_info_ir, "ecx",
82 json_object_new_uint64(cpuid_info->Ecx));
83 json_object_object_add(cpuid_info_ir, "edx",
84 json_object_new_uint64(cpuid_info->Edx));
85 json_object_object_add(record_ir, "cpuidInfo", cpuid_info_ir);
86 }
Lawrence Tang794312c2022-07-05 14:46:10 +010087
Lawrence Tange407b4c2022-07-21 13:54:01 +010088 //Processor error information, of the amount described above.
89 EFI_IA32_X64_PROCESS_ERROR_INFO *current_error_info =
90 (EFI_IA32_X64_PROCESS_ERROR_INFO *)(record + 1);
91 json_object *error_info_array = json_object_new_array();
92 for (int i = 0; i < processor_error_info_num; i++) {
93 json_object_array_add(error_info_array,
94 cper_ia32x64_processor_error_info_to_ir(
95 current_error_info));
96 current_error_info++;
97 }
98 json_object_object_add(record_ir, "processorErrorInfo",
99 error_info_array);
Lawrence Tang794312c2022-07-05 14:46:10 +0100100
Lawrence Tange407b4c2022-07-21 13:54:01 +0100101 //Processor context information, of the amount described above.
102 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *current_context_info =
103 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)current_error_info;
104 void *cur_pos = (void *)current_context_info;
105 json_object *context_info_array = json_object_new_array();
106 for (int i = 0; i < processor_context_info_num; i++) {
107 json_object_array_add(context_info_array,
108 cper_ia32x64_processor_context_info_to_ir(
109 current_context_info, &cur_pos));
110 current_context_info =
111 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)cur_pos;
112 //The context array is a non-fixed size, pointer is shifted within the above function.
113 }
114 json_object_object_add(record_ir, "processorContextInfo",
115 context_info_array);
Lawrence Tang794312c2022-07-05 14:46:10 +0100116
Lawrence Tange407b4c2022-07-21 13:54:01 +0100117 return record_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100118}
119
120//Converts a single IA32/x64 processor error info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121json_object *cper_ia32x64_processor_error_info_to_ir(
122 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info)
Lawrence Tang794312c2022-07-05 14:46:10 +0100123{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100124 json_object *error_info_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100125
Lawrence Tange407b4c2022-07-21 13:54:01 +0100126 //Error structure type (as GUID).
127 char error_type[GUID_STRING_LENGTH];
128 guid_to_string(error_type, &error_info->ErrorType);
Lawrence Tang3592da72022-07-21 16:50:07 +0100129 json_object *type = json_object_new_object();
130 json_object_object_add(type, "guid",
Lawrence Tange407b4c2022-07-21 13:54:01 +0100131 json_object_new_string(error_type));
Lawrence Tang794312c2022-07-05 14:46:10 +0100132
Lawrence Tang3592da72022-07-21 16:50:07 +0100133 //Get the error structure type as a readable string.
134 const char *readable_type = "Unknown";
135 if (guid_equal(&error_info->ErrorType,
John Chungf8fc7052024-05-03 20:05:29 +0800136 &gEfiIa32x64ErrorTypeCacheCheckGuid)) {
Lawrence Tang3592da72022-07-21 16:50:07 +0100137 readable_type = "Cache Check Error";
John Chungf8fc7052024-05-03 20:05:29 +0800138 } else if (guid_equal(&error_info->ErrorType,
139 &gEfiIa32x64ErrorTypeTlbCheckGuid)) {
Lawrence Tang3592da72022-07-21 16:50:07 +0100140 readable_type = "TLB Check Error";
John Chungf8fc7052024-05-03 20:05:29 +0800141 } else if (guid_equal(&error_info->ErrorType,
142 &gEfiIa32x64ErrorTypeBusCheckGuid)) {
Lawrence Tang3592da72022-07-21 16:50:07 +0100143 readable_type = "Bus Check Error";
John Chungf8fc7052024-05-03 20:05:29 +0800144 } else if (guid_equal(&error_info->ErrorType,
145 &gEfiIa32x64ErrorTypeMsCheckGuid)) {
Lawrence Tang3592da72022-07-21 16:50:07 +0100146 readable_type = "MS Check Error";
John Chungf8fc7052024-05-03 20:05:29 +0800147 }
148 json_object_object_add(type, "name",
149 json_object_new_string(readable_type));
Lawrence Tang3592da72022-07-21 16:50:07 +0100150 json_object_object_add(error_info_ir, "type", type);
151
Lawrence Tange407b4c2022-07-21 13:54:01 +0100152 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800153 ValidationTypes ui64Type = { UINT_64T,
154 .value.ui64 = error_info->ValidFields };
Lawrence Tang794312c2022-07-05 14:46:10 +0100155
Lawrence Tange407b4c2022-07-21 13:54:01 +0100156 //Add the check information on a per-structure basis.
157 //Cache and TLB check information are identical, so can be equated.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800158 if (isvalid_prop_to_ir(&ui64Type, 0)) {
159 json_object *check_information = NULL;
160 if (guid_equal(&error_info->ErrorType,
161 &gEfiIa32x64ErrorTypeCacheCheckGuid) ||
162 guid_equal(&error_info->ErrorType,
163 &gEfiIa32x64ErrorTypeTlbCheckGuid)) {
164 check_information = cper_ia32x64_cache_tlb_check_to_ir(
165 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info
166 ->CheckInfo);
167 } else if (guid_equal(&error_info->ErrorType,
168 &gEfiIa32x64ErrorTypeBusCheckGuid)) {
169 check_information = cper_ia32x64_bus_check_to_ir(
170 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info
171 ->CheckInfo);
172 } else if (guid_equal(&error_info->ErrorType,
173 &gEfiIa32x64ErrorTypeMsCheckGuid)) {
174 check_information = cper_ia32x64_ms_check_to_ir(
175 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info
176 ->CheckInfo);
177
178 } else {
179 //Unknown check information.
180 printf("WARN: Invalid/unknown check information GUID found in IA32/x64 CPER section. Ignoring.\n");
181 }
182 json_object_object_add(error_info_ir, "checkInfo",
183 check_information);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100184 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100185
Lawrence Tange407b4c2022-07-21 13:54:01 +0100186 //Target, requestor, and responder identifiers.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800187 if (isvalid_prop_to_ir(&ui64Type, 1)) {
188 json_object_object_add(
189 error_info_ir, "targetAddressID",
190 json_object_new_uint64(error_info->TargetId));
191 }
192 if (isvalid_prop_to_ir(&ui64Type, 2)) {
193 json_object_object_add(
194 error_info_ir, "requestorID",
195 json_object_new_uint64(error_info->RequestorId));
196 }
197 if (isvalid_prop_to_ir(&ui64Type, 3)) {
198 json_object_object_add(
199 error_info_ir, "responderID",
200 json_object_new_uint64(error_info->ResponderId));
201 }
202 if (isvalid_prop_to_ir(&ui64Type, 4)) {
203 json_object_object_add(
204 error_info_ir, "instructionPointer",
205 json_object_new_uint64(error_info->InstructionIP));
206 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100207
Lawrence Tange407b4c2022-07-21 13:54:01 +0100208 return error_info_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100209}
210
211//Converts a single IA32/x64 cache or TLB check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100212json_object *cper_ia32x64_cache_tlb_check_to_ir(
213 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check)
Lawrence Tang794312c2022-07-05 14:46:10 +0100214{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100215 json_object *cache_tlb_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100216
Lawrence Tange407b4c2022-07-21 13:54:01 +0100217 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800218 ValidationTypes ui64Type = {
219 UINT_64T, .value.ui64 = cache_tlb_check->ValidFields
220 };
Lawrence Tang794312c2022-07-05 14:46:10 +0100221
Lawrence Tange407b4c2022-07-21 13:54:01 +0100222 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800223 if (isvalid_prop_to_ir(&ui64Type, 0)) {
224 json_object *transaction_type = integer_to_readable_pair(
225 cache_tlb_check->TransactionType, 3,
226 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
227 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
228 "Unknown (Reserved)");
229 json_object_object_add(cache_tlb_check_ir, "transactionType",
230 transaction_type);
231 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100232
Lawrence Tange407b4c2022-07-21 13:54:01 +0100233 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800234 if (isvalid_prop_to_ir(&ui64Type, 1)) {
235 json_object *operation = integer_to_readable_pair(
236 cache_tlb_check->Operation, 9,
237 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
238 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
239 "Unknown (Reserved)");
240 json_object_object_add(cache_tlb_check_ir, "operation",
241 operation);
242 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100243
Lawrence Tange407b4c2022-07-21 13:54:01 +0100244 //Affected cache/TLB level.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800245 if (isvalid_prop_to_ir(&ui64Type, 2)) {
246 json_object_object_add(
247 cache_tlb_check_ir, "level",
248 json_object_new_uint64(cache_tlb_check->Level));
249 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100250
Lawrence Tange407b4c2022-07-21 13:54:01 +0100251 //Miscellaneous boolean fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800252 if (isvalid_prop_to_ir(&ui64Type, 3)) {
253 json_object_object_add(
254 cache_tlb_check_ir, "processorContextCorrupt",
255 json_object_new_boolean(
256 cache_tlb_check->ContextCorrupt));
257 }
258 if (isvalid_prop_to_ir(&ui64Type, 4)) {
259 json_object_object_add(
260 cache_tlb_check_ir, "uncorrected",
261 json_object_new_boolean(
262 cache_tlb_check->ErrorUncorrected));
263 }
264 if (isvalid_prop_to_ir(&ui64Type, 5)) {
265 json_object_object_add(
266 cache_tlb_check_ir, "preciseIP",
267 json_object_new_boolean(cache_tlb_check->PreciseIp));
268 }
269 if (isvalid_prop_to_ir(&ui64Type, 6)) {
270 json_object_object_add(cache_tlb_check_ir, "restartableIP",
271 json_object_new_boolean(
272 cache_tlb_check->RestartableIp));
273 }
274 if (isvalid_prop_to_ir(&ui64Type, 7)) {
275 json_object_object_add(
276 cache_tlb_check_ir, "overflow",
277 json_object_new_boolean(cache_tlb_check->Overflow));
278 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100279
Lawrence Tange407b4c2022-07-21 13:54:01 +0100280 return cache_tlb_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100281}
282
283//Converts a single IA32/x64 bus check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100284json_object *
285cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check)
286{
287 json_object *bus_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100288
Lawrence Tange407b4c2022-07-21 13:54:01 +0100289 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800290 ValidationTypes ui64Type = { UINT_64T,
291 .value.ui64 = bus_check->ValidFields };
Lawrence Tang794312c2022-07-05 14:46:10 +0100292
Lawrence Tange407b4c2022-07-21 13:54:01 +0100293 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800294 if (isvalid_prop_to_ir(&ui64Type, 0)) {
295 json_object *transaction_type = integer_to_readable_pair(
296 bus_check->TransactionType, 3,
297 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
298 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
299 "Unknown (Reserved)");
300 json_object_object_add(bus_check_ir, "transactionType",
301 transaction_type);
302 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100303
Lawrence Tange407b4c2022-07-21 13:54:01 +0100304 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800305 if (isvalid_prop_to_ir(&ui64Type, 1)) {
306 json_object *operation = integer_to_readable_pair(
307 bus_check->Operation, 9,
308 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
309 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
310 "Unknown (Reserved)");
311 json_object_object_add(bus_check_ir, "operation", operation);
312 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100313
Lawrence Tange407b4c2022-07-21 13:54:01 +0100314 //Affected bus level.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800315 if (isvalid_prop_to_ir(&ui64Type, 2)) {
316 json_object_object_add(
317 bus_check_ir, "level",
318 json_object_new_uint64(bus_check->Level));
319 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100320
Lawrence Tange407b4c2022-07-21 13:54:01 +0100321 //Miscellaneous boolean fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800322 if (isvalid_prop_to_ir(&ui64Type, 3)) {
323 json_object_object_add(
324 bus_check_ir, "processorContextCorrupt",
325 json_object_new_boolean(bus_check->ContextCorrupt));
326 }
327 if (isvalid_prop_to_ir(&ui64Type, 4)) {
328 json_object_object_add(
329 bus_check_ir, "uncorrected",
330 json_object_new_boolean(bus_check->ErrorUncorrected));
331 }
332 if (isvalid_prop_to_ir(&ui64Type, 5)) {
333 json_object_object_add(
334 bus_check_ir, "preciseIP",
335 json_object_new_boolean(bus_check->PreciseIp));
336 }
337 if (isvalid_prop_to_ir(&ui64Type, 6)) {
338 json_object_object_add(
339 bus_check_ir, "restartableIP",
340 json_object_new_boolean(bus_check->RestartableIp));
341 }
342 if (isvalid_prop_to_ir(&ui64Type, 7)) {
343 json_object_object_add(
344 bus_check_ir, "overflow",
345 json_object_new_boolean(bus_check->Overflow));
346 }
347 if (isvalid_prop_to_ir(&ui64Type, 9)) {
348 json_object_object_add(
349 bus_check_ir, "timedOut",
350 json_object_new_boolean(bus_check->TimeOut));
351 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100352
Lawrence Tange407b4c2022-07-21 13:54:01 +0100353 //Participation type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800354 if (isvalid_prop_to_ir(&ui64Type, 8)) {
355 json_object *participation_type = integer_to_readable_pair(
356 bus_check->ParticipationType, 4,
357 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_KEYS,
358 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_VALUES,
359 "Unknown");
360 json_object_object_add(bus_check_ir, "participationType",
361 participation_type);
362 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100363
Lawrence Tange407b4c2022-07-21 13:54:01 +0100364 //Address space.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800365 if (isvalid_prop_to_ir(&ui64Type, 10)) {
366 json_object *address_space = integer_to_readable_pair(
367 bus_check->AddressSpace, 4,
368 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_KEYS,
369 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_VALUES,
370 "Unknown");
371 json_object_object_add(bus_check_ir, "addressSpace",
372 address_space);
373 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100374
375 return bus_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100376}
377
378//Converts a single IA32/x64 MS check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100379json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check)
Lawrence Tang794312c2022-07-05 14:46:10 +0100380{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100381 json_object *ms_check_ir = json_object_new_object();
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800382 ValidationTypes ui64Type = { UINT_64T,
383 .value.ui64 = ms_check->ValidFields };
Lawrence Tange407b4c2022-07-21 13:54:01 +0100384 //Validation bits.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100385 //Error type (operation that caused the error).
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800386 if (isvalid_prop_to_ir(&ui64Type, 0)) {
387 json_object *error_type = integer_to_readable_pair(
388 ms_check->ErrorType, 4,
389 IA32X64_MS_CHECK_INFO_ERROR_TYPES_KEYS,
390 IA32X64_MS_CHECK_INFO_ERROR_TYPES_VALUES,
391 "Unknown (Processor Specific)");
392 json_object_object_add(ms_check_ir, "errorType", error_type);
393 }
Lawrence Tang794312c2022-07-05 14:46:10 +0100394
Lawrence Tange407b4c2022-07-21 13:54:01 +0100395 //Miscellaneous fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800396 if (isvalid_prop_to_ir(&ui64Type, 1)) {
397 json_object_object_add(
398 ms_check_ir, "processorContextCorrupt",
399 json_object_new_boolean(ms_check->ContextCorrupt));
400 }
401 if (isvalid_prop_to_ir(&ui64Type, 2)) {
402 json_object_object_add(
403 ms_check_ir, "uncorrected",
404 json_object_new_boolean(ms_check->ErrorUncorrected));
405 }
406 if (isvalid_prop_to_ir(&ui64Type, 3)) {
407 json_object_object_add(
408 ms_check_ir, "preciseIP",
409 json_object_new_boolean(ms_check->PreciseIp));
410 }
411 if (isvalid_prop_to_ir(&ui64Type, 4)) {
412 json_object_object_add(
413 ms_check_ir, "restartableIP",
414 json_object_new_boolean(ms_check->RestartableIp));
415 }
416 if (isvalid_prop_to_ir(&ui64Type, 5)) {
417 json_object_object_add(
418 ms_check_ir, "overflow",
419 json_object_new_boolean(ms_check->Overflow));
420 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100421
422 return ms_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100423}
424
425//Converts a single IA32/x64 processor context info entry into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100426json_object *cper_ia32x64_processor_context_info_to_ir(
427 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos)
Lawrence Tang794312c2022-07-05 14:46:10 +0100428{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100429 json_object *context_info_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100430
Lawrence Tange407b4c2022-07-21 13:54:01 +0100431 //Register context type.
432 json_object *context_type = integer_to_readable_pair(
433 context_info->RegisterType, 8,
434 IA32X64_REGISTER_CONTEXT_TYPES_KEYS,
435 IA32X64_REGISTER_CONTEXT_TYPES_VALUES, "Unknown (Reserved)");
436 json_object_object_add(context_info_ir, "registerContextType",
437 context_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100438
Lawrence Tange407b4c2022-07-21 13:54:01 +0100439 //Register array size, MSR and MM address.
440 json_object_object_add(context_info_ir, "registerArraySize",
441 json_object_new_uint64(context_info->ArraySize));
442 json_object_object_add(
443 context_info_ir, "msrAddress",
444 json_object_new_uint64(context_info->MsrAddress));
445 json_object_object_add(
446 context_info_ir, "mmRegisterAddress",
447 json_object_new_uint64(context_info->MmRegisterAddress));
Lawrence Tang794312c2022-07-05 14:46:10 +0100448
Lawrence Tange407b4c2022-07-21 13:54:01 +0100449 //Register array.
450 json_object *register_array = NULL;
451 if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
452 EFI_CONTEXT_IA32_REGISTER_STATE *register_state =
453 (EFI_CONTEXT_IA32_REGISTER_STATE *)(context_info + 1);
454 register_array =
455 cper_ia32x64_register_32bit_to_ir(register_state);
456 *cur_pos = (void *)(register_state + 1);
457 } else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) {
458 EFI_CONTEXT_X64_REGISTER_STATE *register_state =
459 (EFI_CONTEXT_X64_REGISTER_STATE *)(context_info + 1);
460 register_array =
461 cper_ia32x64_register_64bit_to_ir(register_state);
462 *cur_pos = (void *)(register_state + 1);
463 } else {
464 //No parseable data, just dump as base64 and shift the head to the next item.
465 *cur_pos = (void *)(context_info + 1);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100466
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700467 int32_t encoded_len = 0;
468 char *encoded = base64_encode((UINT8 *)*cur_pos,
469 context_info->ArraySize,
470 &encoded_len);
471 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800472 printf("Failed to allocate encode output buffer. \n");
473 } else {
John Chungf8fc7052024-05-03 20:05:29 +0800474 register_array = json_object_new_object();
475 json_object_object_add(register_array, "data",
476 json_object_new_string_len(
477 encoded, encoded_len));
478 free(encoded);
479 }
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100480
Lawrence Tange407b4c2022-07-21 13:54:01 +0100481 *cur_pos =
482 (void *)(((char *)*cur_pos) + context_info->ArraySize);
483 }
484 json_object_object_add(context_info_ir, "registerArray",
485 register_array);
Lawrence Tang794312c2022-07-05 14:46:10 +0100486
Lawrence Tange407b4c2022-07-21 13:54:01 +0100487 return context_info_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100488}
489
490//Converts a single CPER IA32 register state into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100491json_object *
492cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers)
Lawrence Tang794312c2022-07-05 14:46:10 +0100493{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100494 json_object *ia32_registers = json_object_new_object();
495 json_object_object_add(ia32_registers, "eax",
496 json_object_new_uint64(registers->Eax));
497 json_object_object_add(ia32_registers, "ebx",
498 json_object_new_uint64(registers->Ebx));
499 json_object_object_add(ia32_registers, "ecx",
500 json_object_new_uint64(registers->Ecx));
501 json_object_object_add(ia32_registers, "edx",
502 json_object_new_uint64(registers->Edx));
503 json_object_object_add(ia32_registers, "esi",
504 json_object_new_uint64(registers->Esi));
505 json_object_object_add(ia32_registers, "edi",
506 json_object_new_uint64(registers->Edi));
507 json_object_object_add(ia32_registers, "ebp",
508 json_object_new_uint64(registers->Ebp));
509 json_object_object_add(ia32_registers, "esp",
510 json_object_new_uint64(registers->Esp));
511 json_object_object_add(ia32_registers, "cs",
512 json_object_new_uint64(registers->Cs));
513 json_object_object_add(ia32_registers, "ds",
514 json_object_new_uint64(registers->Ds));
515 json_object_object_add(ia32_registers, "ss",
516 json_object_new_uint64(registers->Ss));
517 json_object_object_add(ia32_registers, "es",
518 json_object_new_uint64(registers->Es));
519 json_object_object_add(ia32_registers, "fs",
520 json_object_new_uint64(registers->Fs));
521 json_object_object_add(ia32_registers, "gs",
522 json_object_new_uint64(registers->Gs));
523 json_object_object_add(ia32_registers, "eflags",
524 json_object_new_uint64(registers->Eflags));
525 json_object_object_add(ia32_registers, "eip",
526 json_object_new_uint64(registers->Eip));
527 json_object_object_add(ia32_registers, "cr0",
528 json_object_new_uint64(registers->Cr0));
529 json_object_object_add(ia32_registers, "cr1",
530 json_object_new_uint64(registers->Cr1));
531 json_object_object_add(ia32_registers, "cr2",
532 json_object_new_uint64(registers->Cr2));
533 json_object_object_add(ia32_registers, "cr3",
534 json_object_new_uint64(registers->Cr3));
535 json_object_object_add(ia32_registers, "cr4",
536 json_object_new_uint64(registers->Cr4));
537 json_object_object_add(
538 ia32_registers, "gdtr",
539 json_object_new_uint64(registers->Gdtr[0] +
540 ((UINT64)registers->Gdtr[1] << 32)));
541 json_object_object_add(
542 ia32_registers, "idtr",
543 json_object_new_uint64(registers->Idtr[0] +
544 ((UINT64)registers->Idtr[1] << 32)));
545 json_object_object_add(ia32_registers, "ldtr",
546 json_object_new_uint64(registers->Ldtr));
547 json_object_object_add(ia32_registers, "tr",
548 json_object_new_uint64(registers->Tr));
Lawrence Tang794312c2022-07-05 14:46:10 +0100549
Lawrence Tange407b4c2022-07-21 13:54:01 +0100550 return ia32_registers;
Lawrence Tang794312c2022-07-05 14:46:10 +0100551}
552
553//Converts a single CPER x64 register state into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100554json_object *
555cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers)
Lawrence Tang794312c2022-07-05 14:46:10 +0100556{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100557 json_object *x64_registers = json_object_new_object();
558 json_object_object_add(x64_registers, "rax",
559 json_object_new_uint64(registers->Rax));
560 json_object_object_add(x64_registers, "rbx",
561 json_object_new_uint64(registers->Rbx));
562 json_object_object_add(x64_registers, "rcx",
563 json_object_new_uint64(registers->Rcx));
564 json_object_object_add(x64_registers, "rdx",
565 json_object_new_uint64(registers->Rdx));
566 json_object_object_add(x64_registers, "rsi",
567 json_object_new_uint64(registers->Rsi));
568 json_object_object_add(x64_registers, "rdi",
569 json_object_new_uint64(registers->Rdi));
570 json_object_object_add(x64_registers, "rbp",
571 json_object_new_uint64(registers->Rbp));
572 json_object_object_add(x64_registers, "rsp",
573 json_object_new_uint64(registers->Rsp));
574 json_object_object_add(x64_registers, "r8",
575 json_object_new_uint64(registers->R8));
576 json_object_object_add(x64_registers, "r9",
577 json_object_new_uint64(registers->R9));
578 json_object_object_add(x64_registers, "r10",
579 json_object_new_uint64(registers->R10));
580 json_object_object_add(x64_registers, "r11",
581 json_object_new_uint64(registers->R11));
582 json_object_object_add(x64_registers, "r12",
583 json_object_new_uint64(registers->R12));
584 json_object_object_add(x64_registers, "r13",
585 json_object_new_uint64(registers->R13));
586 json_object_object_add(x64_registers, "r14",
587 json_object_new_uint64(registers->R14));
588 json_object_object_add(x64_registers, "r15",
589 json_object_new_uint64(registers->R15));
590 json_object_object_add(x64_registers, "cs",
591 json_object_new_int(registers->Cs));
592 json_object_object_add(x64_registers, "ds",
593 json_object_new_int(registers->Ds));
594 json_object_object_add(x64_registers, "ss",
595 json_object_new_int(registers->Ss));
596 json_object_object_add(x64_registers, "es",
597 json_object_new_int(registers->Es));
598 json_object_object_add(x64_registers, "fs",
599 json_object_new_int(registers->Fs));
600 json_object_object_add(x64_registers, "gs",
601 json_object_new_int(registers->Gs));
602 json_object_object_add(x64_registers, "rflags",
603 json_object_new_uint64(registers->Rflags));
604 json_object_object_add(x64_registers, "eip",
605 json_object_new_uint64(registers->Rip));
606 json_object_object_add(x64_registers, "cr0",
607 json_object_new_uint64(registers->Cr0));
608 json_object_object_add(x64_registers, "cr1",
609 json_object_new_uint64(registers->Cr1));
610 json_object_object_add(x64_registers, "cr2",
611 json_object_new_uint64(registers->Cr2));
612 json_object_object_add(x64_registers, "cr3",
613 json_object_new_uint64(registers->Cr3));
614 json_object_object_add(x64_registers, "cr4",
615 json_object_new_uint64(registers->Cr4));
616 json_object_object_add(x64_registers, "cr8",
617 json_object_new_uint64(registers->Cr8));
618 json_object_object_add(x64_registers, "gdtr_0",
619 json_object_new_uint64(registers->Gdtr[0]));
620 json_object_object_add(x64_registers, "gdtr_1",
621 json_object_new_uint64(registers->Gdtr[1]));
622 json_object_object_add(x64_registers, "idtr_0",
623 json_object_new_uint64(registers->Idtr[0]));
624 json_object_object_add(x64_registers, "idtr_1",
625 json_object_new_uint64(registers->Idtr[1]));
626 json_object_object_add(x64_registers, "ldtr",
627 json_object_new_int(registers->Ldtr));
628 json_object_object_add(x64_registers, "tr",
629 json_object_new_int(registers->Tr));
Lawrence Tang794312c2022-07-05 14:46:10 +0100630
Lawrence Tange407b4c2022-07-21 13:54:01 +0100631 return x64_registers;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100632}
633
634//////////////////
635/// IR TO CPER ///
636//////////////////
637
638//Converts a single IA32/x64 CPER-JSON section into CPER binary, outputting to the provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100639void ir_section_ia32x64_to_cper(json_object *section, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100640{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100641 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *section_cper =
642 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)calloc(
643 1, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100644
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800645 uint64_t valid = 0x0;
646
647 int proc_error_info_num = json_object_get_int(json_object_object_get(
648 section, "processorErrorInfoNum")) &
649 0x3F;
650 int proc_ctx_info_num = json_object_get_int(json_object_object_get(
651 section, "processorContextInfoNum")) &
652 0x3F;
653 valid |= proc_error_info_num << 2;
654 valid |= proc_ctx_info_num << 8;
655
656 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = valid };
657 struct json_object *obj = NULL;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100658
Lawrence Tange407b4c2022-07-21 13:54:01 +0100659 //Local APIC ID.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800660 if (json_object_object_get_ex(section, "localAPICID", &obj)) {
661 section_cper->ApicId = json_object_get_uint64(obj);
662 add_to_valid_bitfield(&ui64Type, 0);
663 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100664
Lawrence Tange407b4c2022-07-21 13:54:01 +0100665 //CPUID info.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800666 if (json_object_object_get_ex(section, "cpuidInfo", &obj)) {
667 json_object *cpuid_info = obj;
668 EFI_IA32_X64_CPU_ID *cpuid_info_cper =
669 (EFI_IA32_X64_CPU_ID *)section_cper->CpuIdInfo;
670 cpuid_info_cper->Eax = json_object_get_uint64(
671 json_object_object_get(cpuid_info, "eax"));
672 cpuid_info_cper->Ebx = json_object_get_uint64(
673 json_object_object_get(cpuid_info, "ebx"));
674 cpuid_info_cper->Ecx = json_object_get_uint64(
675 json_object_object_get(cpuid_info, "ecx"));
676 cpuid_info_cper->Edx = json_object_get_uint64(
677 json_object_object_get(cpuid_info, "edx"));
678 add_to_valid_bitfield(&ui64Type, 1);
679 }
680 section_cper->ValidFields = ui64Type.value.ui64;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100681
Lawrence Tange407b4c2022-07-21 13:54:01 +0100682 //Flush the header to file before dealing w/ info sections.
683 fwrite(section_cper, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD), 1,
684 out);
685 fflush(out);
686 free(section_cper);
687
688 //Iterate and deal with sections.
689 json_object *error_info =
690 json_object_object_get(section, "processorErrorInfo");
691 json_object *context_info =
692 json_object_object_get(section, "processorContextInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800693 for (int i = 0; i < proc_error_info_num; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100694 ir_ia32x64_error_info_to_cper(
695 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800696 }
697 for (int i = 0; i < proc_ctx_info_num; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100698 ir_ia32x64_context_info_to_cper(
699 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800700 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100701}
702
703//Converts a single CPER-JSON IA32/x64 error information structure into CPER binary, outputting to the
704//provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100705void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100706{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100707 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info_cper =
708 (EFI_IA32_X64_PROCESS_ERROR_INFO *)calloc(
709 1, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100710
Lawrence Tange407b4c2022-07-21 13:54:01 +0100711 //Error structure type.
Lawrence Tang3592da72022-07-21 16:50:07 +0100712 json_object *type = json_object_object_get(error_info, "type");
713 string_to_guid(
714 &error_info_cper->ErrorType,
715 json_object_get_string(json_object_object_get(type, "guid")));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100716
Lawrence Tange407b4c2022-07-21 13:54:01 +0100717 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800718 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
719 struct json_object *obj = NULL;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100720
Lawrence Tange407b4c2022-07-21 13:54:01 +0100721 //Check information, parsed based on the error type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800722 if (json_object_object_get_ex(error_info, "checkInfo", &obj)) {
723 json_object *check_info = obj;
724 if (guid_equal(&error_info_cper->ErrorType,
725 &gEfiIa32x64ErrorTypeCacheCheckGuid) ||
726 guid_equal(&error_info_cper->ErrorType,
727 &gEfiIa32x64ErrorTypeTlbCheckGuid)) {
728 ir_ia32x64_cache_tlb_check_error_to_cper(
729 check_info,
730 (EFI_IA32_X64_CACHE_CHECK_INFO
731 *)&error_info_cper->CheckInfo);
732 } else if (guid_equal(&error_info_cper->ErrorType,
733 &gEfiIa32x64ErrorTypeBusCheckGuid)) {
734 ir_ia32x64_bus_check_error_to_cper(
735 check_info,
736 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info_cper
737 ->CheckInfo);
738 } else if (guid_equal(&error_info_cper->ErrorType,
739 &gEfiIa32x64ErrorTypeMsCheckGuid)) {
740 ir_ia32x64_ms_check_error_to_cper(
741 check_info,
742 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info_cper
743 ->CheckInfo);
744 }
745 add_to_valid_bitfield(&ui64Type, 0);
John Chungf8fc7052024-05-03 20:05:29 +0800746 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100747
Lawrence Tange407b4c2022-07-21 13:54:01 +0100748 //Miscellaneous numeric fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800749 if (json_object_object_get_ex(error_info, "targetAddressID", &obj)) {
750 error_info_cper->TargetId = json_object_get_uint64(obj);
751 add_to_valid_bitfield(&ui64Type, 1);
752 }
753 if (json_object_object_get_ex(error_info, "requestorID", &obj)) {
754 error_info_cper->RequestorId = json_object_get_uint64(obj);
755 add_to_valid_bitfield(&ui64Type, 2);
756 }
757 if (json_object_object_get_ex(error_info, "responderID", &obj)) {
758 error_info_cper->ResponderId = json_object_get_uint64(obj);
759 add_to_valid_bitfield(&ui64Type, 3);
760 }
761 if (json_object_object_get_ex(error_info, "instructionPointer", &obj)) {
762 error_info_cper->InstructionIP = json_object_get_uint64(obj);
763 add_to_valid_bitfield(&ui64Type, 4);
764 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100765
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800766 error_info_cper->ValidFields = ui64Type.value.ui64;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100767 //Write out to stream, then free resources.
768 fwrite(error_info_cper, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO), 1,
769 out);
770 fflush(out);
771 free(error_info_cper);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100772}
773
774//Converts a single CPER-JSON IA32/x64 cache/TLB check error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100775void ir_ia32x64_cache_tlb_check_error_to_cper(
776 json_object *check_info, EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100777{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100778 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800779 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
780 struct json_object *obj = NULL;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100781
Lawrence Tange407b4c2022-07-21 13:54:01 +0100782 //Transaction type, operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800783 if (json_object_object_get_ex(check_info, "transactionType", &obj)) {
784 check_info_cper->TransactionType =
785 readable_pair_to_integer(obj);
786 add_to_valid_bitfield(&ui64Type, 0);
787 }
788 if (json_object_object_get_ex(check_info, "operation", &obj)) {
789 check_info_cper->Operation = readable_pair_to_integer(obj);
790 add_to_valid_bitfield(&ui64Type, 1);
791 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100792
Lawrence Tange407b4c2022-07-21 13:54:01 +0100793 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800794 if (json_object_object_get_ex(check_info, "level", &obj)) {
795 check_info_cper->Level = json_object_get_uint64(obj);
796 add_to_valid_bitfield(&ui64Type, 2);
797 }
798 if (json_object_object_get_ex(check_info, "processorContextCorrupt",
799 &obj)) {
800 check_info_cper->ContextCorrupt = json_object_get_boolean(obj);
801 add_to_valid_bitfield(&ui64Type, 3);
802 }
803 if (json_object_object_get_ex(check_info, "uncorrected", &obj)) {
804 check_info_cper->ErrorUncorrected =
805 json_object_get_boolean(obj);
806 add_to_valid_bitfield(&ui64Type, 4);
807 }
808 if (json_object_object_get_ex(check_info, "preciseIP", &obj)) {
809 check_info_cper->PreciseIp = json_object_get_boolean(obj);
810 add_to_valid_bitfield(&ui64Type, 5);
811 }
812 if (json_object_object_get_ex(check_info, "restartableIP", &obj)) {
813 check_info_cper->RestartableIp = json_object_get_boolean(obj);
814 add_to_valid_bitfield(&ui64Type, 6);
815 }
816 if (json_object_object_get_ex(check_info, "overflow", &obj)) {
817 check_info_cper->Overflow = json_object_get_boolean(obj);
818 add_to_valid_bitfield(&ui64Type, 7);
819 }
820 check_info_cper->ValidFields = ui64Type.value.ui64;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100821}
822
823//Converts a single CPER-JSON IA32/x64 bus error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100824void ir_ia32x64_bus_check_error_to_cper(
825 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100826{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100827 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800828 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
829 struct json_object *obj = NULL;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100830
Lawrence Tange407b4c2022-07-21 13:54:01 +0100831 //Readable pair fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800832 if (json_object_object_get_ex(check_info, "transactionType", &obj)) {
833 check_info_cper->TransactionType =
834 readable_pair_to_integer(obj);
835 add_to_valid_bitfield(&ui64Type, 0);
836 }
837 if (json_object_object_get_ex(check_info, "operation", &obj)) {
838 check_info_cper->Operation = readable_pair_to_integer(obj);
839 add_to_valid_bitfield(&ui64Type, 1);
840 }
841 if (json_object_object_get_ex(check_info, "participationType", &obj)) {
842 check_info_cper->ParticipationType =
843 readable_pair_to_integer(obj);
844 add_to_valid_bitfield(&ui64Type, 8);
845 }
846
847 if (json_object_object_get_ex(check_info, "addressSpace", &obj)) {
848 check_info_cper->AddressSpace = readable_pair_to_integer(obj);
849 add_to_valid_bitfield(&ui64Type, 10);
850 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100851
Lawrence Tange407b4c2022-07-21 13:54:01 +0100852 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800853 if (json_object_object_get_ex(check_info, "level", &obj)) {
854 check_info_cper->Level = json_object_get_uint64(obj);
855 add_to_valid_bitfield(&ui64Type, 2);
856 }
857 if (json_object_object_get_ex(check_info, "processorContextCorrupt",
858 &obj)) {
859 check_info_cper->ContextCorrupt = json_object_get_boolean(obj);
860 add_to_valid_bitfield(&ui64Type, 3);
861 }
862 if (json_object_object_get_ex(check_info, "uncorrected", &obj)) {
863 check_info_cper->ErrorUncorrected =
864 json_object_get_boolean(obj);
865 add_to_valid_bitfield(&ui64Type, 4);
866 }
867 if (json_object_object_get_ex(check_info, "preciseIP", &obj)) {
868 check_info_cper->PreciseIp = json_object_get_boolean(obj);
869 add_to_valid_bitfield(&ui64Type, 5);
870 }
871 if (json_object_object_get_ex(check_info, "restartableIP", &obj)) {
872 check_info_cper->RestartableIp = json_object_get_boolean(obj);
873 add_to_valid_bitfield(&ui64Type, 6);
874 }
875 if (json_object_object_get_ex(check_info, "overflow", &obj)) {
876 check_info_cper->Overflow = json_object_get_boolean(obj);
877 add_to_valid_bitfield(&ui64Type, 7);
878 }
879 if (json_object_object_get_ex(check_info, "timedOut", &obj)) {
880 check_info_cper->TimeOut = json_object_get_boolean(obj);
881 add_to_valid_bitfield(&ui64Type, 9);
882 }
883 check_info_cper->ValidFields = ui64Type.value.ui64;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100884}
885
886//Converts a single CPER-JSON IA32/x64 MS error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100887void ir_ia32x64_ms_check_error_to_cper(
888 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100889{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100890 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800891 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
892 struct json_object *obj = NULL;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100893
Lawrence Tange407b4c2022-07-21 13:54:01 +0100894 //Type of MS check error.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800895 if (json_object_object_get_ex(check_info, "errorType", &obj)) {
896 check_info_cper->ErrorType = readable_pair_to_integer(obj);
897 add_to_valid_bitfield(&ui64Type, 0);
898 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100899
Lawrence Tange407b4c2022-07-21 13:54:01 +0100900 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800901 if (json_object_object_get_ex(check_info, "processorContextCorrupt",
902 &obj)) {
903 check_info_cper->ContextCorrupt = json_object_get_boolean(obj);
904 add_to_valid_bitfield(&ui64Type, 1);
905 }
906 if (json_object_object_get_ex(check_info, "uncorrected", &obj)) {
907 check_info_cper->ErrorUncorrected =
908 json_object_get_boolean(obj);
909 add_to_valid_bitfield(&ui64Type, 2);
910 }
911 if (json_object_object_get_ex(check_info, "preciseIP", &obj)) {
912 check_info_cper->PreciseIp = json_object_get_boolean(obj);
913 add_to_valid_bitfield(&ui64Type, 3);
914 }
915 if (json_object_object_get_ex(check_info, "restartableIP", &obj)) {
916 check_info_cper->RestartableIp = json_object_get_boolean(obj);
917 add_to_valid_bitfield(&ui64Type, 4);
918 }
919 if (json_object_object_get_ex(check_info, "overflow", &obj)) {
920 check_info_cper->Overflow = json_object_get_boolean(obj);
921 add_to_valid_bitfield(&ui64Type, 5);
922 }
923 check_info_cper->ValidFields = ui64Type.value.ui64;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100924}
925
926//Converts a single CPER-JSON IA32/x64 context information structure into CPER binary, outputting to the
927//provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100928void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100929{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100930 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info_cper =
931 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)calloc(
932 1, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100933
Lawrence Tange407b4c2022-07-21 13:54:01 +0100934 //Register context type.
935 context_info_cper->RegisterType = (UINT16)readable_pair_to_integer(
936 json_object_object_get(context_info, "registerContextType"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100937
Lawrence Tange407b4c2022-07-21 13:54:01 +0100938 //Miscellaneous numeric fields.
939 context_info_cper->ArraySize = (UINT16)json_object_get_uint64(
940 json_object_object_get(context_info, "registerArraySize"));
941 context_info_cper->MsrAddress = (UINT32)json_object_get_uint64(
942 json_object_object_get(context_info, "msrAddress"));
943 context_info_cper->MmRegisterAddress = json_object_get_uint64(
944 json_object_object_get(context_info, "mmRegisterAddress"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100945
Lawrence Tange407b4c2022-07-21 13:54:01 +0100946 //Flush header to stream.
947 fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO),
948 1, out);
949 fflush(out);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100950
Lawrence Tange407b4c2022-07-21 13:54:01 +0100951 //Handle the register array, depending on type provided.
952 json_object *register_array =
953 json_object_object_get(context_info, "registerArray");
954 if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
955 ir_ia32x64_ia32_registers_to_cper(register_array, out);
956 } else if (context_info_cper->RegisterType ==
957 EFI_REG_CONTEXT_TYPE_X64) {
958 ir_ia32x64_x64_registers_to_cper(register_array, out);
959 } else {
960 //Unknown/structure is not defined.
961 json_object *encoded =
962 json_object_object_get(register_array, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700963 int32_t decoded_len = 0;
964 const char *j_string = json_object_get_string(encoded);
965 int j_size = json_object_get_string_len(encoded);
966 UINT8 *decoded = base64_decode(j_string, j_size, &decoded_len);
967 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800968 printf("Failed to allocate decode output buffer. \n");
969 } else {
John Chungf8fc7052024-05-03 20:05:29 +0800970 fwrite(decoded, decoded_len, 1, out);
971 fflush(out);
972 free(decoded);
973 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100974 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100975
Lawrence Tange407b4c2022-07-21 13:54:01 +0100976 //Free remaining resources.
977 free(context_info_cper);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100978}
979
980//Converts a single CPER-JSON IA32 register array into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100981void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100982{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100983 EFI_CONTEXT_IA32_REGISTER_STATE register_state;
984 register_state.Eax = (UINT32)json_object_get_uint64(
985 json_object_object_get(registers, "eax"));
986 register_state.Ebx = (UINT32)json_object_get_uint64(
987 json_object_object_get(registers, "ebx"));
988 register_state.Ecx = (UINT32)json_object_get_uint64(
989 json_object_object_get(registers, "ecx"));
990 register_state.Edx = (UINT32)json_object_get_uint64(
991 json_object_object_get(registers, "edx"));
992 register_state.Esi = (UINT32)json_object_get_uint64(
993 json_object_object_get(registers, "esi"));
994 register_state.Edi = (UINT32)json_object_get_uint64(
995 json_object_object_get(registers, "edi"));
996 register_state.Ebp = (UINT32)json_object_get_uint64(
997 json_object_object_get(registers, "ebp"));
998 register_state.Esp = (UINT32)json_object_get_uint64(
999 json_object_object_get(registers, "esp"));
1000 register_state.Cs = (UINT16)json_object_get_uint64(
1001 json_object_object_get(registers, "cs"));
1002 register_state.Ds = (UINT32)json_object_get_uint64(
1003 json_object_object_get(registers, "ds"));
1004 register_state.Ss = (UINT16)json_object_get_uint64(
1005 json_object_object_get(registers, "ss"));
1006 register_state.Es = (UINT16)json_object_get_uint64(
1007 json_object_object_get(registers, "es"));
1008 register_state.Fs = (UINT16)json_object_get_uint64(
1009 json_object_object_get(registers, "fs"));
1010 register_state.Gs = (UINT16)json_object_get_uint64(
1011 json_object_object_get(registers, "gs"));
1012 register_state.Eflags = (UINT32)json_object_get_uint64(
1013 json_object_object_get(registers, "eflags"));
1014 register_state.Eip = (UINT32)json_object_get_uint64(
1015 json_object_object_get(registers, "eip"));
1016 register_state.Cr0 = (UINT32)json_object_get_uint64(
1017 json_object_object_get(registers, "cr0"));
1018 register_state.Cr1 = (UINT32)json_object_get_uint64(
1019 json_object_object_get(registers, "cr1"));
1020 register_state.Cr2 = (UINT32)json_object_get_uint64(
1021 json_object_object_get(registers, "cr2"));
1022 register_state.Cr3 = (UINT32)json_object_get_uint64(
1023 json_object_object_get(registers, "cr3"));
1024 register_state.Cr4 = (UINT32)json_object_get_uint64(
1025 json_object_object_get(registers, "cr4"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +01001026
Lawrence Tange407b4c2022-07-21 13:54:01 +01001027 //64-bit registers are split into two 32-bit parts.
1028 UINT64 gdtr = json_object_get_uint64(
1029 json_object_object_get(registers, "gdtr"));
1030 register_state.Gdtr[0] = gdtr & 0xFFFFFFFF;
1031 register_state.Gdtr[1] = gdtr >> 32;
1032 UINT64 idtr = json_object_get_uint64(
1033 json_object_object_get(registers, "idtr"));
1034 register_state.Idtr[0] = idtr & 0xFFFFFFFF;
1035 register_state.Idtr[1] = idtr >> 32;
Lawrence Tangbd9a84a2022-07-13 15:41:16 +01001036
Lawrence Tange407b4c2022-07-21 13:54:01 +01001037 //16-bit registers.
1038 register_state.Ldtr = (UINT16)json_object_get_uint64(
1039 json_object_object_get(registers, "ldtr"));
1040 register_state.Tr = (UINT16)json_object_get_uint64(
1041 json_object_object_get(registers, "tr"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +01001042
Lawrence Tange407b4c2022-07-21 13:54:01 +01001043 //Write out to stream.
1044 fwrite(&register_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1,
1045 out);
1046 fflush(out);
Lawrence Tangd0c88842022-07-13 14:51:17 +01001047}
1048
1049//Converts a single CPER-JSON x64 register array into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001050void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +01001051{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001052 EFI_CONTEXT_X64_REGISTER_STATE register_state;
1053 register_state.Rax = json_object_get_uint64(
1054 json_object_object_get(registers, "rax"));
1055 register_state.Rbx = json_object_get_uint64(
1056 json_object_object_get(registers, "rbx"));
1057 register_state.Rcx = json_object_get_uint64(
1058 json_object_object_get(registers, "rcx"));
1059 register_state.Rdx = json_object_get_uint64(
1060 json_object_object_get(registers, "rdx"));
1061 register_state.Rsi = json_object_get_uint64(
1062 json_object_object_get(registers, "rsi"));
1063 register_state.Rdi = json_object_get_uint64(
1064 json_object_object_get(registers, "rdi"));
1065 register_state.Rbp = json_object_get_uint64(
1066 json_object_object_get(registers, "rbp"));
1067 register_state.Rsp = json_object_get_uint64(
1068 json_object_object_get(registers, "rsp"));
1069 register_state.R8 =
1070 json_object_get_uint64(json_object_object_get(registers, "r8"));
1071 register_state.R9 =
1072 json_object_get_uint64(json_object_object_get(registers, "r9"));
1073 register_state.R10 = json_object_get_uint64(
1074 json_object_object_get(registers, "r10"));
1075 register_state.R11 = json_object_get_uint64(
1076 json_object_object_get(registers, "r11"));
1077 register_state.R12 = json_object_get_uint64(
1078 json_object_object_get(registers, "r12"));
1079 register_state.R13 = json_object_get_uint64(
1080 json_object_object_get(registers, "r13"));
1081 register_state.R14 = json_object_get_uint64(
1082 json_object_object_get(registers, "r14"));
1083 register_state.R15 = json_object_get_uint64(
1084 json_object_object_get(registers, "r15"));
1085 register_state.Cs = (UINT16)json_object_get_int(
1086 json_object_object_get(registers, "cs"));
1087 register_state.Ds = (UINT16)json_object_get_int(
1088 json_object_object_get(registers, "ds"));
1089 register_state.Ss = (UINT16)json_object_get_int(
1090 json_object_object_get(registers, "ss"));
1091 register_state.Es = (UINT16)json_object_get_int(
1092 json_object_object_get(registers, "es"));
1093 register_state.Fs = (UINT16)json_object_get_int(
1094 json_object_object_get(registers, "fs"));
1095 register_state.Gs = (UINT16)json_object_get_int(
1096 json_object_object_get(registers, "gs"));
1097 register_state.Resv1 = 0;
1098 register_state.Rflags = json_object_get_uint64(
1099 json_object_object_get(registers, "rflags"));
1100 register_state.Rip = json_object_get_uint64(
1101 json_object_object_get(registers, "eip"));
1102 register_state.Cr0 = json_object_get_uint64(
1103 json_object_object_get(registers, "cr0"));
1104 register_state.Cr1 = json_object_get_uint64(
1105 json_object_object_get(registers, "cr1"));
1106 register_state.Cr2 = json_object_get_uint64(
1107 json_object_object_get(registers, "cr2"));
1108 register_state.Cr3 = json_object_get_uint64(
1109 json_object_object_get(registers, "cr3"));
1110 register_state.Cr4 = json_object_get_uint64(
1111 json_object_object_get(registers, "cr4"));
1112 register_state.Cr8 = json_object_get_uint64(
1113 json_object_object_get(registers, "cr8"));
1114 register_state.Gdtr[0] = json_object_get_uint64(
1115 json_object_object_get(registers, "gdtr_0"));
1116 register_state.Gdtr[1] = json_object_get_uint64(
1117 json_object_object_get(registers, "gdtr_1"));
1118 register_state.Idtr[0] = json_object_get_uint64(
1119 json_object_object_get(registers, "idtr_0"));
1120 register_state.Idtr[1] = json_object_get_uint64(
1121 json_object_object_get(registers, "idtr_1"));
1122 register_state.Ldtr = (UINT16)json_object_get_int(
1123 json_object_object_get(registers, "ldtr"));
1124 register_state.Tr = (UINT16)json_object_get_int(
1125 json_object_object_get(registers, "tr"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +01001126
Lawrence Tange407b4c2022-07-21 13:54:01 +01001127 //Write out to stream.
1128 fwrite(&register_state, sizeof(EFI_CONTEXT_X64_REGISTER_STATE), 1, out);
1129 fflush(out);
John Chungf8fc7052024-05-03 20:05:29 +08001130}