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