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