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>
10*5202bbb4SLawrence 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.
16e407b4c8SLawrence Tang json_object *
17e407b4c8SLawrence Tang cper_section_generic_to_ir(void *section,
18e407b4c8SLawrence Tang 			   EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
191b0b00e3SLawrence Tang {
20e407b4c8SLawrence Tang 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic =
21e407b4c8SLawrence Tang 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)section;
223c43f743SLawrence Tang 	json_object *section_ir = json_object_new_object();
233c43f743SLawrence Tang 
243c43f743SLawrence Tang 	//Validation bits.
25e407b4c8SLawrence Tang 	json_object *validation =
26e407b4c8SLawrence Tang 		bitfield_to_ir(section_generic->ValidFields, 13,
27e407b4c8SLawrence 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.
31e407b4c8SLawrence Tang 	json_object *processor_type = integer_to_readable_pair(
32e407b4c8SLawrence Tang 		section_generic->Type,
333c43f743SLawrence Tang 		sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int),
34e407b4c8SLawrence 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.
39e407b4c8SLawrence Tang 	json_object *processor_isa = integer_to_readable_pair(
40e407b4c8SLawrence Tang 		section_generic->Isa,
413c43f743SLawrence Tang 		sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int),
42e407b4c8SLawrence 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.
47e407b4c8SLawrence Tang 	json_object *processor_error_type = integer_to_readable_pair(
48e407b4c8SLawrence Tang 		section_generic->ErrorType,
493c43f743SLawrence Tang 		sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int),
50e407b4c8SLawrence 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.
55e407b4c8SLawrence Tang 	json_object *operation = integer_to_readable_pair(
56e407b4c8SLawrence Tang 		section_generic->Operation,
573c43f743SLawrence Tang 		sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int),
58e407b4c8SLawrence 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.
63e407b4c8SLawrence Tang 	json_object *flags = bitfield_to_ir(section_generic->Flags, 4,
64e407b4c8SLawrence Tang 					    GENERIC_FLAGS_BITFIELD_NAMES);
653c43f743SLawrence Tang 	json_object_object_add(section_ir, "flags", flags);
663c43f743SLawrence Tang 
673c43f743SLawrence Tang 	//The level of the error.
68e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "level",
69e407b4c8SLawrence Tang 			       json_object_new_int(section_generic->Level));
703c43f743SLawrence Tang 
719a785c2aSLawrence Tang 	//CPU version information.
72e407b4c8SLawrence Tang 	json_object_object_add(
73e407b4c8SLawrence Tang 		section_ir, "cpuVersionInfo",
74e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->VersionInfo));
753c43f743SLawrence Tang 
763c43f743SLawrence Tang 	//CPU brand string. May not exist if on ARM.
77e407b4c8SLawrence Tang 	json_object_object_add(
78e407b4c8SLawrence Tang 		section_ir, "cpuBrandString",
79e407b4c8SLawrence Tang 		json_object_new_string(section_generic->BrandString));
803c43f743SLawrence Tang 
813c43f743SLawrence Tang 	//Remaining 64-bit fields.
82e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "processorID",
83e407b4c8SLawrence Tang 			       json_object_new_uint64(section_generic->ApicId));
84e407b4c8SLawrence Tang 	json_object_object_add(
85e407b4c8SLawrence Tang 		section_ir, "targetAddress",
86e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->TargetAddr));
87e407b4c8SLawrence Tang 	json_object_object_add(
88e407b4c8SLawrence Tang 		section_ir, "requestorID",
89e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->RequestorId));
90e407b4c8SLawrence Tang 	json_object_object_add(
91e407b4c8SLawrence Tang 		section_ir, "responderID",
92e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->ResponderId));
93e407b4c8SLawrence Tang 	json_object_object_add(
94e407b4c8SLawrence Tang 		section_ir, "instructionIP",
95e407b4c8SLawrence 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 =
105e407b4c8SLawrence Tang 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc(
106e407b4c8SLawrence Tang 			1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA));
1070cb33793SLawrence Tang 
1080cb33793SLawrence Tang 	//Validation bits.
109e407b4c8SLawrence Tang 	section_cper->ValidFields = ir_to_bitfield(
110e407b4c8SLawrence Tang 		json_object_object_get(section, "validationBits"), 13,
111e407b4c8SLawrence Tang 		GENERIC_VALIDATION_BITFIELD_NAMES);
1120cb33793SLawrence Tang 
1130cb33793SLawrence Tang 	//Various name/value pair fields.
114e407b4c8SLawrence Tang 	section_cper->Type = (UINT8)readable_pair_to_integer(
115e407b4c8SLawrence Tang 		json_object_object_get(section, "processorType"));
116e407b4c8SLawrence Tang 	section_cper->Isa = (UINT8)readable_pair_to_integer(
117e407b4c8SLawrence Tang 		json_object_object_get(section, "processorISA"));
118e407b4c8SLawrence Tang 	section_cper->ErrorType = (UINT8)readable_pair_to_integer(
119e407b4c8SLawrence Tang 		json_object_object_get(section, "errorType"));
120e407b4c8SLawrence Tang 	section_cper->Operation = (UINT8)readable_pair_to_integer(
121e407b4c8SLawrence Tang 		json_object_object_get(section, "operation"));
1220cb33793SLawrence Tang 
1230cb33793SLawrence Tang 	//Flags.
124e407b4c8SLawrence Tang 	section_cper->Flags =
125e407b4c8SLawrence Tang 		(UINT8)ir_to_bitfield(json_object_object_get(section, "flags"),
126e407b4c8SLawrence Tang 				      4, GENERIC_FLAGS_BITFIELD_NAMES);
1270cb33793SLawrence Tang 
1280cb33793SLawrence Tang 	//Various numeric/string fields.
129e407b4c8SLawrence Tang 	section_cper->Level = (UINT8)json_object_get_int(
130e407b4c8SLawrence Tang 		json_object_object_get(section, "level"));
131e407b4c8SLawrence Tang 	section_cper->VersionInfo = json_object_get_uint64(
132e407b4c8SLawrence Tang 		json_object_object_get(section, "cpuVersionInfo"));
133e407b4c8SLawrence Tang 	section_cper->ApicId = json_object_get_uint64(
134e407b4c8SLawrence Tang 		json_object_object_get(section, "processorID"));
135e407b4c8SLawrence Tang 	section_cper->TargetAddr = json_object_get_uint64(
136e407b4c8SLawrence Tang 		json_object_object_get(section, "targetAddress"));
137e407b4c8SLawrence Tang 	section_cper->RequestorId = json_object_get_uint64(
138e407b4c8SLawrence Tang 		json_object_object_get(section, "requestorID"));
139e407b4c8SLawrence Tang 	section_cper->ResponderId = json_object_get_uint64(
140e407b4c8SLawrence Tang 		json_object_object_get(section, "responderID"));
141e407b4c8SLawrence Tang 	section_cper->InstructionIP = json_object_get_uint64(
142e407b4c8SLawrence Tang 		json_object_object_get(section, "instructionIP"));
1430cb33793SLawrence Tang 
1440cb33793SLawrence Tang 	//CPU brand string.
145e407b4c8SLawrence Tang 	const char *brand_string = json_object_get_string(
146e407b4c8SLawrence 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 }