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