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