11b0b00e3SLawrence Tang /**
21b0b00e3SLawrence Tang  * Describes functions for converting processor-generic CPER sections from binary and JSON format
31b0b00e3SLawrence Tang  * into an intermediate format.
41b0b00e3SLawrence Tang  *
51b0b00e3SLawrence Tang  * Author: Lawrence.Tang@arm.com
61b0b00e3SLawrence Tang  **/
71b0b00e3SLawrence Tang 
81b0b00e3SLawrence Tang #include <stdio.h>
90cb33793SLawrence Tang #include <string.h>
101b0b00e3SLawrence Tang #include "json.h"
111b0b00e3SLawrence Tang #include "../edk/Cper.h"
121b0b00e3SLawrence Tang #include "../cper-utils.h"
133c43f743SLawrence Tang #include "cper-section-generic.h"
141b0b00e3SLawrence Tang 
151b0b00e3SLawrence Tang //Converts the given processor-generic CPER section into JSON IR.
16*e407b4c8SLawrence Tang json_object *
17*e407b4c8SLawrence Tang cper_section_generic_to_ir(void *section,
18*e407b4c8SLawrence Tang 			   EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
191b0b00e3SLawrence Tang {
20*e407b4c8SLawrence Tang 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic =
21*e407b4c8SLawrence Tang 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)section;
223c43f743SLawrence Tang 	json_object *section_ir = json_object_new_object();
233c43f743SLawrence Tang 
243c43f743SLawrence Tang 	//Validation bits.
25*e407b4c8SLawrence Tang 	json_object *validation =
26*e407b4c8SLawrence Tang 		bitfield_to_ir(section_generic->ValidFields, 13,
27*e407b4c8SLawrence Tang 			       GENERIC_VALIDATION_BITFIELD_NAMES);
283c43f743SLawrence Tang 	json_object_object_add(section_ir, "validationBits", validation);
293c43f743SLawrence Tang 
303c43f743SLawrence Tang 	//Processor type, with human readable name if possible.
31*e407b4c8SLawrence Tang 	json_object *processor_type = integer_to_readable_pair(
32*e407b4c8SLawrence Tang 		section_generic->Type,
333c43f743SLawrence Tang 		sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int),
34*e407b4c8SLawrence Tang 		GENERIC_PROC_TYPES_KEYS, GENERIC_PROC_TYPES_VALUES,
353c43f743SLawrence Tang 		"Unknown (Reserved)");
363c43f743SLawrence Tang 	json_object_object_add(section_ir, "processorType", processor_type);
373c43f743SLawrence Tang 
383c43f743SLawrence Tang 	//Processor ISA, with human readable name if possible.
39*e407b4c8SLawrence Tang 	json_object *processor_isa = integer_to_readable_pair(
40*e407b4c8SLawrence Tang 		section_generic->Isa,
413c43f743SLawrence Tang 		sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int),
42*e407b4c8SLawrence Tang 		GENERIC_ISA_TYPES_KEYS, GENERIC_ISA_TYPES_VALUES,
4367cbed6bSLawrence Tang 		"Unknown (Reserved)");
443c43f743SLawrence Tang 	json_object_object_add(section_ir, "processorISA", processor_isa);
453c43f743SLawrence Tang 
463c43f743SLawrence Tang 	//Processor error type, with human readable name if possible.
47*e407b4c8SLawrence Tang 	json_object *processor_error_type = integer_to_readable_pair(
48*e407b4c8SLawrence Tang 		section_generic->ErrorType,
493c43f743SLawrence Tang 		sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int),
50*e407b4c8SLawrence Tang 		GENERIC_ERROR_TYPES_KEYS, GENERIC_ERROR_TYPES_VALUES,
5167cbed6bSLawrence Tang 		"Unknown (Reserved)");
523c43f743SLawrence Tang 	json_object_object_add(section_ir, "errorType", processor_error_type);
533c43f743SLawrence Tang 
543c43f743SLawrence Tang 	//The operation performed, with a human readable name if possible.
55*e407b4c8SLawrence Tang 	json_object *operation = integer_to_readable_pair(
56*e407b4c8SLawrence Tang 		section_generic->Operation,
573c43f743SLawrence Tang 		sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int),
58*e407b4c8SLawrence Tang 		GENERIC_OPERATION_TYPES_KEYS, GENERIC_OPERATION_TYPES_VALUES,
5967cbed6bSLawrence Tang 		"Unknown (Reserved)");
603c43f743SLawrence Tang 	json_object_object_add(section_ir, "operation", operation);
613c43f743SLawrence Tang 
623c43f743SLawrence Tang 	//Flags, additional information about the error.
63*e407b4c8SLawrence Tang 	json_object *flags = bitfield_to_ir(section_generic->Flags, 4,
64*e407b4c8SLawrence Tang 					    GENERIC_FLAGS_BITFIELD_NAMES);
653c43f743SLawrence Tang 	json_object_object_add(section_ir, "flags", flags);
663c43f743SLawrence Tang 
673c43f743SLawrence Tang 	//The level of the error.
68*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "level",
69*e407b4c8SLawrence Tang 			       json_object_new_int(section_generic->Level));
703c43f743SLawrence Tang 
719a785c2aSLawrence Tang 	//CPU version information.
72*e407b4c8SLawrence Tang 	json_object_object_add(
73*e407b4c8SLawrence Tang 		section_ir, "cpuVersionInfo",
74*e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->VersionInfo));
753c43f743SLawrence Tang 
763c43f743SLawrence Tang 	//CPU brand string. May not exist if on ARM.
77*e407b4c8SLawrence Tang 	json_object_object_add(
78*e407b4c8SLawrence Tang 		section_ir, "cpuBrandString",
79*e407b4c8SLawrence Tang 		json_object_new_string(section_generic->BrandString));
803c43f743SLawrence Tang 
813c43f743SLawrence Tang 	//Remaining 64-bit fields.
82*e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "processorID",
83*e407b4c8SLawrence Tang 			       json_object_new_uint64(section_generic->ApicId));
84*e407b4c8SLawrence Tang 	json_object_object_add(
85*e407b4c8SLawrence Tang 		section_ir, "targetAddress",
86*e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->TargetAddr));
87*e407b4c8SLawrence Tang 	json_object_object_add(
88*e407b4c8SLawrence Tang 		section_ir, "requestorID",
89*e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->RequestorId));
90*e407b4c8SLawrence Tang 	json_object_object_add(
91*e407b4c8SLawrence Tang 		section_ir, "responderID",
92*e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->ResponderId));
93*e407b4c8SLawrence Tang 	json_object_object_add(
94*e407b4c8SLawrence Tang 		section_ir, "instructionIP",
95*e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->InstructionIP));
963c43f743SLawrence Tang 
973c43f743SLawrence Tang 	return section_ir;
981b0b00e3SLawrence Tang }
990cb33793SLawrence Tang 
1000cb33793SLawrence Tang //Converts the given CPER-JSON processor-generic error section into CPER binary,
1010cb33793SLawrence Tang //outputting to the provided stream.
1020cb33793SLawrence Tang void ir_section_generic_to_cper(json_object *section, FILE *out)
1030cb33793SLawrence Tang {
1040cb33793SLawrence Tang 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_cper =
105*e407b4c8SLawrence Tang 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc(
106*e407b4c8SLawrence Tang 			1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA));
1070cb33793SLawrence Tang 
1080cb33793SLawrence Tang 	//Validation bits.
109*e407b4c8SLawrence Tang 	section_cper->ValidFields = ir_to_bitfield(
110*e407b4c8SLawrence Tang 		json_object_object_get(section, "validationBits"), 13,
111*e407b4c8SLawrence Tang 		GENERIC_VALIDATION_BITFIELD_NAMES);
1120cb33793SLawrence Tang 
1130cb33793SLawrence Tang 	//Various name/value pair fields.
114*e407b4c8SLawrence Tang 	section_cper->Type = (UINT8)readable_pair_to_integer(
115*e407b4c8SLawrence Tang 		json_object_object_get(section, "processorType"));
116*e407b4c8SLawrence Tang 	section_cper->Isa = (UINT8)readable_pair_to_integer(
117*e407b4c8SLawrence Tang 		json_object_object_get(section, "processorISA"));
118*e407b4c8SLawrence Tang 	section_cper->ErrorType = (UINT8)readable_pair_to_integer(
119*e407b4c8SLawrence Tang 		json_object_object_get(section, "errorType"));
120*e407b4c8SLawrence Tang 	section_cper->Operation = (UINT8)readable_pair_to_integer(
121*e407b4c8SLawrence Tang 		json_object_object_get(section, "operation"));
1220cb33793SLawrence Tang 
1230cb33793SLawrence Tang 	//Flags.
124*e407b4c8SLawrence Tang 	section_cper->Flags =
125*e407b4c8SLawrence Tang 		(UINT8)ir_to_bitfield(json_object_object_get(section, "flags"),
126*e407b4c8SLawrence Tang 				      4, GENERIC_FLAGS_BITFIELD_NAMES);
1270cb33793SLawrence Tang 
1280cb33793SLawrence Tang 	//Various numeric/string fields.
129*e407b4c8SLawrence Tang 	section_cper->Level = (UINT8)json_object_get_int(
130*e407b4c8SLawrence Tang 		json_object_object_get(section, "level"));
131*e407b4c8SLawrence Tang 	section_cper->VersionInfo = json_object_get_uint64(
132*e407b4c8SLawrence Tang 		json_object_object_get(section, "cpuVersionInfo"));
133*e407b4c8SLawrence Tang 	section_cper->ApicId = json_object_get_uint64(
134*e407b4c8SLawrence Tang 		json_object_object_get(section, "processorID"));
135*e407b4c8SLawrence Tang 	section_cper->TargetAddr = json_object_get_uint64(
136*e407b4c8SLawrence Tang 		json_object_object_get(section, "targetAddress"));
137*e407b4c8SLawrence Tang 	section_cper->RequestorId = json_object_get_uint64(
138*e407b4c8SLawrence Tang 		json_object_object_get(section, "requestorID"));
139*e407b4c8SLawrence Tang 	section_cper->ResponderId = json_object_get_uint64(
140*e407b4c8SLawrence Tang 		json_object_object_get(section, "responderID"));
141*e407b4c8SLawrence Tang 	section_cper->InstructionIP = json_object_get_uint64(
142*e407b4c8SLawrence Tang 		json_object_object_get(section, "instructionIP"));
1430cb33793SLawrence Tang 
1440cb33793SLawrence Tang 	//CPU brand string.
145*e407b4c8SLawrence Tang 	const char *brand_string = json_object_get_string(
146*e407b4c8SLawrence Tang 		json_object_object_get(section, "cpuBrandString"));
1470cb33793SLawrence Tang 	if (brand_string != NULL)
1480cb33793SLawrence Tang 		strncpy(section_cper->BrandString, brand_string, 127);
1490cb33793SLawrence Tang 
1500cb33793SLawrence Tang 	//Write & flush out to file, free memory.
1510cb33793SLawrence Tang 	fwrite(section_cper, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA), 1, out);
1520cb33793SLawrence Tang 	fflush(out);
1530cb33793SLawrence Tang 	free(section_cper);
1540cb33793SLawrence Tang }