blob: 35c5a2e9396bfc234ddffcd0a8764396e9511d7e [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);
129 json_object_object_add(error_info_ir, "type",
130 json_object_new_string(error_type));
Lawrence Tang794312c2022-07-05 14:46:10 +0100131
Lawrence Tange407b4c2022-07-21 13:54:01 +0100132 //Validation bits.
133 json_object *validation =
134 bitfield_to_ir(error_info->ValidFields, 5,
135 IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES);
136 json_object_object_add(error_info_ir, "validationBits", validation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100137
Lawrence Tange407b4c2022-07-21 13:54:01 +0100138 //Add the check information on a per-structure basis.
139 //Cache and TLB check information are identical, so can be equated.
140 json_object *check_information = NULL;
141 if (guid_equal(&error_info->ErrorType,
142 &gEfiIa32x64ErrorTypeCacheCheckGuid) ||
143 guid_equal(&error_info->ErrorType,
144 &gEfiIa32x64ErrorTypeTlbCheckGuid)) {
145 check_information = cper_ia32x64_cache_tlb_check_to_ir(
146 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info->CheckInfo);
147 } else if (guid_equal(&error_info->ErrorType,
148 &gEfiIa32x64ErrorTypeBusCheckGuid)) {
149 check_information = cper_ia32x64_bus_check_to_ir(
150 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info->CheckInfo);
151 } else if (guid_equal(&error_info->ErrorType,
152 &gEfiIa32x64ErrorTypeMsCheckGuid)) {
153 check_information = cper_ia32x64_ms_check_to_ir(
154 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info->CheckInfo);
155 } else {
156 //Unknown check information.
157 printf("WARN: Invalid/unknown check information GUID found in IA32/x64 CPER section. Ignoring.\n");
158 }
159 json_object_object_add(error_info_ir, "checkInfo", check_information);
Lawrence Tang794312c2022-07-05 14:46:10 +0100160
Lawrence Tange407b4c2022-07-21 13:54:01 +0100161 //Target, requestor, and responder identifiers.
162 json_object_object_add(error_info_ir, "targetAddressID",
163 json_object_new_uint64(error_info->TargetId));
164 json_object_object_add(error_info_ir, "requestorID",
165 json_object_new_uint64(error_info->RequestorId));
166 json_object_object_add(error_info_ir, "responderID",
167 json_object_new_uint64(error_info->ResponderId));
168 json_object_object_add(
169 error_info_ir, "instructionPointer",
170 json_object_new_uint64(error_info->InstructionIP));
Lawrence Tang794312c2022-07-05 14:46:10 +0100171
Lawrence Tange407b4c2022-07-21 13:54:01 +0100172 return error_info_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100173}
174
175//Converts a single IA32/x64 cache or TLB check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100176json_object *cper_ia32x64_cache_tlb_check_to_ir(
177 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check)
Lawrence Tang794312c2022-07-05 14:46:10 +0100178{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100179 json_object *cache_tlb_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100180
Lawrence Tange407b4c2022-07-21 13:54:01 +0100181 //Validation bits.
182 json_object *validation =
183 bitfield_to_ir(cache_tlb_check->ValidFields, 8,
184 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
185 json_object_object_add(cache_tlb_check_ir, "validationBits",
186 validation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100187
Lawrence Tange407b4c2022-07-21 13:54:01 +0100188 //Transaction type.
189 json_object *transaction_type = integer_to_readable_pair(
190 cache_tlb_check->TransactionType, 3,
191 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
192 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
193 "Unknown (Reserved)");
194 json_object_object_add(cache_tlb_check_ir, "transactionType",
195 transaction_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100196
Lawrence Tange407b4c2022-07-21 13:54:01 +0100197 //Operation.
198 json_object *operation = integer_to_readable_pair(
199 cache_tlb_check->Operation, 9,
200 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
201 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
202 "Unknown (Reserved)");
203 json_object_object_add(cache_tlb_check_ir, "operation", operation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100204
Lawrence Tange407b4c2022-07-21 13:54:01 +0100205 //Affected cache/TLB level.
206 json_object_object_add(cache_tlb_check_ir, "level",
207 json_object_new_uint64(cache_tlb_check->Level));
Lawrence Tang794312c2022-07-05 14:46:10 +0100208
Lawrence Tange407b4c2022-07-21 13:54:01 +0100209 //Miscellaneous boolean fields.
210 json_object_object_add(
211 cache_tlb_check_ir, "processorContextCorrupt",
212 json_object_new_boolean(cache_tlb_check->ContextCorrupt));
213 json_object_object_add(
214 cache_tlb_check_ir, "uncorrected",
215 json_object_new_boolean(cache_tlb_check->ErrorUncorrected));
216 json_object_object_add(
217 cache_tlb_check_ir, "preciseIP",
218 json_object_new_boolean(cache_tlb_check->PreciseIp));
219 json_object_object_add(
220 cache_tlb_check_ir, "restartableIP",
221 json_object_new_boolean(cache_tlb_check->RestartableIp));
222 json_object_object_add(
223 cache_tlb_check_ir, "overflow",
224 json_object_new_boolean(cache_tlb_check->Overflow));
Lawrence Tang794312c2022-07-05 14:46:10 +0100225
Lawrence Tange407b4c2022-07-21 13:54:01 +0100226 return cache_tlb_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100227}
228
229//Converts a single IA32/x64 bus check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100230json_object *
231cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check)
232{
233 json_object *bus_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100234
Lawrence Tange407b4c2022-07-21 13:54:01 +0100235 //Validation bits.
236 json_object *validation =
237 bitfield_to_ir(bus_check->ValidFields, 11,
238 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
239 json_object_object_add(bus_check_ir, "validationBits", validation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100240
Lawrence Tange407b4c2022-07-21 13:54:01 +0100241 //Transaction type.
242 json_object *transaction_type = integer_to_readable_pair(
243 bus_check->TransactionType, 3,
244 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
245 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
246 "Unknown (Reserved)");
247 json_object_object_add(bus_check_ir, "transactionType",
248 transaction_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100249
Lawrence Tange407b4c2022-07-21 13:54:01 +0100250 //Operation.
251 json_object *operation = integer_to_readable_pair(
252 bus_check->Operation, 9,
253 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
254 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
255 "Unknown (Reserved)");
256 json_object_object_add(bus_check_ir, "operation", operation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100257
Lawrence Tange407b4c2022-07-21 13:54:01 +0100258 //Affected bus level.
259 json_object_object_add(bus_check_ir, "level",
260 json_object_new_uint64(bus_check->Level));
Lawrence Tang794312c2022-07-05 14:46:10 +0100261
Lawrence Tange407b4c2022-07-21 13:54:01 +0100262 //Miscellaneous boolean fields.
263 json_object_object_add(
264 bus_check_ir, "processorContextCorrupt",
265 json_object_new_boolean(bus_check->ContextCorrupt));
266 json_object_object_add(
267 bus_check_ir, "uncorrected",
268 json_object_new_boolean(bus_check->ErrorUncorrected));
269 json_object_object_add(bus_check_ir, "preciseIP",
270 json_object_new_boolean(bus_check->PreciseIp));
271 json_object_object_add(
272 bus_check_ir, "restartableIP",
273 json_object_new_boolean(bus_check->RestartableIp));
274 json_object_object_add(bus_check_ir, "overflow",
275 json_object_new_boolean(bus_check->Overflow));
276 json_object_object_add(bus_check_ir, "timedOut",
277 json_object_new_boolean(bus_check->TimeOut));
Lawrence Tang794312c2022-07-05 14:46:10 +0100278
Lawrence Tange407b4c2022-07-21 13:54:01 +0100279 //Participation type.
280 json_object *participation_type = integer_to_readable_pair(
281 bus_check->ParticipationType, 4,
282 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_KEYS,
283 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_VALUES, "Unknown");
284 json_object_object_add(bus_check_ir, "participationType",
285 participation_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100286
Lawrence Tange407b4c2022-07-21 13:54:01 +0100287 //Address space.
288 json_object *address_space = integer_to_readable_pair(
289 bus_check->AddressSpace, 4,
290 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_KEYS,
291 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
292 json_object_object_add(bus_check_ir, "addressSpace", address_space);
293
294 return bus_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100295}
296
297//Converts a single IA32/x64 MS check check info block into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100298json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check)
Lawrence Tang794312c2022-07-05 14:46:10 +0100299{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100300 json_object *ms_check_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100301
Lawrence Tange407b4c2022-07-21 13:54:01 +0100302 //Validation bits.
303 json_object *validation = bitfield_to_ir(
304 ms_check->ValidFields, 6,
305 IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES);
306 json_object_object_add(ms_check_ir, "validationBits", validation);
Lawrence Tang794312c2022-07-05 14:46:10 +0100307
Lawrence Tange407b4c2022-07-21 13:54:01 +0100308 //Error type (operation that caused the error).
309 json_object *error_type = integer_to_readable_pair(
310 ms_check->ErrorType, 4, IA32X64_MS_CHECK_INFO_ERROR_TYPES_KEYS,
311 IA32X64_MS_CHECK_INFO_ERROR_TYPES_VALUES,
312 "Unknown (Processor Specific)");
313 json_object_object_add(ms_check_ir, "errorType", error_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100314
Lawrence Tange407b4c2022-07-21 13:54:01 +0100315 //Miscellaneous fields.
316 json_object_object_add(
317 ms_check_ir, "processorContextCorrupt",
318 json_object_new_boolean(ms_check->ContextCorrupt));
319 json_object_object_add(
320 ms_check_ir, "uncorrected",
321 json_object_new_boolean(ms_check->ErrorUncorrected));
322 json_object_object_add(ms_check_ir, "preciseIP",
323 json_object_new_boolean(ms_check->PreciseIp));
324 json_object_object_add(
325 ms_check_ir, "restartableIP",
326 json_object_new_boolean(ms_check->RestartableIp));
327 json_object_object_add(ms_check_ir, "overflow",
328 json_object_new_boolean(ms_check->Overflow));
329
330 return ms_check_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100331}
332
333//Converts a single IA32/x64 processor context info entry into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100334json_object *cper_ia32x64_processor_context_info_to_ir(
335 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos)
Lawrence Tang794312c2022-07-05 14:46:10 +0100336{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100337 json_object *context_info_ir = json_object_new_object();
Lawrence Tang794312c2022-07-05 14:46:10 +0100338
Lawrence Tange407b4c2022-07-21 13:54:01 +0100339 //Register context type.
340 json_object *context_type = integer_to_readable_pair(
341 context_info->RegisterType, 8,
342 IA32X64_REGISTER_CONTEXT_TYPES_KEYS,
343 IA32X64_REGISTER_CONTEXT_TYPES_VALUES, "Unknown (Reserved)");
344 json_object_object_add(context_info_ir, "registerContextType",
345 context_type);
Lawrence Tang794312c2022-07-05 14:46:10 +0100346
Lawrence Tange407b4c2022-07-21 13:54:01 +0100347 //Register array size, MSR and MM address.
348 json_object_object_add(context_info_ir, "registerArraySize",
349 json_object_new_uint64(context_info->ArraySize));
350 json_object_object_add(
351 context_info_ir, "msrAddress",
352 json_object_new_uint64(context_info->MsrAddress));
353 json_object_object_add(
354 context_info_ir, "mmRegisterAddress",
355 json_object_new_uint64(context_info->MmRegisterAddress));
Lawrence Tang794312c2022-07-05 14:46:10 +0100356
Lawrence Tange407b4c2022-07-21 13:54:01 +0100357 //Register array.
358 json_object *register_array = NULL;
359 if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
360 EFI_CONTEXT_IA32_REGISTER_STATE *register_state =
361 (EFI_CONTEXT_IA32_REGISTER_STATE *)(context_info + 1);
362 register_array =
363 cper_ia32x64_register_32bit_to_ir(register_state);
364 *cur_pos = (void *)(register_state + 1);
365 } else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) {
366 EFI_CONTEXT_X64_REGISTER_STATE *register_state =
367 (EFI_CONTEXT_X64_REGISTER_STATE *)(context_info + 1);
368 register_array =
369 cper_ia32x64_register_64bit_to_ir(register_state);
370 *cur_pos = (void *)(register_state + 1);
371 } else {
372 //No parseable data, just dump as base64 and shift the head to the next item.
373 *cur_pos = (void *)(context_info + 1);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100374
Lawrence Tange407b4c2022-07-21 13:54:01 +0100375 char *encoded = b64_encode((unsigned char *)*cur_pos,
376 context_info->ArraySize);
377 register_array = json_object_new_object();
378 json_object_object_add(register_array, "data",
379 json_object_new_string(encoded));
380 free(encoded);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100381
Lawrence Tange407b4c2022-07-21 13:54:01 +0100382 *cur_pos =
383 (void *)(((char *)*cur_pos) + context_info->ArraySize);
384 }
385 json_object_object_add(context_info_ir, "registerArray",
386 register_array);
Lawrence Tang794312c2022-07-05 14:46:10 +0100387
Lawrence Tange407b4c2022-07-21 13:54:01 +0100388 return context_info_ir;
Lawrence Tang794312c2022-07-05 14:46:10 +0100389}
390
391//Converts a single CPER IA32 register state into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100392json_object *
393cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers)
Lawrence Tang794312c2022-07-05 14:46:10 +0100394{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100395 json_object *ia32_registers = json_object_new_object();
396 json_object_object_add(ia32_registers, "eax",
397 json_object_new_uint64(registers->Eax));
398 json_object_object_add(ia32_registers, "ebx",
399 json_object_new_uint64(registers->Ebx));
400 json_object_object_add(ia32_registers, "ecx",
401 json_object_new_uint64(registers->Ecx));
402 json_object_object_add(ia32_registers, "edx",
403 json_object_new_uint64(registers->Edx));
404 json_object_object_add(ia32_registers, "esi",
405 json_object_new_uint64(registers->Esi));
406 json_object_object_add(ia32_registers, "edi",
407 json_object_new_uint64(registers->Edi));
408 json_object_object_add(ia32_registers, "ebp",
409 json_object_new_uint64(registers->Ebp));
410 json_object_object_add(ia32_registers, "esp",
411 json_object_new_uint64(registers->Esp));
412 json_object_object_add(ia32_registers, "cs",
413 json_object_new_uint64(registers->Cs));
414 json_object_object_add(ia32_registers, "ds",
415 json_object_new_uint64(registers->Ds));
416 json_object_object_add(ia32_registers, "ss",
417 json_object_new_uint64(registers->Ss));
418 json_object_object_add(ia32_registers, "es",
419 json_object_new_uint64(registers->Es));
420 json_object_object_add(ia32_registers, "fs",
421 json_object_new_uint64(registers->Fs));
422 json_object_object_add(ia32_registers, "gs",
423 json_object_new_uint64(registers->Gs));
424 json_object_object_add(ia32_registers, "eflags",
425 json_object_new_uint64(registers->Eflags));
426 json_object_object_add(ia32_registers, "eip",
427 json_object_new_uint64(registers->Eip));
428 json_object_object_add(ia32_registers, "cr0",
429 json_object_new_uint64(registers->Cr0));
430 json_object_object_add(ia32_registers, "cr1",
431 json_object_new_uint64(registers->Cr1));
432 json_object_object_add(ia32_registers, "cr2",
433 json_object_new_uint64(registers->Cr2));
434 json_object_object_add(ia32_registers, "cr3",
435 json_object_new_uint64(registers->Cr3));
436 json_object_object_add(ia32_registers, "cr4",
437 json_object_new_uint64(registers->Cr4));
438 json_object_object_add(
439 ia32_registers, "gdtr",
440 json_object_new_uint64(registers->Gdtr[0] +
441 ((UINT64)registers->Gdtr[1] << 32)));
442 json_object_object_add(
443 ia32_registers, "idtr",
444 json_object_new_uint64(registers->Idtr[0] +
445 ((UINT64)registers->Idtr[1] << 32)));
446 json_object_object_add(ia32_registers, "ldtr",
447 json_object_new_uint64(registers->Ldtr));
448 json_object_object_add(ia32_registers, "tr",
449 json_object_new_uint64(registers->Tr));
Lawrence Tang794312c2022-07-05 14:46:10 +0100450
Lawrence Tange407b4c2022-07-21 13:54:01 +0100451 return ia32_registers;
Lawrence Tang794312c2022-07-05 14:46:10 +0100452}
453
454//Converts a single CPER x64 register state into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100455json_object *
456cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers)
Lawrence Tang794312c2022-07-05 14:46:10 +0100457{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100458 json_object *x64_registers = json_object_new_object();
459 json_object_object_add(x64_registers, "rax",
460 json_object_new_uint64(registers->Rax));
461 json_object_object_add(x64_registers, "rbx",
462 json_object_new_uint64(registers->Rbx));
463 json_object_object_add(x64_registers, "rcx",
464 json_object_new_uint64(registers->Rcx));
465 json_object_object_add(x64_registers, "rdx",
466 json_object_new_uint64(registers->Rdx));
467 json_object_object_add(x64_registers, "rsi",
468 json_object_new_uint64(registers->Rsi));
469 json_object_object_add(x64_registers, "rdi",
470 json_object_new_uint64(registers->Rdi));
471 json_object_object_add(x64_registers, "rbp",
472 json_object_new_uint64(registers->Rbp));
473 json_object_object_add(x64_registers, "rsp",
474 json_object_new_uint64(registers->Rsp));
475 json_object_object_add(x64_registers, "r8",
476 json_object_new_uint64(registers->R8));
477 json_object_object_add(x64_registers, "r9",
478 json_object_new_uint64(registers->R9));
479 json_object_object_add(x64_registers, "r10",
480 json_object_new_uint64(registers->R10));
481 json_object_object_add(x64_registers, "r11",
482 json_object_new_uint64(registers->R11));
483 json_object_object_add(x64_registers, "r12",
484 json_object_new_uint64(registers->R12));
485 json_object_object_add(x64_registers, "r13",
486 json_object_new_uint64(registers->R13));
487 json_object_object_add(x64_registers, "r14",
488 json_object_new_uint64(registers->R14));
489 json_object_object_add(x64_registers, "r15",
490 json_object_new_uint64(registers->R15));
491 json_object_object_add(x64_registers, "cs",
492 json_object_new_int(registers->Cs));
493 json_object_object_add(x64_registers, "ds",
494 json_object_new_int(registers->Ds));
495 json_object_object_add(x64_registers, "ss",
496 json_object_new_int(registers->Ss));
497 json_object_object_add(x64_registers, "es",
498 json_object_new_int(registers->Es));
499 json_object_object_add(x64_registers, "fs",
500 json_object_new_int(registers->Fs));
501 json_object_object_add(x64_registers, "gs",
502 json_object_new_int(registers->Gs));
503 json_object_object_add(x64_registers, "rflags",
504 json_object_new_uint64(registers->Rflags));
505 json_object_object_add(x64_registers, "eip",
506 json_object_new_uint64(registers->Rip));
507 json_object_object_add(x64_registers, "cr0",
508 json_object_new_uint64(registers->Cr0));
509 json_object_object_add(x64_registers, "cr1",
510 json_object_new_uint64(registers->Cr1));
511 json_object_object_add(x64_registers, "cr2",
512 json_object_new_uint64(registers->Cr2));
513 json_object_object_add(x64_registers, "cr3",
514 json_object_new_uint64(registers->Cr3));
515 json_object_object_add(x64_registers, "cr4",
516 json_object_new_uint64(registers->Cr4));
517 json_object_object_add(x64_registers, "cr8",
518 json_object_new_uint64(registers->Cr8));
519 json_object_object_add(x64_registers, "gdtr_0",
520 json_object_new_uint64(registers->Gdtr[0]));
521 json_object_object_add(x64_registers, "gdtr_1",
522 json_object_new_uint64(registers->Gdtr[1]));
523 json_object_object_add(x64_registers, "idtr_0",
524 json_object_new_uint64(registers->Idtr[0]));
525 json_object_object_add(x64_registers, "idtr_1",
526 json_object_new_uint64(registers->Idtr[1]));
527 json_object_object_add(x64_registers, "ldtr",
528 json_object_new_int(registers->Ldtr));
529 json_object_object_add(x64_registers, "tr",
530 json_object_new_int(registers->Tr));
Lawrence Tang794312c2022-07-05 14:46:10 +0100531
Lawrence Tange407b4c2022-07-21 13:54:01 +0100532 return x64_registers;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100533}
534
535//////////////////
536/// IR TO CPER ///
537//////////////////
538
539//Converts a single IA32/x64 CPER-JSON section into CPER binary, outputting to the provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100540void ir_section_ia32x64_to_cper(json_object *section, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100541{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100542 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *section_cper =
543 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)calloc(
544 1, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100545
Lawrence Tange407b4c2022-07-21 13:54:01 +0100546 //Validation bits.
547 json_object *validation =
548 json_object_object_get(section, "validationBits");
549 section_cper->ValidFields = 0x0;
550 section_cper->ValidFields |= json_object_get_boolean(
551 json_object_object_get(validation, "localAPICIDValid"));
552 section_cper->ValidFields |=
553 json_object_get_boolean(
554 json_object_object_get(validation, "cpuIDInfoValid"))
555 << 1;
556 int proc_error_info_num =
557 json_object_get_int(json_object_object_get(
558 validation, "processorErrorInfoNum")) &
559 0b111111;
560 int proc_ctx_info_num =
561 json_object_get_int(json_object_object_get(
562 validation, "processorContextInfoNum")) &
563 0b111111;
564 section_cper->ValidFields |= proc_error_info_num << 2;
565 section_cper->ValidFields |= proc_ctx_info_num << 8;
Lawrence Tangd0c88842022-07-13 14:51:17 +0100566
Lawrence Tange407b4c2022-07-21 13:54:01 +0100567 //Local APIC ID.
568 section_cper->ApicId = json_object_get_uint64(
569 json_object_object_get(section, "localAPICID"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100570
Lawrence Tange407b4c2022-07-21 13:54:01 +0100571 //CPUID info.
572 json_object *cpuid_info = json_object_object_get(section, "cpuidInfo");
573 EFI_IA32_X64_CPU_ID *cpuid_info_cper =
574 (EFI_IA32_X64_CPU_ID *)section_cper->CpuIdInfo;
575 cpuid_info_cper->Eax = json_object_get_uint64(
576 json_object_object_get(cpuid_info, "eax"));
577 cpuid_info_cper->Ebx = json_object_get_uint64(
578 json_object_object_get(cpuid_info, "ebx"));
579 cpuid_info_cper->Ecx = json_object_get_uint64(
580 json_object_object_get(cpuid_info, "ecx"));
581 cpuid_info_cper->Edx = json_object_get_uint64(
582 json_object_object_get(cpuid_info, "edx"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100583
Lawrence Tange407b4c2022-07-21 13:54:01 +0100584 //Flush the header to file before dealing w/ info sections.
585 fwrite(section_cper, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD), 1,
586 out);
587 fflush(out);
588 free(section_cper);
589
590 //Iterate and deal with sections.
591 json_object *error_info =
592 json_object_object_get(section, "processorErrorInfo");
593 json_object *context_info =
594 json_object_object_get(section, "processorContextInfo");
595 for (int i = 0; i < proc_error_info_num; i++)
596 ir_ia32x64_error_info_to_cper(
597 json_object_array_get_idx(error_info, i), out);
598 for (int i = 0; i < proc_ctx_info_num; i++)
599 ir_ia32x64_context_info_to_cper(
600 json_object_array_get_idx(context_info, i), out);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100601}
602
603//Converts a single CPER-JSON IA32/x64 error information structure into CPER binary, outputting to the
604//provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100605void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100606{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100607 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info_cper =
608 (EFI_IA32_X64_PROCESS_ERROR_INFO *)calloc(
609 1, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100610
Lawrence Tange407b4c2022-07-21 13:54:01 +0100611 //Error structure type.
612 string_to_guid(&error_info_cper->ErrorType,
613 json_object_get_string(
614 json_object_object_get(error_info, "type")));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100615
Lawrence Tange407b4c2022-07-21 13:54:01 +0100616 //Validation bits.
617 error_info_cper->ValidFields = ir_to_bitfield(
618 json_object_object_get(error_info, "validationBits"), 5,
619 IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100620
Lawrence Tange407b4c2022-07-21 13:54:01 +0100621 //Check information, parsed based on the error type.
622 json_object *check_info =
623 json_object_object_get(error_info, "checkInfo");
624 if (guid_equal(&error_info_cper->ErrorType,
625 &gEfiIa32x64ErrorTypeCacheCheckGuid) ||
626 guid_equal(&error_info_cper->ErrorType,
627 &gEfiIa32x64ErrorTypeTlbCheckGuid)) {
628 ir_ia32x64_cache_tlb_check_error_to_cper(
629 check_info,
630 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info_cper
631 ->CheckInfo);
632 } else if (guid_equal(&error_info_cper->ErrorType,
633 &gEfiIa32x64ErrorTypeBusCheckGuid))
634 ir_ia32x64_bus_check_error_to_cper(
635 check_info,
636 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info_cper
637 ->CheckInfo);
638 else if (guid_equal(&error_info_cper->ErrorType,
639 &gEfiIa32x64ErrorTypeMsCheckGuid))
640 ir_ia32x64_ms_check_error_to_cper(
641 check_info,
642 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info_cper
643 ->CheckInfo);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100644
Lawrence Tange407b4c2022-07-21 13:54:01 +0100645 //Miscellaneous numeric fields.
646 error_info_cper->TargetId = json_object_get_uint64(
647 json_object_object_get(error_info, "targetAddressID"));
648 error_info_cper->RequestorId = json_object_get_uint64(
649 json_object_object_get(error_info, "requestorID"));
650 error_info_cper->ResponderId = json_object_get_uint64(
651 json_object_object_get(error_info, "responderID"));
652 error_info_cper->InstructionIP = json_object_get_uint64(
653 json_object_object_get(error_info, "instructionPointer"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100654
Lawrence Tange407b4c2022-07-21 13:54:01 +0100655 //Write out to stream, then free resources.
656 fwrite(error_info_cper, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO), 1,
657 out);
658 fflush(out);
659 free(error_info_cper);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100660}
661
662//Converts a single CPER-JSON IA32/x64 cache/TLB check error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100663void ir_ia32x64_cache_tlb_check_error_to_cper(
664 json_object *check_info, EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100665{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100666 //Validation bits.
667 check_info_cper->ValidFields = ir_to_bitfield(
668 json_object_object_get(check_info, "validationBits"), 8,
669 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100670
Lawrence Tange407b4c2022-07-21 13:54:01 +0100671 //Transaction type, operation.
672 check_info_cper->TransactionType = readable_pair_to_integer(
673 json_object_object_get(check_info, "transactionType"));
674 check_info_cper->Operation = readable_pair_to_integer(
675 json_object_object_get(check_info, "operation"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100676
Lawrence Tange407b4c2022-07-21 13:54:01 +0100677 //Miscellaneous raw value fields.
678 check_info_cper->Level = json_object_get_uint64(
679 json_object_object_get(check_info, "level"));
680 check_info_cper->ContextCorrupt = json_object_get_boolean(
681 json_object_object_get(check_info, "processorContextCorrupt"));
682 check_info_cper->ErrorUncorrected = json_object_get_boolean(
683 json_object_object_get(check_info, "uncorrected"));
684 check_info_cper->PreciseIp = json_object_get_boolean(
685 json_object_object_get(check_info, "preciseIP"));
686 check_info_cper->RestartableIp = json_object_get_boolean(
687 json_object_object_get(check_info, "restartableIP"));
688 check_info_cper->Overflow = json_object_get_boolean(
689 json_object_object_get(check_info, "overflow"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100690}
691
692//Converts a single CPER-JSON IA32/x64 bus error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100693void ir_ia32x64_bus_check_error_to_cper(
694 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100695{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100696 //Validation bits.
697 check_info_cper->ValidFields = ir_to_bitfield(
698 json_object_object_get(check_info, "validationBits"), 11,
699 IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100700
Lawrence Tange407b4c2022-07-21 13:54:01 +0100701 //Readable pair fields.
702 check_info_cper->TransactionType = readable_pair_to_integer(
703 json_object_object_get(check_info, "transactionType"));
704 check_info_cper->Operation = readable_pair_to_integer(
705 json_object_object_get(check_info, "operation"));
706 check_info_cper->ParticipationType = readable_pair_to_integer(
707 json_object_object_get(check_info, "participationType"));
708 check_info_cper->AddressSpace = readable_pair_to_integer(
709 json_object_object_get(check_info, "addressSpace"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100710
Lawrence Tange407b4c2022-07-21 13:54:01 +0100711 //Miscellaneous raw value fields.
712 check_info_cper->Level = json_object_get_uint64(
713 json_object_object_get(check_info, "level"));
714 check_info_cper->ContextCorrupt = json_object_get_boolean(
715 json_object_object_get(check_info, "processorContextCorrupt"));
716 check_info_cper->ErrorUncorrected = json_object_get_boolean(
717 json_object_object_get(check_info, "uncorrected"));
718 check_info_cper->PreciseIp = json_object_get_boolean(
719 json_object_object_get(check_info, "preciseIP"));
720 check_info_cper->RestartableIp = json_object_get_boolean(
721 json_object_object_get(check_info, "restartableIP"));
722 check_info_cper->Overflow = json_object_get_boolean(
723 json_object_object_get(check_info, "overflow"));
724 check_info_cper->TimeOut = json_object_get_boolean(
725 json_object_object_get(check_info, "timedOut"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100726}
727
728//Converts a single CPER-JSON IA32/x64 MS error info structure to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100729void ir_ia32x64_ms_check_error_to_cper(
730 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100731{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100732 //Validation bits.
733 check_info_cper->ValidFields = ir_to_bitfield(
734 json_object_object_get(check_info, "validationBits"), 6,
735 IA32X64_CHECK_INFO_MS_CHECK_VALID_BITFIELD_NAMES);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100736
Lawrence Tange407b4c2022-07-21 13:54:01 +0100737 //Type of MS check error.
738 check_info_cper->ErrorType = readable_pair_to_integer(
739 json_object_object_get(check_info, "errorType"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100740
Lawrence Tange407b4c2022-07-21 13:54:01 +0100741 //Miscellaneous raw value fields.
742 check_info_cper->ContextCorrupt = json_object_get_boolean(
743 json_object_object_get(check_info, "processorContextCorrupt"));
744 check_info_cper->ErrorUncorrected = json_object_get_boolean(
745 json_object_object_get(check_info, "uncorrected"));
746 check_info_cper->PreciseIp = json_object_get_boolean(
747 json_object_object_get(check_info, "preciseIP"));
748 check_info_cper->RestartableIp = json_object_get_boolean(
749 json_object_object_get(check_info, "restartableIP"));
750 check_info_cper->Overflow = json_object_get_boolean(
751 json_object_object_get(check_info, "overflow"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100752}
753
754//Converts a single CPER-JSON IA32/x64 context information structure into CPER binary, outputting to the
755//provided stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100756void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100757{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100758 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info_cper =
759 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)calloc(
760 1, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100761
Lawrence Tange407b4c2022-07-21 13:54:01 +0100762 //Register context type.
763 context_info_cper->RegisterType = (UINT16)readable_pair_to_integer(
764 json_object_object_get(context_info, "registerContextType"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100765
Lawrence Tange407b4c2022-07-21 13:54:01 +0100766 //Miscellaneous numeric fields.
767 context_info_cper->ArraySize = (UINT16)json_object_get_uint64(
768 json_object_object_get(context_info, "registerArraySize"));
769 context_info_cper->MsrAddress = (UINT32)json_object_get_uint64(
770 json_object_object_get(context_info, "msrAddress"));
771 context_info_cper->MmRegisterAddress = json_object_get_uint64(
772 json_object_object_get(context_info, "mmRegisterAddress"));
Lawrence Tangd0c88842022-07-13 14:51:17 +0100773
Lawrence Tange407b4c2022-07-21 13:54:01 +0100774 //Flush header to stream.
775 fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO),
776 1, out);
777 fflush(out);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100778
Lawrence Tange407b4c2022-07-21 13:54:01 +0100779 //Handle the register array, depending on type provided.
780 json_object *register_array =
781 json_object_object_get(context_info, "registerArray");
782 if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
783 ir_ia32x64_ia32_registers_to_cper(register_array, out);
784 } else if (context_info_cper->RegisterType ==
785 EFI_REG_CONTEXT_TYPE_X64) {
786 ir_ia32x64_x64_registers_to_cper(register_array, out);
787 } else {
788 //Unknown/structure is not defined.
789 json_object *encoded =
790 json_object_object_get(register_array, "data");
791 char *decoded = b64_decode(json_object_get_string(encoded),
792 json_object_get_string_len(encoded));
793 fwrite(decoded, context_info_cper->ArraySize, 1, out);
794 fflush(out);
795 }
Lawrence Tangd0c88842022-07-13 14:51:17 +0100796
Lawrence Tange407b4c2022-07-21 13:54:01 +0100797 //Free remaining resources.
798 free(context_info_cper);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100799}
800
801//Converts a single CPER-JSON IA32 register array into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100802void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100803{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100804 EFI_CONTEXT_IA32_REGISTER_STATE register_state;
805 register_state.Eax = (UINT32)json_object_get_uint64(
806 json_object_object_get(registers, "eax"));
807 register_state.Ebx = (UINT32)json_object_get_uint64(
808 json_object_object_get(registers, "ebx"));
809 register_state.Ecx = (UINT32)json_object_get_uint64(
810 json_object_object_get(registers, "ecx"));
811 register_state.Edx = (UINT32)json_object_get_uint64(
812 json_object_object_get(registers, "edx"));
813 register_state.Esi = (UINT32)json_object_get_uint64(
814 json_object_object_get(registers, "esi"));
815 register_state.Edi = (UINT32)json_object_get_uint64(
816 json_object_object_get(registers, "edi"));
817 register_state.Ebp = (UINT32)json_object_get_uint64(
818 json_object_object_get(registers, "ebp"));
819 register_state.Esp = (UINT32)json_object_get_uint64(
820 json_object_object_get(registers, "esp"));
821 register_state.Cs = (UINT16)json_object_get_uint64(
822 json_object_object_get(registers, "cs"));
823 register_state.Ds = (UINT32)json_object_get_uint64(
824 json_object_object_get(registers, "ds"));
825 register_state.Ss = (UINT16)json_object_get_uint64(
826 json_object_object_get(registers, "ss"));
827 register_state.Es = (UINT16)json_object_get_uint64(
828 json_object_object_get(registers, "es"));
829 register_state.Fs = (UINT16)json_object_get_uint64(
830 json_object_object_get(registers, "fs"));
831 register_state.Gs = (UINT16)json_object_get_uint64(
832 json_object_object_get(registers, "gs"));
833 register_state.Eflags = (UINT32)json_object_get_uint64(
834 json_object_object_get(registers, "eflags"));
835 register_state.Eip = (UINT32)json_object_get_uint64(
836 json_object_object_get(registers, "eip"));
837 register_state.Cr0 = (UINT32)json_object_get_uint64(
838 json_object_object_get(registers, "cr0"));
839 register_state.Cr1 = (UINT32)json_object_get_uint64(
840 json_object_object_get(registers, "cr1"));
841 register_state.Cr2 = (UINT32)json_object_get_uint64(
842 json_object_object_get(registers, "cr2"));
843 register_state.Cr3 = (UINT32)json_object_get_uint64(
844 json_object_object_get(registers, "cr3"));
845 register_state.Cr4 = (UINT32)json_object_get_uint64(
846 json_object_object_get(registers, "cr4"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100847
Lawrence Tange407b4c2022-07-21 13:54:01 +0100848 //64-bit registers are split into two 32-bit parts.
849 UINT64 gdtr = json_object_get_uint64(
850 json_object_object_get(registers, "gdtr"));
851 register_state.Gdtr[0] = gdtr & 0xFFFFFFFF;
852 register_state.Gdtr[1] = gdtr >> 32;
853 UINT64 idtr = json_object_get_uint64(
854 json_object_object_get(registers, "idtr"));
855 register_state.Idtr[0] = idtr & 0xFFFFFFFF;
856 register_state.Idtr[1] = idtr >> 32;
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100857
Lawrence Tange407b4c2022-07-21 13:54:01 +0100858 //16-bit registers.
859 register_state.Ldtr = (UINT16)json_object_get_uint64(
860 json_object_object_get(registers, "ldtr"));
861 register_state.Tr = (UINT16)json_object_get_uint64(
862 json_object_object_get(registers, "tr"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100863
Lawrence Tange407b4c2022-07-21 13:54:01 +0100864 //Write out to stream.
865 fwrite(&register_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1,
866 out);
867 fflush(out);
Lawrence Tangd0c88842022-07-13 14:51:17 +0100868}
869
870//Converts a single CPER-JSON x64 register array into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100871void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tangd0c88842022-07-13 14:51:17 +0100872{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100873 EFI_CONTEXT_X64_REGISTER_STATE register_state;
874 register_state.Rax = json_object_get_uint64(
875 json_object_object_get(registers, "rax"));
876 register_state.Rbx = json_object_get_uint64(
877 json_object_object_get(registers, "rbx"));
878 register_state.Rcx = json_object_get_uint64(
879 json_object_object_get(registers, "rcx"));
880 register_state.Rdx = json_object_get_uint64(
881 json_object_object_get(registers, "rdx"));
882 register_state.Rsi = json_object_get_uint64(
883 json_object_object_get(registers, "rsi"));
884 register_state.Rdi = json_object_get_uint64(
885 json_object_object_get(registers, "rdi"));
886 register_state.Rbp = json_object_get_uint64(
887 json_object_object_get(registers, "rbp"));
888 register_state.Rsp = json_object_get_uint64(
889 json_object_object_get(registers, "rsp"));
890 register_state.R8 =
891 json_object_get_uint64(json_object_object_get(registers, "r8"));
892 register_state.R9 =
893 json_object_get_uint64(json_object_object_get(registers, "r9"));
894 register_state.R10 = json_object_get_uint64(
895 json_object_object_get(registers, "r10"));
896 register_state.R11 = json_object_get_uint64(
897 json_object_object_get(registers, "r11"));
898 register_state.R12 = json_object_get_uint64(
899 json_object_object_get(registers, "r12"));
900 register_state.R13 = json_object_get_uint64(
901 json_object_object_get(registers, "r13"));
902 register_state.R14 = json_object_get_uint64(
903 json_object_object_get(registers, "r14"));
904 register_state.R15 = json_object_get_uint64(
905 json_object_object_get(registers, "r15"));
906 register_state.Cs = (UINT16)json_object_get_int(
907 json_object_object_get(registers, "cs"));
908 register_state.Ds = (UINT16)json_object_get_int(
909 json_object_object_get(registers, "ds"));
910 register_state.Ss = (UINT16)json_object_get_int(
911 json_object_object_get(registers, "ss"));
912 register_state.Es = (UINT16)json_object_get_int(
913 json_object_object_get(registers, "es"));
914 register_state.Fs = (UINT16)json_object_get_int(
915 json_object_object_get(registers, "fs"));
916 register_state.Gs = (UINT16)json_object_get_int(
917 json_object_object_get(registers, "gs"));
918 register_state.Resv1 = 0;
919 register_state.Rflags = json_object_get_uint64(
920 json_object_object_get(registers, "rflags"));
921 register_state.Rip = json_object_get_uint64(
922 json_object_object_get(registers, "eip"));
923 register_state.Cr0 = json_object_get_uint64(
924 json_object_object_get(registers, "cr0"));
925 register_state.Cr1 = json_object_get_uint64(
926 json_object_object_get(registers, "cr1"));
927 register_state.Cr2 = json_object_get_uint64(
928 json_object_object_get(registers, "cr2"));
929 register_state.Cr3 = json_object_get_uint64(
930 json_object_object_get(registers, "cr3"));
931 register_state.Cr4 = json_object_get_uint64(
932 json_object_object_get(registers, "cr4"));
933 register_state.Cr8 = json_object_get_uint64(
934 json_object_object_get(registers, "cr8"));
935 register_state.Gdtr[0] = json_object_get_uint64(
936 json_object_object_get(registers, "gdtr_0"));
937 register_state.Gdtr[1] = json_object_get_uint64(
938 json_object_object_get(registers, "gdtr_1"));
939 register_state.Idtr[0] = json_object_get_uint64(
940 json_object_object_get(registers, "idtr_0"));
941 register_state.Idtr[1] = json_object_get_uint64(
942 json_object_object_get(registers, "idtr_1"));
943 register_state.Ldtr = (UINT16)json_object_get_int(
944 json_object_object_get(registers, "ldtr"));
945 register_state.Tr = (UINT16)json_object_get_int(
946 json_object_object_get(registers, "tr"));
Lawrence Tangbd9a84a2022-07-13 15:41:16 +0100947
Lawrence Tange407b4c2022-07-21 13:54:01 +0100948 //Write out to stream.
949 fwrite(&register_state, sizeof(EFI_CONTEXT_X64_REGISTER_STATE), 1, out);
950 fflush(out);
Lawrence Tang794312c2022-07-05 14:46:10 +0100951}