xref: /openbmc/libcper/sections/cper-section-generic.c (revision ad6c880fc739b6ca750c3ab594e270efd972c2ac)
1 /**
2  * Describes functions for converting processor-generic 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 <string.h>
10 #include <json.h>
11 #include <libcper/Cper.h>
12 #include <libcper/cper-utils.h>
13 #include <libcper/sections/cper-section-generic.h>
14 #include <libcper/log.h>
15 #include <string.h>
16 
17 //Converts the given processor-generic CPER section into JSON IR.
cper_section_generic_to_ir(const UINT8 * section,UINT32 size,char ** desc_string)18 json_object *cper_section_generic_to_ir(const UINT8 *section, UINT32 size,
19 					char **desc_string)
20 {
21 	int outstr_len = 0;
22 	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
23 	outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
24 			      "A Generic Processor Error occurred");
25 	if (outstr_len < 0) {
26 		cper_print_log(
27 			"Error: Could not write to Generic description string\n");
28 	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
29 		cper_print_log("Error: Generic description string truncated\n");
30 	}
31 
32 	if (size < sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA)) {
33 		return NULL;
34 	}
35 
36 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic =
37 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)section;
38 	json_object *section_ir = json_object_new_object();
39 
40 	ValidationTypes ui64Type = {
41 		UINT_64T, .value.ui64 = section_generic->ValidFields
42 	};
43 
44 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
45 		//Processor type, with human readable name if possible.
46 		json_object *processor_type = integer_to_readable_pair(
47 			section_generic->Type,
48 			sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int),
49 			GENERIC_PROC_TYPES_KEYS, GENERIC_PROC_TYPES_VALUES,
50 			"Unknown (Reserved)");
51 		json_object_object_add(section_ir, "processorType",
52 				       processor_type);
53 	}
54 
55 	if (isvalid_prop_to_ir(&ui64Type, 1)) {
56 		//Processor ISA, with human readable name if possible.
57 		json_object *processor_isa = integer_to_readable_pair(
58 			section_generic->Isa,
59 			sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int),
60 			GENERIC_ISA_TYPES_KEYS, GENERIC_ISA_TYPES_VALUES,
61 			"Unknown (Reserved)");
62 		json_object_object_add(section_ir, "processorISA",
63 				       processor_isa);
64 	}
65 
66 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
67 		//Processor error type, with human readable name if possible.
68 		json_object *processor_error_type = integer_to_readable_pair(
69 			section_generic->ErrorType,
70 			sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int),
71 			GENERIC_ERROR_TYPES_KEYS, GENERIC_ERROR_TYPES_VALUES,
72 			"Unknown (Reserved)");
73 		json_object_object_add(section_ir, "errorType",
74 				       processor_error_type);
75 	}
76 
77 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
78 		//The operation performed, with a human readable name if possible.
79 		json_object *operation = integer_to_readable_pair(
80 			section_generic->Operation,
81 			sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int),
82 			GENERIC_OPERATION_TYPES_KEYS,
83 			GENERIC_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
84 		json_object_object_add(section_ir, "operation", operation);
85 	}
86 
87 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
88 		//Flags, additional information about the error.
89 		json_object *flags =
90 			bitfield_to_ir(section_generic->Flags, 4,
91 				       GENERIC_FLAGS_BITFIELD_NAMES);
92 		json_object_object_add(section_ir, "flags", flags);
93 	}
94 
95 	if (isvalid_prop_to_ir(&ui64Type, 5)) {
96 		//The level of the error.
97 		json_object_object_add(
98 			section_ir, "level",
99 			json_object_new_int(section_generic->Level));
100 	}
101 
102 	if (isvalid_prop_to_ir(&ui64Type, 6)) {
103 		//CPU version information.
104 		json_object_object_add(
105 			section_ir, "cpuVersionInfo",
106 			json_object_new_uint64(section_generic->VersionInfo));
107 	}
108 
109 	if (isvalid_prop_to_ir(&ui64Type, 7)) {
110 		//CPU brand string. May not exist if on ARM.
111 		add_untrusted_string(section_ir, "cpuBrandString",
112 				     section_generic->BrandString,
113 				     sizeof(section_generic->BrandString));
114 	}
115 
116 	if (isvalid_prop_to_ir(&ui64Type, 8)) {
117 		//Remaining 64-bit fields.
118 		json_object_object_add(
119 			section_ir, "processorID",
120 			json_object_new_uint64(section_generic->ApicId));
121 	}
122 
123 	if (isvalid_prop_to_ir(&ui64Type, 9)) {
124 		json_object_object_add(
125 			section_ir, "targetAddress",
126 			json_object_new_uint64(section_generic->TargetAddr));
127 	}
128 
129 	if (isvalid_prop_to_ir(&ui64Type, 10)) {
130 		json_object_object_add(
131 			section_ir, "requestorID",
132 			json_object_new_uint64(section_generic->RequestorId));
133 	}
134 
135 	if (isvalid_prop_to_ir(&ui64Type, 11)) {
136 		json_object_object_add(
137 			section_ir, "responderID",
138 			json_object_new_uint64(section_generic->ResponderId));
139 	}
140 
141 	if (isvalid_prop_to_ir(&ui64Type, 12)) {
142 		json_object_object_add(
143 			section_ir, "instructionIP",
144 			json_object_new_uint64(section_generic->InstructionIP));
145 	}
146 
147 	return section_ir;
148 }
149 
150 //Converts the given CPER-JSON processor-generic error section into CPER binary,
151 //outputting to the provided stream.
ir_section_generic_to_cper(json_object * section,FILE * out)152 void ir_section_generic_to_cper(json_object *section, FILE *out)
153 {
154 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_cper =
155 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc(
156 			1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA));
157 
158 	//Validation bits.
159 	//Remove
160 	// section_cper->ValidFields = ir_to_bitfield(
161 	// 	json_object_object_get(section, "validationBits"), 13,
162 	// 	GENERIC_VALIDATION_BITFIELD_NAMES);
163 	ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
164 	struct json_object *obj = NULL;
165 	//Various name/value pair fields.
166 	if (json_object_object_get_ex(section, "processorType", &obj)) {
167 		section_cper->Type = (UINT8)readable_pair_to_integer(obj);
168 		add_to_valid_bitfield(&ui64Type, 0);
169 	}
170 	if (json_object_object_get_ex(section, "processorISA", &obj)) {
171 		section_cper->Isa = (UINT8)readable_pair_to_integer(obj);
172 		add_to_valid_bitfield(&ui64Type, 1);
173 	}
174 	if (json_object_object_get_ex(section, "errorType", &obj)) {
175 		section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj);
176 		add_to_valid_bitfield(&ui64Type, 2);
177 	}
178 	if (json_object_object_get_ex(section, "operation", &obj)) {
179 		section_cper->Operation = (UINT8)readable_pair_to_integer(obj);
180 		add_to_valid_bitfield(&ui64Type, 3);
181 	}
182 	//Flags.
183 	if (json_object_object_get_ex(section, "flags", &obj)) {
184 		section_cper->Flags = (UINT8)ir_to_bitfield(
185 			obj, 4, GENERIC_FLAGS_BITFIELD_NAMES);
186 		add_to_valid_bitfield(&ui64Type, 4);
187 	}
188 
189 	//Various numeric/string fields.
190 	if (json_object_object_get_ex(section, "level", &obj)) {
191 		section_cper->Level = (UINT8)json_object_get_int(obj);
192 		add_to_valid_bitfield(&ui64Type, 5);
193 	}
194 	if (json_object_object_get_ex(section, "cpuVersionInfo", &obj)) {
195 		section_cper->VersionInfo = json_object_get_uint64(obj);
196 		add_to_valid_bitfield(&ui64Type, 6);
197 	}
198 	if (json_object_object_get_ex(section, "processorID", &obj)) {
199 		section_cper->ApicId = json_object_get_uint64(obj);
200 		add_to_valid_bitfield(&ui64Type, 8);
201 	}
202 	if (json_object_object_get_ex(section, "targetAddress", &obj)) {
203 		section_cper->TargetAddr = json_object_get_uint64(obj);
204 		add_to_valid_bitfield(&ui64Type, 9);
205 	}
206 	if (json_object_object_get_ex(section, "requestorID", &obj)) {
207 		section_cper->RequestorId = json_object_get_uint64(obj);
208 		add_to_valid_bitfield(&ui64Type, 10);
209 	}
210 	if (json_object_object_get_ex(section, "responderID", &obj)) {
211 		section_cper->ResponderId = json_object_get_uint64(obj);
212 		add_to_valid_bitfield(&ui64Type, 11);
213 	}
214 	if (json_object_object_get_ex(section, "instructionIP", &obj)) {
215 		section_cper->InstructionIP = json_object_get_uint64(obj);
216 		add_to_valid_bitfield(&ui64Type, 12);
217 	}
218 
219 	//CPU brand string.
220 	if (json_object_object_get_ex(section, "cpuBrandString", &obj)) {
221 		const char *brand_string = json_object_get_string(obj);
222 		if (brand_string != NULL) {
223 			strncpy(section_cper->BrandString, brand_string,
224 				sizeof(section_cper->BrandString) - 1);
225 			section_cper
226 				->BrandString[sizeof(section_cper->BrandString) -
227 					      1] = '\0';
228 		}
229 		add_to_valid_bitfield(&ui64Type, 7);
230 	}
231 	section_cper->ValidFields = ui64Type.value.ui64;
232 
233 	//Write & flush out to file, free memory.
234 	fwrite(section_cper, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA), 1, out);
235 	fflush(out);
236 	free(section_cper);
237 }
238