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>
105202bbb4SLawrence 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.
cper_section_generic_to_ir(void * section)16f8fc7052SJohn Chung json_object *cper_section_generic_to_ir(void *section)
171b0b00e3SLawrence Tang {
18e407b4c8SLawrence Tang 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic =
19e407b4c8SLawrence Tang 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)section;
203c43f743SLawrence Tang 	json_object *section_ir = json_object_new_object();
213c43f743SLawrence Tang 
223c43f743SLawrence Tang 	//Validation bits.
23e407b4c8SLawrence Tang 	json_object *validation =
24e407b4c8SLawrence Tang 		bitfield_to_ir(section_generic->ValidFields, 13,
25e407b4c8SLawrence Tang 			       GENERIC_VALIDATION_BITFIELD_NAMES);
263c43f743SLawrence Tang 	json_object_object_add(section_ir, "validationBits", validation);
273c43f743SLawrence Tang 
283c43f743SLawrence Tang 	//Processor type, with human readable name if possible.
29e407b4c8SLawrence Tang 	json_object *processor_type = integer_to_readable_pair(
30e407b4c8SLawrence Tang 		section_generic->Type,
313c43f743SLawrence Tang 		sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int),
32e407b4c8SLawrence Tang 		GENERIC_PROC_TYPES_KEYS, GENERIC_PROC_TYPES_VALUES,
333c43f743SLawrence Tang 		"Unknown (Reserved)");
343c43f743SLawrence Tang 	json_object_object_add(section_ir, "processorType", processor_type);
353c43f743SLawrence Tang 
363c43f743SLawrence Tang 	//Processor ISA, with human readable name if possible.
37e407b4c8SLawrence Tang 	json_object *processor_isa = integer_to_readable_pair(
38e407b4c8SLawrence Tang 		section_generic->Isa,
393c43f743SLawrence Tang 		sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int),
40e407b4c8SLawrence Tang 		GENERIC_ISA_TYPES_KEYS, GENERIC_ISA_TYPES_VALUES,
4167cbed6bSLawrence Tang 		"Unknown (Reserved)");
423c43f743SLawrence Tang 	json_object_object_add(section_ir, "processorISA", processor_isa);
433c43f743SLawrence Tang 
443c43f743SLawrence Tang 	//Processor error type, with human readable name if possible.
45e407b4c8SLawrence Tang 	json_object *processor_error_type = integer_to_readable_pair(
46e407b4c8SLawrence Tang 		section_generic->ErrorType,
473c43f743SLawrence Tang 		sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int),
48e407b4c8SLawrence Tang 		GENERIC_ERROR_TYPES_KEYS, GENERIC_ERROR_TYPES_VALUES,
4967cbed6bSLawrence Tang 		"Unknown (Reserved)");
503c43f743SLawrence Tang 	json_object_object_add(section_ir, "errorType", processor_error_type);
513c43f743SLawrence Tang 
523c43f743SLawrence Tang 	//The operation performed, with a human readable name if possible.
53e407b4c8SLawrence Tang 	json_object *operation = integer_to_readable_pair(
54e407b4c8SLawrence Tang 		section_generic->Operation,
553c43f743SLawrence Tang 		sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int),
56e407b4c8SLawrence Tang 		GENERIC_OPERATION_TYPES_KEYS, GENERIC_OPERATION_TYPES_VALUES,
5767cbed6bSLawrence Tang 		"Unknown (Reserved)");
583c43f743SLawrence Tang 	json_object_object_add(section_ir, "operation", operation);
593c43f743SLawrence Tang 
603c43f743SLawrence Tang 	//Flags, additional information about the error.
61e407b4c8SLawrence Tang 	json_object *flags = bitfield_to_ir(section_generic->Flags, 4,
62e407b4c8SLawrence Tang 					    GENERIC_FLAGS_BITFIELD_NAMES);
633c43f743SLawrence Tang 	json_object_object_add(section_ir, "flags", flags);
643c43f743SLawrence Tang 
653c43f743SLawrence Tang 	//The level of the error.
66e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "level",
67e407b4c8SLawrence Tang 			       json_object_new_int(section_generic->Level));
683c43f743SLawrence Tang 
699a785c2aSLawrence Tang 	//CPU version information.
70e407b4c8SLawrence Tang 	json_object_object_add(
71e407b4c8SLawrence Tang 		section_ir, "cpuVersionInfo",
72e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->VersionInfo));
733c43f743SLawrence Tang 
743c43f743SLawrence Tang 	//CPU brand string. May not exist if on ARM.
75e407b4c8SLawrence Tang 	json_object_object_add(
76e407b4c8SLawrence Tang 		section_ir, "cpuBrandString",
77e407b4c8SLawrence Tang 		json_object_new_string(section_generic->BrandString));
783c43f743SLawrence Tang 
793c43f743SLawrence Tang 	//Remaining 64-bit fields.
80e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "processorID",
81e407b4c8SLawrence Tang 			       json_object_new_uint64(section_generic->ApicId));
82e407b4c8SLawrence Tang 	json_object_object_add(
83e407b4c8SLawrence Tang 		section_ir, "targetAddress",
84e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->TargetAddr));
85e407b4c8SLawrence Tang 	json_object_object_add(
86e407b4c8SLawrence Tang 		section_ir, "requestorID",
87e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->RequestorId));
88e407b4c8SLawrence Tang 	json_object_object_add(
89e407b4c8SLawrence Tang 		section_ir, "responderID",
90e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->ResponderId));
91e407b4c8SLawrence Tang 	json_object_object_add(
92e407b4c8SLawrence Tang 		section_ir, "instructionIP",
93e407b4c8SLawrence Tang 		json_object_new_uint64(section_generic->InstructionIP));
943c43f743SLawrence Tang 
953c43f743SLawrence Tang 	return section_ir;
961b0b00e3SLawrence Tang }
970cb33793SLawrence Tang 
980cb33793SLawrence Tang //Converts the given CPER-JSON processor-generic error section into CPER binary,
990cb33793SLawrence Tang //outputting to the provided stream.
ir_section_generic_to_cper(json_object * section,FILE * out)1000cb33793SLawrence Tang void ir_section_generic_to_cper(json_object *section, FILE *out)
1010cb33793SLawrence Tang {
1020cb33793SLawrence Tang 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_cper =
103e407b4c8SLawrence Tang 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc(
104e407b4c8SLawrence Tang 			1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA));
1050cb33793SLawrence Tang 
1060cb33793SLawrence Tang 	//Validation bits.
107e407b4c8SLawrence Tang 	section_cper->ValidFields = ir_to_bitfield(
108e407b4c8SLawrence Tang 		json_object_object_get(section, "validationBits"), 13,
109e407b4c8SLawrence Tang 		GENERIC_VALIDATION_BITFIELD_NAMES);
1100cb33793SLawrence Tang 
1110cb33793SLawrence Tang 	//Various name/value pair fields.
112e407b4c8SLawrence Tang 	section_cper->Type = (UINT8)readable_pair_to_integer(
113e407b4c8SLawrence Tang 		json_object_object_get(section, "processorType"));
114e407b4c8SLawrence Tang 	section_cper->Isa = (UINT8)readable_pair_to_integer(
115e407b4c8SLawrence Tang 		json_object_object_get(section, "processorISA"));
116e407b4c8SLawrence Tang 	section_cper->ErrorType = (UINT8)readable_pair_to_integer(
117e407b4c8SLawrence Tang 		json_object_object_get(section, "errorType"));
118e407b4c8SLawrence Tang 	section_cper->Operation = (UINT8)readable_pair_to_integer(
119e407b4c8SLawrence Tang 		json_object_object_get(section, "operation"));
1200cb33793SLawrence Tang 
1210cb33793SLawrence Tang 	//Flags.
122e407b4c8SLawrence Tang 	section_cper->Flags =
123e407b4c8SLawrence Tang 		(UINT8)ir_to_bitfield(json_object_object_get(section, "flags"),
124e407b4c8SLawrence Tang 				      4, GENERIC_FLAGS_BITFIELD_NAMES);
1250cb33793SLawrence Tang 
1260cb33793SLawrence Tang 	//Various numeric/string fields.
127e407b4c8SLawrence Tang 	section_cper->Level = (UINT8)json_object_get_int(
128e407b4c8SLawrence Tang 		json_object_object_get(section, "level"));
129e407b4c8SLawrence Tang 	section_cper->VersionInfo = json_object_get_uint64(
130e407b4c8SLawrence Tang 		json_object_object_get(section, "cpuVersionInfo"));
131e407b4c8SLawrence Tang 	section_cper->ApicId = json_object_get_uint64(
132e407b4c8SLawrence Tang 		json_object_object_get(section, "processorID"));
133e407b4c8SLawrence Tang 	section_cper->TargetAddr = json_object_get_uint64(
134e407b4c8SLawrence Tang 		json_object_object_get(section, "targetAddress"));
135e407b4c8SLawrence Tang 	section_cper->RequestorId = json_object_get_uint64(
136e407b4c8SLawrence Tang 		json_object_object_get(section, "requestorID"));
137e407b4c8SLawrence Tang 	section_cper->ResponderId = json_object_get_uint64(
138e407b4c8SLawrence Tang 		json_object_object_get(section, "responderID"));
139e407b4c8SLawrence Tang 	section_cper->InstructionIP = json_object_get_uint64(
140e407b4c8SLawrence Tang 		json_object_object_get(section, "instructionIP"));
1410cb33793SLawrence Tang 
1420cb33793SLawrence Tang 	//CPU brand string.
143e407b4c8SLawrence Tang 	const char *brand_string = json_object_get_string(
144e407b4c8SLawrence Tang 		json_object_object_get(section, "cpuBrandString"));
145f8fc7052SJohn Chung 	if (brand_string != NULL) {
146*379e492aSPatrick Williams 		strncpy(section_cper->BrandString, brand_string,
147*379e492aSPatrick Williams 			sizeof(section_cper->BrandString) - 1);
148*379e492aSPatrick Williams 		section_cper
149*379e492aSPatrick Williams 			->BrandString[sizeof(section_cper->BrandString) - 1] =
150*379e492aSPatrick Williams 			'\0';
151f8fc7052SJohn Chung 	}
1520cb33793SLawrence Tang 
1530cb33793SLawrence Tang 	//Write & flush out to file, free memory.
1540cb33793SLawrence Tang 	fwrite(section_cper, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA), 1, out);
1550cb33793SLawrence Tang 	fflush(out);
1560cb33793SLawrence Tang 	free(section_cper);
1570cb33793SLawrence Tang }
158