1 /**
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>
10 #include <libcper/base64.h>
11 #include <libcper/Cper.h>
12 #include <libcper/cper-utils.h>
13 #include <libcper/sections/cper-section-ia32x64.h>
14 #include <libcper/log.h>
15 #include <string.h>
16
17 //Private pre-definitions.
18 json_object *cper_ia32x64_processor_error_info_to_ir(
19 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info);
20 json_object *cper_ia32x64_cache_tlb_check_to_ir(
21 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check);
22 json_object *
23 cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check);
24 json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check);
25 json_object *cper_ia32x64_processor_context_info_to_ir(
26 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos,
27 UINT32 *remaining_size);
28 json_object *
29 cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers);
30 json_object *
31 cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers);
32 void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out);
33 void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out);
34 void ir_ia32x64_cache_tlb_check_error_to_cper(
35 json_object *check_info,
36 EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper);
37 void ir_ia32x64_bus_check_error_to_cper(
38 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper);
39 void ir_ia32x64_ms_check_error_to_cper(
40 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper);
41 void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out);
42 void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out);
43
44 //////////////////
45 /// CPER TO IR ///
46 //////////////////
47
48 //Converts the IA32/x64 error section described in the given descriptor into intermediate format.
cper_section_ia32x64_to_ir(const UINT8 * section,UINT32 size,char ** desc_string)49 json_object *cper_section_ia32x64_to_ir(const UINT8 *section, UINT32 size,
50 char **desc_string)
51 {
52 int outstr_len = 0;
53
54 *desc_string = NULL;
55 if (size < sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD)) {
56 cper_print_log("Error: IA32/x64 section too small\n");
57 return NULL;
58 }
59
60 *desc_string = calloc(1, SECTION_DESC_STRING_SIZE);
61 if (*desc_string == NULL) {
62 cper_print_log(
63 "Error: Failed to allocate IA32/x64 desc string\n");
64 return NULL;
65 }
66 outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
67 "An IA32/x64 Processor Error occurred");
68 if (outstr_len < 0) {
69 cper_print_log(
70 "Error: Could not write to IA32/x64 description string\n");
71 } else if (outstr_len > SECTION_DESC_STRING_SIZE) {
72 cper_print_log(
73 "Error: IA32/x64 description string truncated\n");
74 }
75 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *record =
76 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)section;
77 UINT32 remaining_size =
78 size - sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD);
79 json_object *record_ir = json_object_new_object();
80
81 //Validation bits.
82 //validation bits contain information
83 //about processorErrorInfoNum and processorContextInfoNum.
84 //Ensure this is decoded properly in IR->CPER
85 int processor_error_info_num = (record->ValidFields >> 2) & 0x3F;
86 add_int(record_ir, "processorErrorInfoNum", processor_error_info_num);
87 int processor_context_info_num = (record->ValidFields >> 8) & 0x3F;
88 add_int(record_ir, "processorContextInfoNum",
89 processor_context_info_num);
90
91 ValidationTypes ui64Type = { UINT_64T,
92 .value.ui64 = record->ValidFields };
93
94 //APIC ID.
95 if (isvalid_prop_to_ir(&ui64Type, 0)) {
96 add_uint(record_ir, "localAPICID", record->ApicId);
97 }
98
99 //CPUID information.
100 if (isvalid_prop_to_ir(&ui64Type, 1)) {
101 json_object *cpuid_info_ir = json_object_new_object();
102 EFI_IA32_X64_CPU_ID *cpuid_info =
103 (EFI_IA32_X64_CPU_ID *)record->CpuIdInfo;
104 add_uint(cpuid_info_ir, "eax", cpuid_info->Eax);
105 add_uint(cpuid_info_ir, "ebx", cpuid_info->Ebx);
106 add_uint(cpuid_info_ir, "ecx", cpuid_info->Ecx);
107 add_uint(cpuid_info_ir, "edx", cpuid_info->Edx);
108 json_object_object_add(record_ir, "cpuidInfo", cpuid_info_ir);
109 }
110
111 //Processor error information, of the amount described above.
112 EFI_IA32_X64_PROCESS_ERROR_INFO *current_error_info =
113 (EFI_IA32_X64_PROCESS_ERROR_INFO *)(record + 1);
114 json_object *error_info_array = json_object_new_array();
115 if (remaining_size < (processor_error_info_num *
116 sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO))) {
117 json_object_put(error_info_array);
118 json_object_put(record_ir);
119 free(*desc_string);
120 *desc_string = NULL;
121 cper_print_log(
122 "Invalid CPER file: Invalid processor error info num.\n");
123 return NULL;
124 }
125
126 for (int i = 0; i < processor_error_info_num; i++) {
127 json_object_array_add(error_info_array,
128 cper_ia32x64_processor_error_info_to_ir(
129 current_error_info));
130 current_error_info++;
131 }
132 remaining_size -= processor_error_info_num *
133 sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO);
134
135 json_object_object_add(record_ir, "processorErrorInfo",
136 error_info_array);
137
138 //Processor context information, of the amount described above.
139 if (remaining_size < (processor_context_info_num *
140 sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO))) {
141 json_object_put(record_ir);
142 free(*desc_string);
143 *desc_string = NULL;
144 cper_print_log(
145 "Invalid CPER file: Invalid processor context info num.\n");
146 return NULL;
147 }
148 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *current_context_info =
149 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)current_error_info;
150 void *cur_pos = (void *)current_context_info;
151 json_object *context_info_array = json_object_new_array();
152 for (int i = 0; i < processor_context_info_num; i++) {
153 json_object *context_info =
154 cper_ia32x64_processor_context_info_to_ir(
155 current_context_info, &cur_pos,
156 &remaining_size);
157 json_object_array_add(context_info_array, context_info);
158 current_context_info =
159 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)cur_pos;
160
161 //The context array is a non-fixed size, pointer is shifted within the above function.
162 }
163
164 json_object_object_add(record_ir, "processorContextInfo",
165 context_info_array);
166
167 return record_ir;
168 }
169
170 EFI_GUID *gEfiIa32x64ErrorTypeGuids[] = {
171 &gEfiIa32x64ErrorTypeCacheCheckGuid,
172 &gEfiIa32x64ErrorTypeTlbCheckGuid,
173 &gEfiIa32x64ErrorTypeBusCheckGuid,
174 &gEfiIa32x64ErrorTypeMsCheckGuid,
175 };
176
177 //Converts a single IA32/x64 processor error info block into JSON IR format.
cper_ia32x64_processor_error_info_to_ir(EFI_IA32_X64_PROCESS_ERROR_INFO * error_info)178 json_object *cper_ia32x64_processor_error_info_to_ir(
179 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info)
180 {
181 json_object *error_info_ir = json_object_new_object();
182 json_object *type = json_object_new_object();
183
184 //Error structure type (as GUID).
185 add_guid(type, "guid", &error_info->ErrorType);
186
187 //Get the error structure type as a readable string.
188 const char *readable_type = "Unknown";
189
190 const char *readable_names[] = {
191 "Cache Check Error",
192 "TLB Check Error",
193 "Bus Check Error",
194 "MS Check Error",
195 };
196
197 int index = select_guid_from_list(
198 &error_info->ErrorType, gEfiIa32x64ErrorTypeGuids,
199 sizeof(gEfiIa32x64ErrorTypeGuids) / sizeof(EFI_GUID *));
200
201 if (index < (int)(sizeof(readable_names) / sizeof(char *))) {
202 readable_type = readable_names[index];
203 }
204
205 add_string(type, "name", readable_type);
206 json_object_object_add(error_info_ir, "type", type);
207
208 //Validation bits.
209 ValidationTypes ui64Type = { UINT_64T,
210 .value.ui64 = error_info->ValidFields };
211
212 //Add the check information on a per-structure basis.
213 //Cache and TLB check information are identical, so can be equated.
214 if (isvalid_prop_to_ir(&ui64Type, 0)) {
215 json_object *check_information = NULL;
216
217 switch (index) {
218 case 0:
219 case 1:
220 check_information = cper_ia32x64_cache_tlb_check_to_ir(
221 (EFI_IA32_X64_CACHE_CHECK_INFO *)&error_info
222 ->CheckInfo);
223 break;
224 case 2:
225 check_information = cper_ia32x64_bus_check_to_ir(
226 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info
227 ->CheckInfo);
228 break;
229 case 3:
230 check_information = cper_ia32x64_ms_check_to_ir(
231 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info
232 ->CheckInfo);
233 break;
234 default:
235 //Unknown check information.
236 cper_print_log(
237 "WARN: Invalid/unknown check information GUID found in IA32/x64 CPER section. Ignoring.\n");
238 break;
239 }
240 if (check_information != NULL) {
241 json_object_object_add(error_info_ir, "checkInfo",
242 check_information);
243 }
244 }
245
246 //Target, requestor, and responder identifiers.
247 if (isvalid_prop_to_ir(&ui64Type, 1)) {
248 add_uint(error_info_ir, "targetAddressID",
249 error_info->TargetId);
250 }
251 if (isvalid_prop_to_ir(&ui64Type, 2)) {
252 add_uint(error_info_ir, "requestorID", error_info->RequestorId);
253 }
254 if (isvalid_prop_to_ir(&ui64Type, 3)) {
255 add_uint(error_info_ir, "responderID", error_info->ResponderId);
256 }
257 if (isvalid_prop_to_ir(&ui64Type, 4)) {
258 add_uint(error_info_ir, "instructionPointer",
259 error_info->InstructionIP);
260 }
261
262 return error_info_ir;
263 }
264
265 //Converts a single IA32/x64 cache or TLB check check info block into JSON IR format.
cper_ia32x64_cache_tlb_check_to_ir(EFI_IA32_X64_CACHE_CHECK_INFO * cache_tlb_check)266 json_object *cper_ia32x64_cache_tlb_check_to_ir(
267 EFI_IA32_X64_CACHE_CHECK_INFO *cache_tlb_check)
268 {
269 json_object *cache_tlb_check_ir = json_object_new_object();
270
271 //Validation bits.
272 ValidationTypes ui64Type = {
273 UINT_64T, .value.ui64 = cache_tlb_check->ValidFields
274 };
275
276 //Transaction type.
277 if (isvalid_prop_to_ir(&ui64Type, 0)) {
278 json_object *transaction_type = integer_to_readable_pair(
279 cache_tlb_check->TransactionType, 3,
280 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
281 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
282 "Unknown (Reserved)");
283 json_object_object_add(cache_tlb_check_ir, "transactionType",
284 transaction_type);
285 }
286
287 //Operation.
288 if (isvalid_prop_to_ir(&ui64Type, 1)) {
289 json_object *operation = integer_to_readable_pair(
290 cache_tlb_check->Operation, 9,
291 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
292 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
293 "Unknown (Reserved)");
294 json_object_object_add(cache_tlb_check_ir, "operation",
295 operation);
296 }
297
298 //Affected cache/TLB level.
299 if (isvalid_prop_to_ir(&ui64Type, 2)) {
300 add_uint(cache_tlb_check_ir, "level", cache_tlb_check->Level);
301 }
302
303 //Miscellaneous boolean fields.
304 if (isvalid_prop_to_ir(&ui64Type, 3)) {
305 add_bool(cache_tlb_check_ir, "processorContextCorrupt",
306 cache_tlb_check->ContextCorrupt);
307 }
308 if (isvalid_prop_to_ir(&ui64Type, 4)) {
309 add_bool(cache_tlb_check_ir, "uncorrected",
310 cache_tlb_check->ErrorUncorrected);
311 }
312 if (isvalid_prop_to_ir(&ui64Type, 5)) {
313 add_bool(cache_tlb_check_ir, "preciseIP",
314 cache_tlb_check->PreciseIp);
315 }
316 if (isvalid_prop_to_ir(&ui64Type, 6)) {
317 add_bool(cache_tlb_check_ir, "restartableIP",
318 cache_tlb_check->RestartableIp);
319 }
320 if (isvalid_prop_to_ir(&ui64Type, 7)) {
321 add_bool(cache_tlb_check_ir, "overflow",
322 cache_tlb_check->Overflow);
323 }
324
325 return cache_tlb_check_ir;
326 }
327
328 //Converts a single IA32/x64 bus check check info block into JSON IR format.
329 json_object *
cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO * bus_check)330 cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check)
331 {
332 json_object *bus_check_ir = json_object_new_object();
333
334 //Validation bits.
335 ValidationTypes ui64Type = { UINT_64T,
336 .value.ui64 = bus_check->ValidFields };
337
338 //Transaction type.
339 if (isvalid_prop_to_ir(&ui64Type, 0)) {
340 json_object *transaction_type = integer_to_readable_pair(
341 bus_check->TransactionType, 3,
342 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS,
343 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES,
344 "Unknown (Reserved)");
345 json_object_object_add(bus_check_ir, "transactionType",
346 transaction_type);
347 }
348
349 //Operation.
350 if (isvalid_prop_to_ir(&ui64Type, 1)) {
351 json_object *operation = integer_to_readable_pair(
352 bus_check->Operation, 9,
353 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS,
354 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES,
355 "Unknown (Reserved)");
356 json_object_object_add(bus_check_ir, "operation", operation);
357 }
358
359 //Affected bus level.
360 if (isvalid_prop_to_ir(&ui64Type, 2)) {
361 add_uint(bus_check_ir, "level", bus_check->Level);
362 }
363
364 //Miscellaneous boolean fields.
365 if (isvalid_prop_to_ir(&ui64Type, 3)) {
366 add_bool(bus_check_ir, "processorContextCorrupt",
367 bus_check->ContextCorrupt);
368 }
369 if (isvalid_prop_to_ir(&ui64Type, 4)) {
370 add_bool(bus_check_ir, "uncorrected",
371 bus_check->ErrorUncorrected);
372 }
373 if (isvalid_prop_to_ir(&ui64Type, 5)) {
374 add_bool(bus_check_ir, "preciseIP", bus_check->PreciseIp);
375 }
376 if (isvalid_prop_to_ir(&ui64Type, 6)) {
377 add_bool(bus_check_ir, "restartableIP",
378 bus_check->RestartableIp);
379 }
380 if (isvalid_prop_to_ir(&ui64Type, 7)) {
381 add_bool(bus_check_ir, "overflow", bus_check->Overflow);
382 }
383 if (isvalid_prop_to_ir(&ui64Type, 9)) {
384 add_bool(bus_check_ir, "timedOut", bus_check->TimeOut);
385 }
386
387 //Participation type.
388 if (isvalid_prop_to_ir(&ui64Type, 8)) {
389 json_object *participation_type = integer_to_readable_pair(
390 bus_check->ParticipationType, 4,
391 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_KEYS,
392 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_VALUES,
393 "Unknown");
394 json_object_object_add(bus_check_ir, "participationType",
395 participation_type);
396 }
397
398 //Address space.
399 if (isvalid_prop_to_ir(&ui64Type, 10)) {
400 json_object *address_space = integer_to_readable_pair(
401 bus_check->AddressSpace, 4,
402 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_KEYS,
403 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_VALUES,
404 "Unknown");
405 json_object_object_add(bus_check_ir, "addressSpace",
406 address_space);
407 }
408
409 return bus_check_ir;
410 }
411
412 //Converts a single IA32/x64 MS check check info block into JSON IR format.
cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO * ms_check)413 json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check)
414 {
415 json_object *ms_check_ir = json_object_new_object();
416 ValidationTypes ui64Type = { UINT_64T,
417 .value.ui64 = ms_check->ValidFields };
418 //Validation bits.
419 //Error type (operation that caused the error).
420 if (isvalid_prop_to_ir(&ui64Type, 0)) {
421 json_object *error_type = integer_to_readable_pair(
422 ms_check->ErrorType, 4,
423 IA32X64_MS_CHECK_INFO_ERROR_TYPES_KEYS,
424 IA32X64_MS_CHECK_INFO_ERROR_TYPES_VALUES,
425 "Unknown (Processor Specific)");
426 json_object_object_add(ms_check_ir, "errorType", error_type);
427 }
428
429 //Miscellaneous fields.
430 if (isvalid_prop_to_ir(&ui64Type, 1)) {
431 add_bool(ms_check_ir, "processorContextCorrupt",
432 ms_check->ContextCorrupt);
433 }
434 if (isvalid_prop_to_ir(&ui64Type, 2)) {
435 add_bool(ms_check_ir, "uncorrected",
436 ms_check->ErrorUncorrected);
437 }
438 if (isvalid_prop_to_ir(&ui64Type, 3)) {
439 add_bool(ms_check_ir, "preciseIP", ms_check->PreciseIp);
440 }
441 if (isvalid_prop_to_ir(&ui64Type, 4)) {
442 add_bool(ms_check_ir, "restartableIP", ms_check->RestartableIp);
443 }
444 if (isvalid_prop_to_ir(&ui64Type, 5)) {
445 add_bool(ms_check_ir, "overflow", ms_check->Overflow);
446 }
447
448 return ms_check_ir;
449 }
450
451 //Converts a single IA32/x64 processor context info entry into JSON IR format.
cper_ia32x64_processor_context_info_to_ir(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO * context_info,void ** cur_pos,UINT32 * remaining_size)452 json_object *cper_ia32x64_processor_context_info_to_ir(
453 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos,
454 UINT32 *remaining_size)
455 {
456 if (*remaining_size < sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO)) {
457 return NULL;
458 }
459 *remaining_size -= sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO);
460 json_object *context_info_ir = json_object_new_object();
461
462 //Register context type.
463 json_object *context_type = integer_to_readable_pair(
464 context_info->RegisterType, IA32X64_REGISTER_CONTEXT_TYPES_SIZE,
465 IA32X64_REGISTER_CONTEXT_TYPES_KEYS,
466 IA32X64_REGISTER_CONTEXT_TYPES_VALUES, "Unknown (Reserved)");
467 json_object_object_add(context_info_ir, "registerContextType",
468 context_type);
469
470 //Register array size, MSR and MM address.
471 add_uint(context_info_ir, "registerArraySize", context_info->ArraySize);
472 add_uint(context_info_ir, "msrAddress", context_info->MsrAddress);
473 add_uint(context_info_ir, "mmRegisterAddress",
474 context_info->MmRegisterAddress);
475
476 //Register array.
477 json_object *register_array = NULL;
478 if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
479 if (*remaining_size < sizeof(EFI_CONTEXT_IA32_REGISTER_STATE)) {
480 return context_info_ir;
481 }
482 EFI_CONTEXT_IA32_REGISTER_STATE *register_state =
483 (EFI_CONTEXT_IA32_REGISTER_STATE *)(context_info + 1);
484 register_array =
485 cper_ia32x64_register_32bit_to_ir(register_state);
486 *cur_pos = (void *)(register_state + 1);
487 *remaining_size -= sizeof(EFI_CONTEXT_IA32_REGISTER_STATE);
488 } else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) {
489 if (*remaining_size < sizeof(EFI_CONTEXT_X64_REGISTER_STATE)) {
490 return context_info_ir;
491 }
492 EFI_CONTEXT_X64_REGISTER_STATE *register_state =
493 (EFI_CONTEXT_X64_REGISTER_STATE *)(context_info + 1);
494 register_array =
495 cper_ia32x64_register_64bit_to_ir(register_state);
496 *cur_pos = (void *)(register_state + 1);
497 *remaining_size -= sizeof(EFI_CONTEXT_X64_REGISTER_STATE);
498 } else {
499 //No parseable data, just dump as base64 and shift the head to the next item.
500 *cur_pos = (void *)(context_info + 1);
501 if (*remaining_size < context_info->ArraySize) {
502 return context_info_ir;
503 }
504 register_array = json_object_new_object();
505 add_binary_base64(register_array, "data", (UINT8 *)*cur_pos,
506 context_info->ArraySize);
507
508 *cur_pos =
509 (void *)(((char *)*cur_pos) + context_info->ArraySize);
510 *remaining_size -= context_info->ArraySize;
511 }
512 if (register_array != NULL) {
513 json_object_object_add(context_info_ir, "registerArray",
514 register_array);
515 }
516
517 return context_info_ir;
518 }
519
520 //Converts a single CPER IA32 register state into JSON IR format.
521 json_object *
cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE * registers)522 cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers)
523 {
524 json_object *ia32_registers = json_object_new_object();
525 add_uint(ia32_registers, "eax", registers->Eax);
526 add_uint(ia32_registers, "ebx", registers->Ebx);
527 add_uint(ia32_registers, "ecx", registers->Ecx);
528 add_uint(ia32_registers, "edx", registers->Edx);
529 add_uint(ia32_registers, "esi", registers->Esi);
530 add_uint(ia32_registers, "edi", registers->Edi);
531 add_uint(ia32_registers, "ebp", registers->Ebp);
532 add_uint(ia32_registers, "esp", registers->Esp);
533 add_uint(ia32_registers, "cs", registers->Cs);
534 add_uint(ia32_registers, "ds", registers->Ds);
535 add_uint(ia32_registers, "ss", registers->Ss);
536 add_uint(ia32_registers, "es", registers->Es);
537 add_uint(ia32_registers, "fs", registers->Fs);
538 add_uint(ia32_registers, "gs", registers->Gs);
539 add_uint(ia32_registers, "eflags", registers->Eflags);
540 add_uint(ia32_registers, "eip", registers->Eip);
541 add_uint(ia32_registers, "cr0", registers->Cr0);
542 add_uint(ia32_registers, "cr1", registers->Cr1);
543 add_uint(ia32_registers, "cr2", registers->Cr2);
544 add_uint(ia32_registers, "cr3", registers->Cr3);
545 add_uint(ia32_registers, "cr4", registers->Cr4);
546 add_uint(ia32_registers, "gdtr",
547 registers->Gdtr[0] + ((UINT64)registers->Gdtr[1] << 32));
548 add_uint(ia32_registers, "idtr",
549 registers->Idtr[0] + ((UINT64)registers->Idtr[1] << 32));
550 add_uint(ia32_registers, "ldtr", registers->Ldtr);
551 add_uint(ia32_registers, "tr", registers->Tr);
552
553 return ia32_registers;
554 }
555
556 //Converts a single CPER x64 register state into JSON IR format.
557 json_object *
cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE * registers)558 cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE *registers)
559 {
560 json_object *x64_registers = json_object_new_object();
561 add_uint(x64_registers, "rax", registers->Rax);
562 add_uint(x64_registers, "rbx", registers->Rbx);
563 add_uint(x64_registers, "rcx", registers->Rcx);
564 add_uint(x64_registers, "rdx", registers->Rdx);
565 add_uint(x64_registers, "rsi", registers->Rsi);
566 add_uint(x64_registers, "rdi", registers->Rdi);
567 add_uint(x64_registers, "rbp", registers->Rbp);
568 add_uint(x64_registers, "rsp", registers->Rsp);
569 add_uint(x64_registers, "r8", registers->R8);
570 add_uint(x64_registers, "r9", registers->R9);
571 add_uint(x64_registers, "r10", registers->R10);
572 add_uint(x64_registers, "r11", registers->R11);
573 add_uint(x64_registers, "r12", registers->R12);
574 add_uint(x64_registers, "r13", registers->R13);
575 add_uint(x64_registers, "r14", registers->R14);
576 add_uint(x64_registers, "r15", registers->R15);
577 add_int(x64_registers, "cs", registers->Cs);
578 add_int(x64_registers, "ds", registers->Ds);
579 add_int(x64_registers, "ss", registers->Ss);
580 add_int(x64_registers, "es", registers->Es);
581 add_int(x64_registers, "fs", registers->Fs);
582 add_int(x64_registers, "gs", registers->Gs);
583 add_uint(x64_registers, "rflags", registers->Rflags);
584 add_uint(x64_registers, "eip", registers->Rip);
585 add_uint(x64_registers, "cr0", registers->Cr0);
586 add_uint(x64_registers, "cr1", registers->Cr1);
587 add_uint(x64_registers, "cr2", registers->Cr2);
588 add_uint(x64_registers, "cr3", registers->Cr3);
589 add_uint(x64_registers, "cr4", registers->Cr4);
590 add_uint(x64_registers, "cr8", registers->Cr8);
591 add_uint(x64_registers, "gdtr_0", registers->Gdtr[0]);
592 add_uint(x64_registers, "gdtr_1", registers->Gdtr[1]);
593 add_uint(x64_registers, "idtr_0", registers->Idtr[0]);
594 add_uint(x64_registers, "idtr_1", registers->Idtr[1]);
595 add_int(x64_registers, "ldtr", registers->Ldtr);
596 add_int(x64_registers, "tr", registers->Tr);
597
598 return x64_registers;
599 }
600
601 //////////////////
602 /// IR TO CPER ///
603 //////////////////
604
605 //Converts a single IA32/x64 CPER-JSON section into CPER binary, outputting to the provided stream.
ir_section_ia32x64_to_cper(json_object * section,FILE * out)606 void ir_section_ia32x64_to_cper(json_object *section, FILE *out)
607 {
608 EFI_IA32_X64_PROCESSOR_ERROR_RECORD *section_cper =
609 (EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)calloc(
610 1, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD));
611
612 uint64_t valid = 0x0;
613
614 int proc_error_info_num = json_object_get_int(json_object_object_get(
615 section, "processorErrorInfoNum")) &
616 0x3F;
617 int proc_ctx_info_num = json_object_get_int(json_object_object_get(
618 section, "processorContextInfoNum")) &
619 0x3F;
620 valid |= proc_error_info_num << 2;
621 valid |= proc_ctx_info_num << 8;
622
623 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = valid };
624 struct json_object *obj = NULL;
625
626 //Local APIC ID.
627 if (json_object_object_get_ex(section, "localAPICID", &obj)) {
628 section_cper->ApicId = json_object_get_uint64(obj);
629 add_to_valid_bitfield(&ui64Type, 0);
630 }
631
632 //CPUID info.
633 if (json_object_object_get_ex(section, "cpuidInfo", &obj)) {
634 json_object *cpuid_info = obj;
635 EFI_IA32_X64_CPU_ID *cpuid_info_cper =
636 (EFI_IA32_X64_CPU_ID *)section_cper->CpuIdInfo;
637 cpuid_info_cper->Eax = json_object_get_uint64(
638 json_object_object_get(cpuid_info, "eax"));
639 cpuid_info_cper->Ebx = json_object_get_uint64(
640 json_object_object_get(cpuid_info, "ebx"));
641 cpuid_info_cper->Ecx = json_object_get_uint64(
642 json_object_object_get(cpuid_info, "ecx"));
643 cpuid_info_cper->Edx = json_object_get_uint64(
644 json_object_object_get(cpuid_info, "edx"));
645 add_to_valid_bitfield(&ui64Type, 1);
646 }
647 section_cper->ValidFields = ui64Type.value.ui64;
648
649 //Flush the header to file before dealing w/ info sections.
650 fwrite(section_cper, sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD), 1,
651 out);
652 fflush(out);
653 free(section_cper);
654
655 //Iterate and deal with sections.
656 json_object *error_info =
657 json_object_object_get(section, "processorErrorInfo");
658 json_object *context_info =
659 json_object_object_get(section, "processorContextInfo");
660 for (int i = 0; i < proc_error_info_num; i++) {
661 ir_ia32x64_error_info_to_cper(
662 json_object_array_get_idx(error_info, i), out);
663 }
664 for (int i = 0; i < proc_ctx_info_num; i++) {
665 ir_ia32x64_context_info_to_cper(
666 json_object_array_get_idx(context_info, i), out);
667 }
668 }
669
670 //Converts a single CPER-JSON IA32/x64 error information structure into CPER binary, outputting to the
671 //provided stream.
ir_ia32x64_error_info_to_cper(json_object * error_info,FILE * out)672 void ir_ia32x64_error_info_to_cper(json_object *error_info, FILE *out)
673 {
674 EFI_IA32_X64_PROCESS_ERROR_INFO *error_info_cper =
675 (EFI_IA32_X64_PROCESS_ERROR_INFO *)calloc(
676 1, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO));
677
678 //Error structure type.
679 json_object *type = json_object_object_get(error_info, "type");
680 string_to_guid(
681 &error_info_cper->ErrorType,
682 json_object_get_string(json_object_object_get(type, "guid")));
683
684 //Validation bits.
685 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
686 struct json_object *obj = NULL;
687
688 //Check information, parsed based on the error type.
689 if (json_object_object_get_ex(error_info, "checkInfo", &obj)) {
690 json_object *check_info = obj;
691
692 int index = select_guid_from_list(
693 &error_info_cper->ErrorType, gEfiIa32x64ErrorTypeGuids,
694 sizeof(gEfiIa32x64ErrorTypeGuids) / sizeof(EFI_GUID *));
695
696 switch (index) {
697 case 0:
698 case 1:
699 ir_ia32x64_cache_tlb_check_error_to_cper(
700 check_info,
701 (EFI_IA32_X64_CACHE_CHECK_INFO
702 *)&error_info_cper->CheckInfo);
703 break;
704 case 2:
705 ir_ia32x64_bus_check_error_to_cper(
706 check_info,
707 (EFI_IA32_X64_BUS_CHECK_INFO *)&error_info_cper
708 ->CheckInfo);
709 break;
710 case 3:
711 ir_ia32x64_ms_check_error_to_cper(
712 check_info,
713 (EFI_IA32_X64_MS_CHECK_INFO *)&error_info_cper
714 ->CheckInfo);
715 break;
716 default:
717 //Unknown check information.
718 cper_print_log(
719 "WARN: Invalid/unknown check information GUID found in IA32/x64 CPER section. Ignoring.\n");
720 break;
721 }
722 add_to_valid_bitfield(&ui64Type, 0);
723 }
724
725 //Miscellaneous numeric fields.
726 if (json_object_object_get_ex(error_info, "targetAddressID", &obj)) {
727 error_info_cper->TargetId = json_object_get_uint64(obj);
728 add_to_valid_bitfield(&ui64Type, 1);
729 }
730 if (json_object_object_get_ex(error_info, "requestorID", &obj)) {
731 error_info_cper->RequestorId = json_object_get_uint64(obj);
732 add_to_valid_bitfield(&ui64Type, 2);
733 }
734 if (json_object_object_get_ex(error_info, "responderID", &obj)) {
735 error_info_cper->ResponderId = json_object_get_uint64(obj);
736 add_to_valid_bitfield(&ui64Type, 3);
737 }
738 if (json_object_object_get_ex(error_info, "instructionPointer", &obj)) {
739 error_info_cper->InstructionIP = json_object_get_uint64(obj);
740 add_to_valid_bitfield(&ui64Type, 4);
741 }
742
743 error_info_cper->ValidFields = ui64Type.value.ui64;
744 //Write out to stream, then free resources.
745 fwrite(error_info_cper, sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO), 1,
746 out);
747 fflush(out);
748 free(error_info_cper);
749 }
750
751 //Converts a single CPER-JSON IA32/x64 cache/TLB check error info structure to CPER binary.
ir_ia32x64_cache_tlb_check_error_to_cper(json_object * check_info,EFI_IA32_X64_CACHE_CHECK_INFO * check_info_cper)752 void ir_ia32x64_cache_tlb_check_error_to_cper(
753 json_object *check_info, EFI_IA32_X64_CACHE_CHECK_INFO *check_info_cper)
754 {
755 //Validation bits.
756 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
757 struct json_object *obj = NULL;
758
759 //Transaction type, operation.
760 if (json_object_object_get_ex(check_info, "transactionType", &obj)) {
761 check_info_cper->TransactionType =
762 readable_pair_to_integer(obj);
763 add_to_valid_bitfield(&ui64Type, 0);
764 }
765 if (json_object_object_get_ex(check_info, "operation", &obj)) {
766 check_info_cper->Operation = readable_pair_to_integer(obj);
767 add_to_valid_bitfield(&ui64Type, 1);
768 }
769
770 //Miscellaneous raw value fields.
771 if (json_object_object_get_ex(check_info, "level", &obj)) {
772 check_info_cper->Level = json_object_get_uint64(obj);
773 add_to_valid_bitfield(&ui64Type, 2);
774 }
775 if (json_object_object_get_ex(check_info, "processorContextCorrupt",
776 &obj)) {
777 check_info_cper->ContextCorrupt = json_object_get_boolean(obj);
778 add_to_valid_bitfield(&ui64Type, 3);
779 }
780 if (json_object_object_get_ex(check_info, "uncorrected", &obj)) {
781 check_info_cper->ErrorUncorrected =
782 json_object_get_boolean(obj);
783 add_to_valid_bitfield(&ui64Type, 4);
784 }
785 if (json_object_object_get_ex(check_info, "preciseIP", &obj)) {
786 check_info_cper->PreciseIp = json_object_get_boolean(obj);
787 add_to_valid_bitfield(&ui64Type, 5);
788 }
789 if (json_object_object_get_ex(check_info, "restartableIP", &obj)) {
790 check_info_cper->RestartableIp = json_object_get_boolean(obj);
791 add_to_valid_bitfield(&ui64Type, 6);
792 }
793 if (json_object_object_get_ex(check_info, "overflow", &obj)) {
794 check_info_cper->Overflow = json_object_get_boolean(obj);
795 add_to_valid_bitfield(&ui64Type, 7);
796 }
797 check_info_cper->ValidFields = ui64Type.value.ui64;
798 }
799
800 //Converts a single CPER-JSON IA32/x64 bus error info structure to CPER binary.
ir_ia32x64_bus_check_error_to_cper(json_object * check_info,EFI_IA32_X64_BUS_CHECK_INFO * check_info_cper)801 void ir_ia32x64_bus_check_error_to_cper(
802 json_object *check_info, EFI_IA32_X64_BUS_CHECK_INFO *check_info_cper)
803 {
804 //Validation bits.
805 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
806 struct json_object *obj = NULL;
807
808 //Readable pair fields.
809 if (json_object_object_get_ex(check_info, "transactionType", &obj)) {
810 check_info_cper->TransactionType =
811 readable_pair_to_integer(obj);
812 add_to_valid_bitfield(&ui64Type, 0);
813 }
814 if (json_object_object_get_ex(check_info, "operation", &obj)) {
815 check_info_cper->Operation = readable_pair_to_integer(obj);
816 add_to_valid_bitfield(&ui64Type, 1);
817 }
818 if (json_object_object_get_ex(check_info, "participationType", &obj)) {
819 check_info_cper->ParticipationType =
820 readable_pair_to_integer(obj);
821 add_to_valid_bitfield(&ui64Type, 8);
822 }
823
824 if (json_object_object_get_ex(check_info, "addressSpace", &obj)) {
825 check_info_cper->AddressSpace = readable_pair_to_integer(obj);
826 add_to_valid_bitfield(&ui64Type, 10);
827 }
828
829 //Miscellaneous raw value fields.
830 if (json_object_object_get_ex(check_info, "level", &obj)) {
831 check_info_cper->Level = json_object_get_uint64(obj);
832 add_to_valid_bitfield(&ui64Type, 2);
833 }
834 if (json_object_object_get_ex(check_info, "processorContextCorrupt",
835 &obj)) {
836 check_info_cper->ContextCorrupt = json_object_get_boolean(obj);
837 add_to_valid_bitfield(&ui64Type, 3);
838 }
839 if (json_object_object_get_ex(check_info, "uncorrected", &obj)) {
840 check_info_cper->ErrorUncorrected =
841 json_object_get_boolean(obj);
842 add_to_valid_bitfield(&ui64Type, 4);
843 }
844 if (json_object_object_get_ex(check_info, "preciseIP", &obj)) {
845 check_info_cper->PreciseIp = json_object_get_boolean(obj);
846 add_to_valid_bitfield(&ui64Type, 5);
847 }
848 if (json_object_object_get_ex(check_info, "restartableIP", &obj)) {
849 check_info_cper->RestartableIp = json_object_get_boolean(obj);
850 add_to_valid_bitfield(&ui64Type, 6);
851 }
852 if (json_object_object_get_ex(check_info, "overflow", &obj)) {
853 check_info_cper->Overflow = json_object_get_boolean(obj);
854 add_to_valid_bitfield(&ui64Type, 7);
855 }
856 if (json_object_object_get_ex(check_info, "timedOut", &obj)) {
857 check_info_cper->TimeOut = json_object_get_boolean(obj);
858 add_to_valid_bitfield(&ui64Type, 9);
859 }
860 check_info_cper->ValidFields = ui64Type.value.ui64;
861 }
862
863 //Converts a single CPER-JSON IA32/x64 MS error info structure to CPER binary.
ir_ia32x64_ms_check_error_to_cper(json_object * check_info,EFI_IA32_X64_MS_CHECK_INFO * check_info_cper)864 void ir_ia32x64_ms_check_error_to_cper(
865 json_object *check_info, EFI_IA32_X64_MS_CHECK_INFO *check_info_cper)
866 {
867 //Validation bits.
868 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
869 struct json_object *obj = NULL;
870
871 //Type of MS check error.
872 if (json_object_object_get_ex(check_info, "errorType", &obj)) {
873 check_info_cper->ErrorType = readable_pair_to_integer(obj);
874 add_to_valid_bitfield(&ui64Type, 0);
875 }
876
877 //Miscellaneous raw value fields.
878 if (json_object_object_get_ex(check_info, "processorContextCorrupt",
879 &obj)) {
880 check_info_cper->ContextCorrupt = json_object_get_boolean(obj);
881 add_to_valid_bitfield(&ui64Type, 1);
882 }
883 if (json_object_object_get_ex(check_info, "uncorrected", &obj)) {
884 check_info_cper->ErrorUncorrected =
885 json_object_get_boolean(obj);
886 add_to_valid_bitfield(&ui64Type, 2);
887 }
888 if (json_object_object_get_ex(check_info, "preciseIP", &obj)) {
889 check_info_cper->PreciseIp = json_object_get_boolean(obj);
890 add_to_valid_bitfield(&ui64Type, 3);
891 }
892 if (json_object_object_get_ex(check_info, "restartableIP", &obj)) {
893 check_info_cper->RestartableIp = json_object_get_boolean(obj);
894 add_to_valid_bitfield(&ui64Type, 4);
895 }
896 if (json_object_object_get_ex(check_info, "overflow", &obj)) {
897 check_info_cper->Overflow = json_object_get_boolean(obj);
898 add_to_valid_bitfield(&ui64Type, 5);
899 }
900 check_info_cper->ValidFields = ui64Type.value.ui64;
901 }
902
903 //Converts a single CPER-JSON IA32/x64 context information structure into CPER binary, outputting to the
904 //provided stream.
ir_ia32x64_context_info_to_cper(json_object * context_info,FILE * out)905 void ir_ia32x64_context_info_to_cper(json_object *context_info, FILE *out)
906 {
907 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info_cper =
908 (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)calloc(
909 1, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO));
910
911 //Register context type.
912 context_info_cper->RegisterType = (UINT16)readable_pair_to_integer(
913 json_object_object_get(context_info, "registerContextType"));
914
915 //Miscellaneous numeric fields.
916 context_info_cper->ArraySize = (UINT16)json_object_get_uint64(
917 json_object_object_get(context_info, "registerArraySize"));
918 context_info_cper->MsrAddress = (UINT32)json_object_get_uint64(
919 json_object_object_get(context_info, "msrAddress"));
920 context_info_cper->MmRegisterAddress = json_object_get_uint64(
921 json_object_object_get(context_info, "mmRegisterAddress"));
922
923 //Flush header to stream.
924 fwrite(context_info_cper, sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO),
925 1, out);
926 fflush(out);
927
928 //Handle the register array, depending on type provided.
929 json_object *register_array =
930 json_object_object_get(context_info, "registerArray");
931 if (context_info_cper->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
932 ir_ia32x64_ia32_registers_to_cper(register_array, out);
933 } else if (context_info_cper->RegisterType ==
934 EFI_REG_CONTEXT_TYPE_X64) {
935 ir_ia32x64_x64_registers_to_cper(register_array, out);
936 } else {
937 //Unknown/structure is not defined.
938 json_object *encoded =
939 json_object_object_get(register_array, "data");
940 int32_t decoded_len = 0;
941 const char *j_string = json_object_get_string(encoded);
942 int j_size = json_object_get_string_len(encoded);
943 UINT8 *decoded = base64_decode(j_string, j_size, &decoded_len);
944 if (decoded == NULL) {
945 cper_print_log(
946 "Failed to allocate decode output buffer. \n");
947 } else {
948 fwrite(decoded, decoded_len, 1, out);
949 fflush(out);
950 free(decoded);
951 }
952 }
953
954 //Free remaining resources.
955 free(context_info_cper);
956 }
957
958 //Converts a single CPER-JSON IA32 register array into CPER binary, outputting to the given stream.
ir_ia32x64_ia32_registers_to_cper(json_object * registers,FILE * out)959 void ir_ia32x64_ia32_registers_to_cper(json_object *registers, FILE *out)
960 {
961 EFI_CONTEXT_IA32_REGISTER_STATE register_state;
962 register_state.Eax = (UINT32)json_object_get_uint64(
963 json_object_object_get(registers, "eax"));
964 register_state.Ebx = (UINT32)json_object_get_uint64(
965 json_object_object_get(registers, "ebx"));
966 register_state.Ecx = (UINT32)json_object_get_uint64(
967 json_object_object_get(registers, "ecx"));
968 register_state.Edx = (UINT32)json_object_get_uint64(
969 json_object_object_get(registers, "edx"));
970 register_state.Esi = (UINT32)json_object_get_uint64(
971 json_object_object_get(registers, "esi"));
972 register_state.Edi = (UINT32)json_object_get_uint64(
973 json_object_object_get(registers, "edi"));
974 register_state.Ebp = (UINT32)json_object_get_uint64(
975 json_object_object_get(registers, "ebp"));
976 register_state.Esp = (UINT32)json_object_get_uint64(
977 json_object_object_get(registers, "esp"));
978 register_state.Cs = (UINT16)json_object_get_uint64(
979 json_object_object_get(registers, "cs"));
980 register_state.Ds = (UINT32)json_object_get_uint64(
981 json_object_object_get(registers, "ds"));
982 register_state.Ss = (UINT16)json_object_get_uint64(
983 json_object_object_get(registers, "ss"));
984 register_state.Es = (UINT16)json_object_get_uint64(
985 json_object_object_get(registers, "es"));
986 register_state.Fs = (UINT16)json_object_get_uint64(
987 json_object_object_get(registers, "fs"));
988 register_state.Gs = (UINT16)json_object_get_uint64(
989 json_object_object_get(registers, "gs"));
990 register_state.Eflags = (UINT32)json_object_get_uint64(
991 json_object_object_get(registers, "eflags"));
992 register_state.Eip = (UINT32)json_object_get_uint64(
993 json_object_object_get(registers, "eip"));
994 register_state.Cr0 = (UINT32)json_object_get_uint64(
995 json_object_object_get(registers, "cr0"));
996 register_state.Cr1 = (UINT32)json_object_get_uint64(
997 json_object_object_get(registers, "cr1"));
998 register_state.Cr2 = (UINT32)json_object_get_uint64(
999 json_object_object_get(registers, "cr2"));
1000 register_state.Cr3 = (UINT32)json_object_get_uint64(
1001 json_object_object_get(registers, "cr3"));
1002 register_state.Cr4 = (UINT32)json_object_get_uint64(
1003 json_object_object_get(registers, "cr4"));
1004
1005 //64-bit registers are split into two 32-bit parts.
1006 UINT64 gdtr = json_object_get_uint64(
1007 json_object_object_get(registers, "gdtr"));
1008 register_state.Gdtr[0] = gdtr & 0xFFFFFFFF;
1009 register_state.Gdtr[1] = gdtr >> 32;
1010 UINT64 idtr = json_object_get_uint64(
1011 json_object_object_get(registers, "idtr"));
1012 register_state.Idtr[0] = idtr & 0xFFFFFFFF;
1013 register_state.Idtr[1] = idtr >> 32;
1014
1015 //16-bit registers.
1016 register_state.Ldtr = (UINT16)json_object_get_uint64(
1017 json_object_object_get(registers, "ldtr"));
1018 register_state.Tr = (UINT16)json_object_get_uint64(
1019 json_object_object_get(registers, "tr"));
1020
1021 //Write out to stream.
1022 fwrite(®ister_state, sizeof(EFI_CONTEXT_IA32_REGISTER_STATE), 1,
1023 out);
1024 fflush(out);
1025 }
1026
1027 //Converts a single CPER-JSON x64 register array into CPER binary, outputting to the given stream.
ir_ia32x64_x64_registers_to_cper(json_object * registers,FILE * out)1028 void ir_ia32x64_x64_registers_to_cper(json_object *registers, FILE *out)
1029 {
1030 EFI_CONTEXT_X64_REGISTER_STATE register_state;
1031 register_state.Rax = json_object_get_uint64(
1032 json_object_object_get(registers, "rax"));
1033 register_state.Rbx = json_object_get_uint64(
1034 json_object_object_get(registers, "rbx"));
1035 register_state.Rcx = json_object_get_uint64(
1036 json_object_object_get(registers, "rcx"));
1037 register_state.Rdx = json_object_get_uint64(
1038 json_object_object_get(registers, "rdx"));
1039 register_state.Rsi = json_object_get_uint64(
1040 json_object_object_get(registers, "rsi"));
1041 register_state.Rdi = json_object_get_uint64(
1042 json_object_object_get(registers, "rdi"));
1043 register_state.Rbp = json_object_get_uint64(
1044 json_object_object_get(registers, "rbp"));
1045 register_state.Rsp = json_object_get_uint64(
1046 json_object_object_get(registers, "rsp"));
1047 register_state.R8 =
1048 json_object_get_uint64(json_object_object_get(registers, "r8"));
1049 register_state.R9 =
1050 json_object_get_uint64(json_object_object_get(registers, "r9"));
1051 register_state.R10 = json_object_get_uint64(
1052 json_object_object_get(registers, "r10"));
1053 register_state.R11 = json_object_get_uint64(
1054 json_object_object_get(registers, "r11"));
1055 register_state.R12 = json_object_get_uint64(
1056 json_object_object_get(registers, "r12"));
1057 register_state.R13 = json_object_get_uint64(
1058 json_object_object_get(registers, "r13"));
1059 register_state.R14 = json_object_get_uint64(
1060 json_object_object_get(registers, "r14"));
1061 register_state.R15 = json_object_get_uint64(
1062 json_object_object_get(registers, "r15"));
1063 register_state.Cs = (UINT16)json_object_get_int(
1064 json_object_object_get(registers, "cs"));
1065 register_state.Ds = (UINT16)json_object_get_int(
1066 json_object_object_get(registers, "ds"));
1067 register_state.Ss = (UINT16)json_object_get_int(
1068 json_object_object_get(registers, "ss"));
1069 register_state.Es = (UINT16)json_object_get_int(
1070 json_object_object_get(registers, "es"));
1071 register_state.Fs = (UINT16)json_object_get_int(
1072 json_object_object_get(registers, "fs"));
1073 register_state.Gs = (UINT16)json_object_get_int(
1074 json_object_object_get(registers, "gs"));
1075 register_state.Resv1 = 0;
1076 register_state.Rflags = json_object_get_uint64(
1077 json_object_object_get(registers, "rflags"));
1078 register_state.Rip = json_object_get_uint64(
1079 json_object_object_get(registers, "eip"));
1080 register_state.Cr0 = json_object_get_uint64(
1081 json_object_object_get(registers, "cr0"));
1082 register_state.Cr1 = json_object_get_uint64(
1083 json_object_object_get(registers, "cr1"));
1084 register_state.Cr2 = json_object_get_uint64(
1085 json_object_object_get(registers, "cr2"));
1086 register_state.Cr3 = json_object_get_uint64(
1087 json_object_object_get(registers, "cr3"));
1088 register_state.Cr4 = json_object_get_uint64(
1089 json_object_object_get(registers, "cr4"));
1090 register_state.Cr8 = json_object_get_uint64(
1091 json_object_object_get(registers, "cr8"));
1092 register_state.Gdtr[0] = json_object_get_uint64(
1093 json_object_object_get(registers, "gdtr_0"));
1094 register_state.Gdtr[1] = json_object_get_uint64(
1095 json_object_object_get(registers, "gdtr_1"));
1096 register_state.Idtr[0] = json_object_get_uint64(
1097 json_object_object_get(registers, "idtr_0"));
1098 register_state.Idtr[1] = json_object_get_uint64(
1099 json_object_object_get(registers, "idtr_1"));
1100 register_state.Ldtr = (UINT16)json_object_get_int(
1101 json_object_object_get(registers, "ldtr"));
1102 register_state.Tr = (UINT16)json_object_get_int(
1103 json_object_object_get(registers, "tr"));
1104
1105 //Write out to stream.
1106 fwrite(®ister_state, sizeof(EFI_CONTEXT_X64_REGISTER_STATE), 1, out);
1107 fflush(out);
1108 }
1109