blob: 0657b821d9244d25c2f12b24645825d2c86dcc91 [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.
4 *
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 Tang794312c2022-07-05 14:46:10 +010011#include "../edk/Cper.h"
12#include "../cper-utils.h"
13#include "cper-section-ia32x64.h"
14
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.
Lawrence Tange407b4c2022-07-21 13:54:01 +010046json_object *
47cper_section_ia32x64_to_ir(void *section,
48 EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
Lawrence Tang794312c2022-07-05 14:46:10 +010049{
Lawrence Tange407b4c2022-07-21 13:54:01 +010050 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *record =
51 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)section;
52 json_object *record_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +010053
Lawrence Tange407b4c2022-07-21 13:54:01 +010054 //Validation bits.
55 json_object *validationBits = json_object_new_object();
56 json_object_object_add(validationBits, "localAPICIDValid",
57 json_object_new_boolean(record->ValidFields &
58 0b1));
59 json_object_object_add(
60 validationBits, "cpuIDInfoValid",
61 json_object_new_boolean((record->ValidFields >> 1) & 0b1));
62 int processor_error_info_num = (record->ValidFields >> 2) & 0b111111;
63 json_object_object_add(validationBits, "processorErrorInfoNum",
64 json_object_new_int(processor_error_info_num));
65 int processor_context_info_num = (record->ValidFields >> 8) & 0b111111;
66 json_object_object_add(validationBits, "processorContextInfoNum",
67 json_object_new_int(processor_context_info_num));
68 json_object_object_add(record_ir, "validationBits", validationBits);
Lawrence Tang794312c2022-07-05 14:46:10 +010069
Lawrence Tange407b4c2022-07-21 13:54:01 +010070 //APIC ID.
71 json_object_object_add(record_ir, "localAPICID",
72 json_object_new_uint64(record->ApicId));
Lawrence Tang794312c2022-07-05 14:46:10 +010073
Lawrence Tange407b4c2022-07-21 13:54:01 +010074 //CPUID information.
75 json_object *cpuid_info_ir = json_object_new_object();
76 EFI_IA32_X64_CPU_ID *cpuid_info =
77 (EFI_IA32_X64_CPU_ID *)record->CpuIdInfo;
78 json_object_object_add(cpuid_info_ir, "eax",
79 json_object_new_uint64(cpuid_info->Eax));
80 json_object_object_add(cpuid_info_ir, "ebx",
81 json_object_new_uint64(cpuid_info->Ebx));
82 json_object_object_add(cpuid_info_ir, "ecx",
83 json_object_new_uint64(cpuid_info->Ecx));
84 json_object_object_add(cpuid_info_ir, "edx",
85 json_object_new_uint64(cpuid_info->Edx));
86 json_object_object_add(record_ir, "cpuidInfo", cpuid_info_ir);
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,
136 &gEfiIa32x64ErrorTypeCacheCheckGuid))
137 readable_type = "Cache Check Error";
138 else if (guid_equal(&error_info->ErrorType,
139 &gEfiIa32x64ErrorTypeTlbCheckGuid))
140 readable_type = "TLB Check Error";
141 else if (guid_equal(&error_info->ErrorType,
142 &gEfiIa32x64ErrorTypeBusCheckGuid))
143 readable_type = "Bus Check Error";
144 else if (guid_equal(&error_info->ErrorType,
145 &gEfiIa32x64ErrorTypeMsCheckGuid))
146 readable_type = "MS Check Error";
147 json_object_object_add(type, "name", json_object_new_string(readable_type));
148 json_object_object_add(error_info_ir, "type", type);
149
Lawrence Tange407b4c2022-07-21 13:54:01 +0100150 //Validation bits.
151 json_object *validation =
152 bitfield_to_ir(error_info->ValidFields, 5,
153 IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES);
154 json_object_object_add(error_info_ir, "validationBits", validation);
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.
158 json_object *check_information = NULL;
159 if (guid_equal(&error_info->ErrorType,
160 &gEfiIa32x64ErrorTypeCacheCheckGuid) ||
161 guid_equal(&error_info->ErrorType,
162 &gEfiIa32x64ErrorTypeTlbCheckGuid)) {
163 check_information = cper_ia32x64_cache_tlb_check_to_ir(
164 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info->CheckInfo);
165 } else if (guid_equal(&error_info->ErrorType,
166 &gEfiIa32x64ErrorTypeBusCheckGuid)) {
167 check_information = cper_ia32x64_bus_check_to_ir(
168 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info->CheckInfo);
169 } else if (guid_equal(&error_info->ErrorType,
170 &gEfiIa32x64ErrorTypeMsCheckGuid)) {
171 check_information = cper_ia32x64_ms_check_to_ir(
172 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info->CheckInfo);
173 } else {
174 //Unknown check information.
175 printf("WARN: Invalid/unknown check information GUID found in IA32/x64 CPER section. Ignoring.\n");
176 }
177 json_object_object_add(error_info_ir, "checkInfo", check_information);
Lawrence Tang794312c2022-07-05 14:46:10 +0100178
Lawrence Tange407b4c2022-07-21 13:54:01 +0100179 //Target, requestor, and responder identifiers.
180 json_object_object_add(error_info_ir, "targetAddressID",
181 json_object_new_uint64(error_info->TargetId));
182 json_object_object_add(error_info_ir, "requestorID",
183 json_object_new_uint64(error_info->RequestorId));
184 json_object_object_add(error_info_ir, "responderID",
185 json_object_new_uint64(error_info->ResponderId));
186 json_object_object_add(
187 error_info_ir, "instructionPointer",
188 json_object_new_uint64(error_info->InstructionIP));
Lawrence Tang794312c2022-07-05 14:46:10 +0100189
Lawrence Tange407b4c2022-07-21 13:54:01 +0100190 return error_info_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100191}
192
193//Converts a single IA32/x64 cache or TLB check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100194json_object *cper_ia32x64_cache_tlb_check_to_ir(
195 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check)
Lawrence Tang794312c2022-07-05 14:46:10 +0100196{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100197 json_object *cache_tlb_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100198
Lawrence Tange407b4c2022-07-21 13:54:01 +0100199 //Validation bits.
200 json_object *validation =
201 bitfield_to_ir(cache_tlb_check->ValidFields, 8,
202 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
203 json_object_object_add(cache_tlb_check_ir, "validationBits",
204 validation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100205
Lawrence Tange407b4c2022-07-21 13:54:01 +0100206 //Transaction type.
207 json_object *transaction_type = integer_to_readable_pair(
208 cache_tlb_check->TransactionType, 3,
209 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
210 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
211 "Unknown (Reserved)");
212 json_object_object_add(cache_tlb_check_ir, "transactionType",
213 transaction_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100214
Lawrence Tange407b4c2022-07-21 13:54:01 +0100215 //Operation.
216 json_object *operation = integer_to_readable_pair(
217 cache_tlb_check->Operation, 9,
218 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
219 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
220 "Unknown (Reserved)");
221 json_object_object_add(cache_tlb_check_ir, "operation", operation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100222
Lawrence Tange407b4c2022-07-21 13:54:01 +0100223 //Affected cache/TLB level.
224 json_object_object_add(cache_tlb_check_ir, "level",
225 json_object_new_uint64(cache_tlb_check->Level));
Lawrence Tang794312c2022-07-05 14:46:10 +0100226
Lawrence Tange407b4c2022-07-21 13:54:01 +0100227 //Miscellaneous boolean fields.
228 json_object_object_add(
229 cache_tlb_check_ir, "processorContextCorrupt",
230 json_object_new_boolean(cache_tlb_check->ContextCorrupt));
231 json_object_object_add(
232 cache_tlb_check_ir, "uncorrected",
233 json_object_new_boolean(cache_tlb_check->ErrorUncorrected));
234 json_object_object_add(
235 cache_tlb_check_ir, "preciseIP",
236 json_object_new_boolean(cache_tlb_check->PreciseIp));
237 json_object_object_add(
238 cache_tlb_check_ir, "restartableIP",
239 json_object_new_boolean(cache_tlb_check->RestartableIp));
240 json_object_object_add(
241 cache_tlb_check_ir, "overflow",
242 json_object_new_boolean(cache_tlb_check->Overflow));
Lawrence Tang794312c2022-07-05 14:46:10 +0100243
Lawrence Tange407b4c2022-07-21 13:54:01 +0100244 return cache_tlb_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100245}
246
247//Converts a single IA32/x64 bus check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100248json_object *
249cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check)
250{
251 json_object *bus_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100252
Lawrence Tange407b4c2022-07-21 13:54:01 +0100253 //Validation bits.
254 json_object *validation =
255 bitfield_to_ir(bus_check->ValidFields, 11,
256 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
257 json_object_object_add(bus_check_ir, "validationBits", validation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100258
Lawrence Tange407b4c2022-07-21 13:54:01 +0100259 //Transaction type.
260 json_object *transaction_type = integer_to_readable_pair(
261 bus_check->TransactionType, 3,
262 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
263 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
264 "Unknown (Reserved)");
265 json_object_object_add(bus_check_ir, "transactionType",
266 transaction_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100267
Lawrence Tange407b4c2022-07-21 13:54:01 +0100268 //Operation.
269 json_object *operation = integer_to_readable_pair(
270 bus_check->Operation, 9,
271 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
272 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
273 "Unknown (Reserved)");
274 json_object_object_add(bus_check_ir, "operation", operation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100275
Lawrence Tange407b4c2022-07-21 13:54:01 +0100276 //Affected bus level.
277 json_object_object_add(bus_check_ir, "level",
278 json_object_new_uint64(bus_check->Level));
Lawrence Tang794312c2022-07-05 14:46:10 +0100279
Lawrence Tange407b4c2022-07-21 13:54:01 +0100280 //Miscellaneous boolean fields.
281 json_object_object_add(
282 bus_check_ir, "processorContextCorrupt",
283 json_object_new_boolean(bus_check->ContextCorrupt));
284 json_object_object_add(
285 bus_check_ir, "uncorrected",
286 json_object_new_boolean(bus_check->ErrorUncorrected));
287 json_object_object_add(bus_check_ir, "preciseIP",
288 json_object_new_boolean(bus_check->PreciseIp));
289 json_object_object_add(
290 bus_check_ir, "restartableIP",
291 json_object_new_boolean(bus_check->RestartableIp));
292 json_object_object_add(bus_check_ir, "overflow",
293 json_object_new_boolean(bus_check->Overflow));
294 json_object_object_add(bus_check_ir, "timedOut",
295 json_object_new_boolean(bus_check->TimeOut));
Lawrence Tang794312c2022-07-05 14:46:10 +0100296
Lawrence Tange407b4c2022-07-21 13:54:01 +0100297 //Participation type.
298 json_object *participation_type = integer_to_readable_pair(
299 bus_check->ParticipationType, 4,
300 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_KEYS,
301 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_VALUES, "Unknown");
302 json_object_object_add(bus_check_ir, "participationType",
303 participation_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100304
Lawrence Tange407b4c2022-07-21 13:54:01 +0100305 //Address space.
306 json_object *address_space = integer_to_readable_pair(
307 bus_check->AddressSpace, 4,
308 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_KEYS,
309 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
310 json_object_object_add(bus_check_ir, "addressSpace", address_space);
311
312 return bus_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100313}
314
315//Converts a single IA32/x64 MS check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100316json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check)
Lawrence Tang794312c2022-07-05 14:46:10 +0100317{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100318 json_object *ms_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100319
Lawrence Tange407b4c2022-07-21 13:54:01 +0100320 //Validation bits.
321 json_object *validation = bitfield_to_ir(
322 ms_check->ValidFields, 6,
323 IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES);
324 json_object_object_add(ms_check_ir, "validationBits", validation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100325
Lawrence Tange407b4c2022-07-21 13:54:01 +0100326 //Error type (operation that caused the error).
327 json_object *error_type = integer_to_readable_pair(
328 ms_check->ErrorType, 4, IA32X64_MS_CHECK_INFO_ERROR_TYPES_KEYS,
329 IA32X64_MS_CHECK_INFO_ERROR_TYPES_VALUES,
330 "Unknown (Processor Specific)");
331 json_object_object_add(ms_check_ir, "errorType", error_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100332
Lawrence Tange407b4c2022-07-21 13:54:01 +0100333 //Miscellaneous fields.
334 json_object_object_add(
335 ms_check_ir, "processorContextCorrupt",
336 json_object_new_boolean(ms_check->ContextCorrupt));
337 json_object_object_add(
338 ms_check_ir, "uncorrected",
339 json_object_new_boolean(ms_check->ErrorUncorrected));
340 json_object_object_add(ms_check_ir, "preciseIP",
341 json_object_new_boolean(ms_check->PreciseIp));
342 json_object_object_add(
343 ms_check_ir, "restartableIP",
344 json_object_new_boolean(ms_check->RestartableIp));
345 json_object_object_add(ms_check_ir, "overflow",
346 json_object_new_boolean(ms_check->Overflow));
347
348 return ms_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100349}
350
351//Converts a single IA32/x64 processor context info entry into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100352json_object *cper_ia32x64_processor_context_info_to_ir(
353 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos)
Lawrence Tang794312c2022-07-05 14:46:10 +0100354{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100355 json_object *context_info_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100356
Lawrence Tange407b4c2022-07-21 13:54:01 +0100357 //Register context type.
358 json_object *context_type = integer_to_readable_pair(
359 context_info->RegisterType, 8,
360 IA32X64_REGISTER_CONTEXT_TYPES_KEYS,
361 IA32X64_REGISTER_CONTEXT_TYPES_VALUES, "Unknown (Reserved)");
362 json_object_object_add(context_info_ir, "registerContextType",
363 context_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100364
Lawrence Tange407b4c2022-07-21 13:54:01 +0100365 //Register array size, MSR and MM address.
366 json_object_object_add(context_info_ir, "registerArraySize",
367 json_object_new_uint64(context_info->ArraySize));
368 json_object_object_add(
369 context_info_ir, "msrAddress",
370 json_object_new_uint64(context_info->MsrAddress));
371 json_object_object_add(
372 context_info_ir, "mmRegisterAddress",
373 json_object_new_uint64(context_info->MmRegisterAddress));
Lawrence Tang794312c2022-07-05 14:46:10 +0100374
Lawrence Tange407b4c2022-07-21 13:54:01 +0100375 //Register array.
376 json_object *register_array = NULL;
377 if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
378 EFI_CONTEXT_IA32_REGISTER_STATE *register_state =
379 (EFI_CONTEXT_IA32_REGISTER_STATE *)(context_info + 1);
380 register_array =
381 cper_ia32x64_register_32bit_to_ir(register_state);
382 *cur_pos = (void *)(register_state + 1);
383 } else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) {
384 EFI_CONTEXT_X64_REGISTER_STATE *register_state =
385 (EFI_CONTEXT_X64_REGISTER_STATE *)(context_info + 1);
386 register_array =
387 cper_ia32x64_register_64bit_to_ir(register_state);
388 *cur_pos = (void *)(register_state + 1);
389 } else {
390 //No parseable data, just dump as base64 and shift the head to the next item.
391 *cur_pos = (void *)(context_info + 1);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100392
Lawrence Tange407b4c2022-07-21 13:54:01 +0100393 char *encoded = b64_encode((unsigned char *)*cur_pos,
394 context_info->ArraySize);
395 register_array = json_object_new_object();
396 json_object_object_add(register_array, "data",
397 json_object_new_string(encoded));
398 free(encoded);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100399
Lawrence Tange407b4c2022-07-21 13:54:01 +0100400 *cur_pos =
401 (void *)(((char *)*cur_pos) + context_info->ArraySize);
402 }
403 json_object_object_add(context_info_ir, "registerArray",
404 register_array);
Lawrence Tang794312c2022-07-05 14:46:10 +0100405
Lawrence Tange407b4c2022-07-21 13:54:01 +0100406 return context_info_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100407}
408
409//Converts a single CPER IA32 register state into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100410json_object *
411cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers)
Lawrence Tang794312c2022-07-05 14:46:10 +0100412{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100413 json_object *ia32_registers = json_object_new_object();
414 json_object_object_add(ia32_registers, "eax",
415 json_object_new_uint64(registers->Eax));
416 json_object_object_add(ia32_registers, "ebx",
417 json_object_new_uint64(registers->Ebx));
418 json_object_object_add(ia32_registers, "ecx",
419 json_object_new_uint64(registers->Ecx));
420 json_object_object_add(ia32_registers, "edx",
421 json_object_new_uint64(registers->Edx));
422 json_object_object_add(ia32_registers, "esi",
423 json_object_new_uint64(registers->Esi));
424 json_object_object_add(ia32_registers, "edi",
425 json_object_new_uint64(registers->Edi));
426 json_object_object_add(ia32_registers, "ebp",
427 json_object_new_uint64(registers->Ebp));
428 json_object_object_add(ia32_registers, "esp",
429 json_object_new_uint64(registers->Esp));
430 json_object_object_add(ia32_registers, "cs",
431 json_object_new_uint64(registers->Cs));
432 json_object_object_add(ia32_registers, "ds",
433 json_object_new_uint64(registers->Ds));
434 json_object_object_add(ia32_registers, "ss",
435 json_object_new_uint64(registers->Ss));
436 json_object_object_add(ia32_registers, "es",
437 json_object_new_uint64(registers->Es));
438 json_object_object_add(ia32_registers, "fs",
439 json_object_new_uint64(registers->Fs));
440 json_object_object_add(ia32_registers, "gs",
441 json_object_new_uint64(registers->Gs));
442 json_object_object_add(ia32_registers, "eflags",
443 json_object_new_uint64(registers->Eflags));
444 json_object_object_add(ia32_registers, "eip",
445 json_object_new_uint64(registers->Eip));
446 json_object_object_add(ia32_registers, "cr0",
447 json_object_new_uint64(registers->Cr0));
448 json_object_object_add(ia32_registers, "cr1",
449 json_object_new_uint64(registers->Cr1));
450 json_object_object_add(ia32_registers, "cr2",
451 json_object_new_uint64(registers->Cr2));
452 json_object_object_add(ia32_registers, "cr3",
453 json_object_new_uint64(registers->Cr3));
454 json_object_object_add(ia32_registers, "cr4",
455 json_object_new_uint64(registers->Cr4));
456 json_object_object_add(
457 ia32_registers, "gdtr",
458 json_object_new_uint64(registers->Gdtr[0] +
459 ((UINT64)registers->Gdtr[1] << 32)));
460 json_object_object_add(
461 ia32_registers, "idtr",
462 json_object_new_uint64(registers->Idtr[0] +
463 ((UINT64)registers->Idtr[1] << 32)));
464 json_object_object_add(ia32_registers, "ldtr",
465 json_object_new_uint64(registers->Ldtr));
466 json_object_object_add(ia32_registers, "tr",
467 json_object_new_uint64(registers->Tr));
Lawrence Tang794312c2022-07-05 14:46:10 +0100468
Lawrence Tange407b4c2022-07-21 13:54:01 +0100469 return ia32_registers;
Lawrence Tang794312c2022-07-05 14:46:10 +0100470}
471
472//Converts a single CPER x64 register state into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100473json_object *
474cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers)
Lawrence Tang794312c2022-07-05 14:46:10 +0100475{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100476 json_object *x64_registers = json_object_new_object();
477 json_object_object_add(x64_registers, "rax",
478 json_object_new_uint64(registers->Rax));
479 json_object_object_add(x64_registers, "rbx",
480 json_object_new_uint64(registers->Rbx));
481 json_object_object_add(x64_registers, "rcx",
482 json_object_new_uint64(registers->Rcx));
483 json_object_object_add(x64_registers, "rdx",
484 json_object_new_uint64(registers->Rdx));
485 json_object_object_add(x64_registers, "rsi",
486 json_object_new_uint64(registers->Rsi));
487 json_object_object_add(x64_registers, "rdi",
488 json_object_new_uint64(registers->Rdi));
489 json_object_object_add(x64_registers, "rbp",
490 json_object_new_uint64(registers->Rbp));
491 json_object_object_add(x64_registers, "rsp",
492 json_object_new_uint64(registers->Rsp));
493 json_object_object_add(x64_registers, "r8",
494 json_object_new_uint64(registers->R8));
495 json_object_object_add(x64_registers, "r9",
496 json_object_new_uint64(registers->R9));
497 json_object_object_add(x64_registers, "r10",
498 json_object_new_uint64(registers->R10));
499 json_object_object_add(x64_registers, "r11",
500 json_object_new_uint64(registers->R11));
501 json_object_object_add(x64_registers, "r12",
502 json_object_new_uint64(registers->R12));
503 json_object_object_add(x64_registers, "r13",
504 json_object_new_uint64(registers->R13));
505 json_object_object_add(x64_registers, "r14",
506 json_object_new_uint64(registers->R14));
507 json_object_object_add(x64_registers, "r15",
508 json_object_new_uint64(registers->R15));
509 json_object_object_add(x64_registers, "cs",
510 json_object_new_int(registers->Cs));
511 json_object_object_add(x64_registers, "ds",
512 json_object_new_int(registers->Ds));
513 json_object_object_add(x64_registers, "ss",
514 json_object_new_int(registers->Ss));
515 json_object_object_add(x64_registers, "es",
516 json_object_new_int(registers->Es));
517 json_object_object_add(x64_registers, "fs",
518 json_object_new_int(registers->Fs));
519 json_object_object_add(x64_registers, "gs",
520 json_object_new_int(registers->Gs));
521 json_object_object_add(x64_registers, "rflags",
522 json_object_new_uint64(registers->Rflags));
523 json_object_object_add(x64_registers, "eip",
524 json_object_new_uint64(registers->Rip));
525 json_object_object_add(x64_registers, "cr0",
526 json_object_new_uint64(registers->Cr0));
527 json_object_object_add(x64_registers, "cr1",
528 json_object_new_uint64(registers->Cr1));
529 json_object_object_add(x64_registers, "cr2",
530 json_object_new_uint64(registers->Cr2));
531 json_object_object_add(x64_registers, "cr3",
532 json_object_new_uint64(registers->Cr3));
533 json_object_object_add(x64_registers, "cr4",
534 json_object_new_uint64(registers->Cr4));
535 json_object_object_add(x64_registers, "cr8",
536 json_object_new_uint64(registers->Cr8));
537 json_object_object_add(x64_registers, "gdtr_0",
538 json_object_new_uint64(registers->Gdtr[0]));
539 json_object_object_add(x64_registers, "gdtr_1",
540 json_object_new_uint64(registers->Gdtr[1]));
541 json_object_object_add(x64_registers, "idtr_0",
542 json_object_new_uint64(registers->Idtr[0]));
543 json_object_object_add(x64_registers, "idtr_1",
544 json_object_new_uint64(registers->Idtr[1]));
545 json_object_object_add(x64_registers, "ldtr",
546 json_object_new_int(registers->Ldtr));
547 json_object_object_add(x64_registers, "tr",
548 json_object_new_int(registers->Tr));
Lawrence Tang794312c2022-07-05 14:46:10 +0100549
Lawrence Tange407b4c2022-07-21 13:54:01 +0100550 return x64_registers;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100551}
552
553//////////////////
554/// IR TO CPER ///
555//////////////////
556
557//Converts a single IA32/x64 CPER-JSON section into CPER binary, outputting to the provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100558void ir_section_ia32x64_to_cper(json_object *section, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100559{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100560 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *section_cper =
561 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)calloc(
562 1, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100563
Lawrence Tange407b4c2022-07-21 13:54:01 +0100564 //Validation bits.
565 json_object *validation =
566 json_object_object_get(section, "validationBits");
567 section_cper->ValidFields = 0x0;
568 section_cper->ValidFields |= json_object_get_boolean(
569 json_object_object_get(validation, "localAPICIDValid"));
570 section_cper->ValidFields |=
571 json_object_get_boolean(
572 json_object_object_get(validation, "cpuIDInfoValid"))
573 << 1;
574 int proc_error_info_num =
575 json_object_get_int(json_object_object_get(
576 validation, "processorErrorInfoNum")) &
577 0b111111;
578 int proc_ctx_info_num =
579 json_object_get_int(json_object_object_get(
580 validation, "processorContextInfoNum")) &
581 0b111111;
582 section_cper->ValidFields |= proc_error_info_num << 2;
583 section_cper->ValidFields |= proc_ctx_info_num << 8;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100584
Lawrence Tange407b4c2022-07-21 13:54:01 +0100585 //Local APIC ID.
586 section_cper->ApicId = json_object_get_uint64(
587 json_object_object_get(section, "localAPICID"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100588
Lawrence Tange407b4c2022-07-21 13:54:01 +0100589 //CPUID info.
590 json_object *cpuid_info = json_object_object_get(section, "cpuidInfo");
591 EFI_IA32_X64_CPU_ID *cpuid_info_cper =
592 (EFI_IA32_X64_CPU_ID *)section_cper->CpuIdInfo;
593 cpuid_info_cper->Eax = json_object_get_uint64(
594 json_object_object_get(cpuid_info, "eax"));
595 cpuid_info_cper->Ebx = json_object_get_uint64(
596 json_object_object_get(cpuid_info, "ebx"));
597 cpuid_info_cper->Ecx = json_object_get_uint64(
598 json_object_object_get(cpuid_info, "ecx"));
599 cpuid_info_cper->Edx = json_object_get_uint64(
600 json_object_object_get(cpuid_info, "edx"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100601
Lawrence Tange407b4c2022-07-21 13:54:01 +0100602 //Flush the header to file before dealing w/ info sections.
603 fwrite(section_cper, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD), 1,
604 out);
605 fflush(out);
606 free(section_cper);
607
608 //Iterate and deal with sections.
609 json_object *error_info =
610 json_object_object_get(section, "processorErrorInfo");
611 json_object *context_info =
612 json_object_object_get(section, "processorContextInfo");
613 for (int i = 0; i < proc_error_info_num; i++)
614 ir_ia32x64_error_info_to_cper(
615 json_object_array_get_idx(error_info, i), out);
616 for (int i = 0; i < proc_ctx_info_num; i++)
617 ir_ia32x64_context_info_to_cper(
618 json_object_array_get_idx(context_info, i), out);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100619}
620
621//Converts a single CPER-JSON IA32/x64 error information structure into CPER binary, outputting to the
622//provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100623void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100624{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100625 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info_cper =
626 (EFI_IA32_X64_PROCESS_ERROR_INFO *)calloc(
627 1, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100628
Lawrence Tange407b4c2022-07-21 13:54:01 +0100629 //Error structure type.
Lawrence Tang3592da72022-07-21 16:50:07 +0100630 json_object *type = json_object_object_get(error_info, "type");
631 string_to_guid(
632 &error_info_cper->ErrorType,
633 json_object_get_string(json_object_object_get(type, "guid")));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100634
Lawrence Tange407b4c2022-07-21 13:54:01 +0100635 //Validation bits.
636 error_info_cper->ValidFields = ir_to_bitfield(
637 json_object_object_get(error_info, "validationBits"), 5,
638 IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100639
Lawrence Tange407b4c2022-07-21 13:54:01 +0100640 //Check information, parsed based on the error type.
641 json_object *check_info =
642 json_object_object_get(error_info, "checkInfo");
643 if (guid_equal(&error_info_cper->ErrorType,
644 &gEfiIa32x64ErrorTypeCacheCheckGuid) ||
645 guid_equal(&error_info_cper->ErrorType,
646 &gEfiIa32x64ErrorTypeTlbCheckGuid)) {
647 ir_ia32x64_cache_tlb_check_error_to_cper(
648 check_info,
649 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info_cper
650 ->CheckInfo);
651 } else if (guid_equal(&error_info_cper->ErrorType,
652 &gEfiIa32x64ErrorTypeBusCheckGuid))
653 ir_ia32x64_bus_check_error_to_cper(
654 check_info,
655 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info_cper
656 ->CheckInfo);
657 else if (guid_equal(&error_info_cper->ErrorType,
658 &gEfiIa32x64ErrorTypeMsCheckGuid))
659 ir_ia32x64_ms_check_error_to_cper(
660 check_info,
661 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info_cper
662 ->CheckInfo);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100663
Lawrence Tange407b4c2022-07-21 13:54:01 +0100664 //Miscellaneous numeric fields.
665 error_info_cper->TargetId = json_object_get_uint64(
666 json_object_object_get(error_info, "targetAddressID"));
667 error_info_cper->RequestorId = json_object_get_uint64(
668 json_object_object_get(error_info, "requestorID"));
669 error_info_cper->ResponderId = json_object_get_uint64(
670 json_object_object_get(error_info, "responderID"));
671 error_info_cper->InstructionIP = json_object_get_uint64(
672 json_object_object_get(error_info, "instructionPointer"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100673
Lawrence Tange407b4c2022-07-21 13:54:01 +0100674 //Write out to stream, then free resources.
675 fwrite(error_info_cper, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO), 1,
676 out);
677 fflush(out);
678 free(error_info_cper);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100679}
680
681//Converts a single CPER-JSON IA32/x64 cache/TLB check error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100682void ir_ia32x64_cache_tlb_check_error_to_cper(
683 json_object *check_info, EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100684{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100685 //Validation bits.
686 check_info_cper->ValidFields = ir_to_bitfield(
687 json_object_object_get(check_info, "validationBits"), 8,
688 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100689
Lawrence Tange407b4c2022-07-21 13:54:01 +0100690 //Transaction type, operation.
691 check_info_cper->TransactionType = readable_pair_to_integer(
692 json_object_object_get(check_info, "transactionType"));
693 check_info_cper->Operation = readable_pair_to_integer(
694 json_object_object_get(check_info, "operation"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100695
Lawrence Tange407b4c2022-07-21 13:54:01 +0100696 //Miscellaneous raw value fields.
697 check_info_cper->Level = json_object_get_uint64(
698 json_object_object_get(check_info, "level"));
699 check_info_cper->ContextCorrupt = json_object_get_boolean(
700 json_object_object_get(check_info, "processorContextCorrupt"));
701 check_info_cper->ErrorUncorrected = json_object_get_boolean(
702 json_object_object_get(check_info, "uncorrected"));
703 check_info_cper->PreciseIp = json_object_get_boolean(
704 json_object_object_get(check_info, "preciseIP"));
705 check_info_cper->RestartableIp = json_object_get_boolean(
706 json_object_object_get(check_info, "restartableIP"));
707 check_info_cper->Overflow = json_object_get_boolean(
708 json_object_object_get(check_info, "overflow"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100709}
710
711//Converts a single CPER-JSON IA32/x64 bus error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100712void ir_ia32x64_bus_check_error_to_cper(
713 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100714{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100715 //Validation bits.
716 check_info_cper->ValidFields = ir_to_bitfield(
717 json_object_object_get(check_info, "validationBits"), 11,
718 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100719
Lawrence Tange407b4c2022-07-21 13:54:01 +0100720 //Readable pair fields.
721 check_info_cper->TransactionType = readable_pair_to_integer(
722 json_object_object_get(check_info, "transactionType"));
723 check_info_cper->Operation = readable_pair_to_integer(
724 json_object_object_get(check_info, "operation"));
725 check_info_cper->ParticipationType = readable_pair_to_integer(
726 json_object_object_get(check_info, "participationType"));
727 check_info_cper->AddressSpace = readable_pair_to_integer(
728 json_object_object_get(check_info, "addressSpace"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100729
Lawrence Tange407b4c2022-07-21 13:54:01 +0100730 //Miscellaneous raw value fields.
731 check_info_cper->Level = json_object_get_uint64(
732 json_object_object_get(check_info, "level"));
733 check_info_cper->ContextCorrupt = json_object_get_boolean(
734 json_object_object_get(check_info, "processorContextCorrupt"));
735 check_info_cper->ErrorUncorrected = json_object_get_boolean(
736 json_object_object_get(check_info, "uncorrected"));
737 check_info_cper->PreciseIp = json_object_get_boolean(
738 json_object_object_get(check_info, "preciseIP"));
739 check_info_cper->RestartableIp = json_object_get_boolean(
740 json_object_object_get(check_info, "restartableIP"));
741 check_info_cper->Overflow = json_object_get_boolean(
742 json_object_object_get(check_info, "overflow"));
743 check_info_cper->TimeOut = json_object_get_boolean(
744 json_object_object_get(check_info, "timedOut"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100745}
746
747//Converts a single CPER-JSON IA32/x64 MS error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100748void ir_ia32x64_ms_check_error_to_cper(
749 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100750{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100751 //Validation bits.
752 check_info_cper->ValidFields = ir_to_bitfield(
753 json_object_object_get(check_info, "validationBits"), 6,
754 IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100755
Lawrence Tange407b4c2022-07-21 13:54:01 +0100756 //Type of MS check error.
757 check_info_cper->ErrorType = readable_pair_to_integer(
758 json_object_object_get(check_info, "errorType"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100759
Lawrence Tange407b4c2022-07-21 13:54:01 +0100760 //Miscellaneous raw value fields.
761 check_info_cper->ContextCorrupt = json_object_get_boolean(
762 json_object_object_get(check_info, "processorContextCorrupt"));
763 check_info_cper->ErrorUncorrected = json_object_get_boolean(
764 json_object_object_get(check_info, "uncorrected"));
765 check_info_cper->PreciseIp = json_object_get_boolean(
766 json_object_object_get(check_info, "preciseIP"));
767 check_info_cper->RestartableIp = json_object_get_boolean(
768 json_object_object_get(check_info, "restartableIP"));
769 check_info_cper->Overflow = json_object_get_boolean(
770 json_object_object_get(check_info, "overflow"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100771}
772
773//Converts a single CPER-JSON IA32/x64 context information structure into CPER binary, outputting to the
774//provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100775void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100776{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100777 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info_cper =
778 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)calloc(
779 1, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100780
Lawrence Tange407b4c2022-07-21 13:54:01 +0100781 //Register context type.
782 context_info_cper->RegisterType = (UINT16)readable_pair_to_integer(
783 json_object_object_get(context_info, "registerContextType"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100784
Lawrence Tange407b4c2022-07-21 13:54:01 +0100785 //Miscellaneous numeric fields.
786 context_info_cper->ArraySize = (UINT16)json_object_get_uint64(
787 json_object_object_get(context_info, "registerArraySize"));
788 context_info_cper->MsrAddress = (UINT32)json_object_get_uint64(
789 json_object_object_get(context_info, "msrAddress"));
790 context_info_cper->MmRegisterAddress = json_object_get_uint64(
791 json_object_object_get(context_info, "mmRegisterAddress"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100792
Lawrence Tange407b4c2022-07-21 13:54:01 +0100793 //Flush header to stream.
794 fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO),
795 1, out);
796 fflush(out);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100797
Lawrence Tange407b4c2022-07-21 13:54:01 +0100798 //Handle the register array, depending on type provided.
799 json_object *register_array =
800 json_object_object_get(context_info, "registerArray");
801 if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
802 ir_ia32x64_ia32_registers_to_cper(register_array, out);
803 } else if (context_info_cper->RegisterType ==
804 EFI_REG_CONTEXT_TYPE_X64) {
805 ir_ia32x64_x64_registers_to_cper(register_array, out);
806 } else {
807 //Unknown/structure is not defined.
808 json_object *encoded =
809 json_object_object_get(register_array, "data");
810 char *decoded = b64_decode(json_object_get_string(encoded),
811 json_object_get_string_len(encoded));
812 fwrite(decoded, context_info_cper->ArraySize, 1, out);
813 fflush(out);
814 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100815
Lawrence Tange407b4c2022-07-21 13:54:01 +0100816 //Free remaining resources.
817 free(context_info_cper);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100818}
819
820//Converts a single CPER-JSON IA32 register array into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100821void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100822{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100823 EFI_CONTEXT_IA32_REGISTER_STATE register_state;
824 register_state.Eax = (UINT32)json_object_get_uint64(
825 json_object_object_get(registers, "eax"));
826 register_state.Ebx = (UINT32)json_object_get_uint64(
827 json_object_object_get(registers, "ebx"));
828 register_state.Ecx = (UINT32)json_object_get_uint64(
829 json_object_object_get(registers, "ecx"));
830 register_state.Edx = (UINT32)json_object_get_uint64(
831 json_object_object_get(registers, "edx"));
832 register_state.Esi = (UINT32)json_object_get_uint64(
833 json_object_object_get(registers, "esi"));
834 register_state.Edi = (UINT32)json_object_get_uint64(
835 json_object_object_get(registers, "edi"));
836 register_state.Ebp = (UINT32)json_object_get_uint64(
837 json_object_object_get(registers, "ebp"));
838 register_state.Esp = (UINT32)json_object_get_uint64(
839 json_object_object_get(registers, "esp"));
840 register_state.Cs = (UINT16)json_object_get_uint64(
841 json_object_object_get(registers, "cs"));
842 register_state.Ds = (UINT32)json_object_get_uint64(
843 json_object_object_get(registers, "ds"));
844 register_state.Ss = (UINT16)json_object_get_uint64(
845 json_object_object_get(registers, "ss"));
846 register_state.Es = (UINT16)json_object_get_uint64(
847 json_object_object_get(registers, "es"));
848 register_state.Fs = (UINT16)json_object_get_uint64(
849 json_object_object_get(registers, "fs"));
850 register_state.Gs = (UINT16)json_object_get_uint64(
851 json_object_object_get(registers, "gs"));
852 register_state.Eflags = (UINT32)json_object_get_uint64(
853 json_object_object_get(registers, "eflags"));
854 register_state.Eip = (UINT32)json_object_get_uint64(
855 json_object_object_get(registers, "eip"));
856 register_state.Cr0 = (UINT32)json_object_get_uint64(
857 json_object_object_get(registers, "cr0"));
858 register_state.Cr1 = (UINT32)json_object_get_uint64(
859 json_object_object_get(registers, "cr1"));
860 register_state.Cr2 = (UINT32)json_object_get_uint64(
861 json_object_object_get(registers, "cr2"));
862 register_state.Cr3 = (UINT32)json_object_get_uint64(
863 json_object_object_get(registers, "cr3"));
864 register_state.Cr4 = (UINT32)json_object_get_uint64(
865 json_object_object_get(registers, "cr4"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100866
Lawrence Tange407b4c2022-07-21 13:54:01 +0100867 //64-bit registers are split into two 32-bit parts.
868 UINT64 gdtr = json_object_get_uint64(
869 json_object_object_get(registers, "gdtr"));
870 register_state.Gdtr[0] = gdtr & 0xFFFFFFFF;
871 register_state.Gdtr[1] = gdtr >> 32;
872 UINT64 idtr = json_object_get_uint64(
873 json_object_object_get(registers, "idtr"));
874 register_state.Idtr[0] = idtr & 0xFFFFFFFF;
875 register_state.Idtr[1] = idtr >> 32;
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100876
Lawrence Tange407b4c2022-07-21 13:54:01 +0100877 //16-bit registers.
878 register_state.Ldtr = (UINT16)json_object_get_uint64(
879 json_object_object_get(registers, "ldtr"));
880 register_state.Tr = (UINT16)json_object_get_uint64(
881 json_object_object_get(registers, "tr"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100882
Lawrence Tange407b4c2022-07-21 13:54:01 +0100883 //Write out to stream.
884 fwrite(&register_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1,
885 out);
886 fflush(out);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100887}
888
889//Converts a single CPER-JSON x64 register array into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100890void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100891{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100892 EFI_CONTEXT_X64_REGISTER_STATE register_state;
893 register_state.Rax = json_object_get_uint64(
894 json_object_object_get(registers, "rax"));
895 register_state.Rbx = json_object_get_uint64(
896 json_object_object_get(registers, "rbx"));
897 register_state.Rcx = json_object_get_uint64(
898 json_object_object_get(registers, "rcx"));
899 register_state.Rdx = json_object_get_uint64(
900 json_object_object_get(registers, "rdx"));
901 register_state.Rsi = json_object_get_uint64(
902 json_object_object_get(registers, "rsi"));
903 register_state.Rdi = json_object_get_uint64(
904 json_object_object_get(registers, "rdi"));
905 register_state.Rbp = json_object_get_uint64(
906 json_object_object_get(registers, "rbp"));
907 register_state.Rsp = json_object_get_uint64(
908 json_object_object_get(registers, "rsp"));
909 register_state.R8 =
910 json_object_get_uint64(json_object_object_get(registers, "r8"));
911 register_state.R9 =
912 json_object_get_uint64(json_object_object_get(registers, "r9"));
913 register_state.R10 = json_object_get_uint64(
914 json_object_object_get(registers, "r10"));
915 register_state.R11 = json_object_get_uint64(
916 json_object_object_get(registers, "r11"));
917 register_state.R12 = json_object_get_uint64(
918 json_object_object_get(registers, "r12"));
919 register_state.R13 = json_object_get_uint64(
920 json_object_object_get(registers, "r13"));
921 register_state.R14 = json_object_get_uint64(
922 json_object_object_get(registers, "r14"));
923 register_state.R15 = json_object_get_uint64(
924 json_object_object_get(registers, "r15"));
925 register_state.Cs = (UINT16)json_object_get_int(
926 json_object_object_get(registers, "cs"));
927 register_state.Ds = (UINT16)json_object_get_int(
928 json_object_object_get(registers, "ds"));
929 register_state.Ss = (UINT16)json_object_get_int(
930 json_object_object_get(registers, "ss"));
931 register_state.Es = (UINT16)json_object_get_int(
932 json_object_object_get(registers, "es"));
933 register_state.Fs = (UINT16)json_object_get_int(
934 json_object_object_get(registers, "fs"));
935 register_state.Gs = (UINT16)json_object_get_int(
936 json_object_object_get(registers, "gs"));
937 register_state.Resv1 = 0;
938 register_state.Rflags = json_object_get_uint64(
939 json_object_object_get(registers, "rflags"));
940 register_state.Rip = json_object_get_uint64(
941 json_object_object_get(registers, "eip"));
942 register_state.Cr0 = json_object_get_uint64(
943 json_object_object_get(registers, "cr0"));
944 register_state.Cr1 = json_object_get_uint64(
945 json_object_object_get(registers, "cr1"));
946 register_state.Cr2 = json_object_get_uint64(
947 json_object_object_get(registers, "cr2"));
948 register_state.Cr3 = json_object_get_uint64(
949 json_object_object_get(registers, "cr3"));
950 register_state.Cr4 = json_object_get_uint64(
951 json_object_object_get(registers, "cr4"));
952 register_state.Cr8 = json_object_get_uint64(
953 json_object_object_get(registers, "cr8"));
954 register_state.Gdtr[0] = json_object_get_uint64(
955 json_object_object_get(registers, "gdtr_0"));
956 register_state.Gdtr[1] = json_object_get_uint64(
957 json_object_object_get(registers, "gdtr_1"));
958 register_state.Idtr[0] = json_object_get_uint64(
959 json_object_object_get(registers, "idtr_0"));
960 register_state.Idtr[1] = json_object_get_uint64(
961 json_object_object_get(registers, "idtr_1"));
962 register_state.Ldtr = (UINT16)json_object_get_int(
963 json_object_object_get(registers, "ldtr"));
964 register_state.Tr = (UINT16)json_object_get_int(
965 json_object_object_get(registers, "tr"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100966
Lawrence Tange407b4c2022-07-21 13:54:01 +0100967 //Write out to stream.
968 fwrite(&register_state, sizeof(EFI_CONTEXT_X64_REGISTER_STATE), 1, out);
969 fflush(out);
Lawrence Tang794312c2022-07-05 14:46:10 +0100970}