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