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