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