1 /**
2  * Describes functions for converting memory error CPER sections from binary and JSON format
3  * into an intermediate format.
4  *
5  * Author: Lawrence.Tang@arm.com
6  **/
7 #include <stdio.h>
8 #include <json.h>
9 #include <libcper/Cper.h>
10 #include <libcper/cper-utils.h>
11 #include <libcper/sections/cper-section-memory.h>
12 
13 //Converts a single memory error CPER section into JSON IR.
cper_section_platform_memory_to_ir(void * section)14 json_object *cper_section_platform_memory_to_ir(void *section)
15 {
16 	EFI_PLATFORM_MEMORY_ERROR_DATA *memory_error =
17 		(EFI_PLATFORM_MEMORY_ERROR_DATA *)section;
18 	json_object *section_ir = json_object_new_object();
19 
20 	//Validation bitfield.
21 	json_object *validation =
22 		bitfield_to_ir(memory_error->ValidFields, 22,
23 			       MEMORY_ERROR_VALID_BITFIELD_NAMES);
24 	json_object_object_add(section_ir, "validationBits", validation);
25 
26 	//Error status.
27 	json_object *error_status =
28 		cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
29 	json_object_object_add(section_ir, "errorStatus", error_status);
30 
31 	//Bank.
32 	json_object *bank = json_object_new_object();
33 	if ((memory_error->ValidFields >> 5) & 0x1) {
34 		//Entire bank address mode.
35 		json_object_object_add(
36 			bank, "value",
37 			json_object_new_uint64(memory_error->Bank));
38 	} else {
39 		//Address/group address mode.
40 		json_object_object_add(
41 			bank, "address",
42 			json_object_new_uint64(memory_error->Bank & 0xFF));
43 		json_object_object_add(
44 			bank, "group",
45 			json_object_new_uint64(memory_error->Bank >> 8));
46 	}
47 	json_object_object_add(section_ir, "bank", bank);
48 
49 	//Memory error type.
50 	json_object *memory_error_type = integer_to_readable_pair(
51 		memory_error->ErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
52 		MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
53 	json_object_object_add(section_ir, "memoryErrorType",
54 			       memory_error_type);
55 
56 	//"Extended" row/column indication field + misc.
57 	json_object *extended = json_object_new_object();
58 	json_object_object_add(extended, "rowBit16",
59 			       json_object_new_boolean(memory_error->Extended &
60 						       0x1));
61 	json_object_object_add(
62 		extended, "rowBit17",
63 		json_object_new_boolean((memory_error->Extended >> 1) & 0x1));
64 	json_object_object_add(extended, "chipIdentification",
65 			       json_object_new_int(memory_error->Extended >>
66 						   5));
67 	json_object_object_add(section_ir, "extended", extended);
68 
69 	//Miscellaneous numeric fields.
70 	json_object_object_add(
71 		section_ir, "physicalAddress",
72 		json_object_new_uint64(memory_error->PhysicalAddress));
73 	json_object_object_add(
74 		section_ir, "physicalAddressMask",
75 		json_object_new_uint64(memory_error->PhysicalAddressMask));
76 	json_object_object_add(section_ir, "node",
77 			       json_object_new_uint64(memory_error->Node));
78 	json_object_object_add(section_ir, "card",
79 			       json_object_new_uint64(memory_error->Card));
80 	json_object_object_add(
81 		section_ir, "moduleRank",
82 		json_object_new_uint64(memory_error->ModuleRank));
83 	json_object_object_add(section_ir, "device",
84 			       json_object_new_uint64(memory_error->Device));
85 	json_object_object_add(section_ir, "row",
86 			       json_object_new_uint64(memory_error->Row));
87 	json_object_object_add(section_ir, "column",
88 			       json_object_new_uint64(memory_error->Column));
89 	json_object_object_add(
90 		section_ir, "bitPosition",
91 		json_object_new_uint64(memory_error->BitPosition));
92 	json_object_object_add(
93 		section_ir, "requestorID",
94 		json_object_new_uint64(memory_error->RequestorId));
95 	json_object_object_add(
96 		section_ir, "responderID",
97 		json_object_new_uint64(memory_error->ResponderId));
98 	json_object_object_add(section_ir, "targetID",
99 			       json_object_new_uint64(memory_error->TargetId));
100 	json_object_object_add(section_ir, "rankNumber",
101 			       json_object_new_uint64(memory_error->RankNum));
102 	json_object_object_add(
103 		section_ir, "cardSmbiosHandle",
104 		json_object_new_uint64(memory_error->CardHandle));
105 	json_object_object_add(
106 		section_ir, "moduleSmbiosHandle",
107 		json_object_new_uint64(memory_error->ModuleHandle));
108 
109 	return section_ir;
110 }
111 
112 //Converts a single memory error 2 CPER section into JSON IR.
cper_section_platform_memory2_to_ir(void * section)113 json_object *cper_section_platform_memory2_to_ir(void *section)
114 {
115 	EFI_PLATFORM_MEMORY2_ERROR_DATA *memory_error =
116 		(EFI_PLATFORM_MEMORY2_ERROR_DATA *)section;
117 	json_object *section_ir = json_object_new_object();
118 
119 	//Validation bits.
120 	json_object *validation =
121 		bitfield_to_ir(memory_error->ValidFields, 22,
122 			       MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
123 	json_object_object_add(section_ir, "validationBits", validation);
124 
125 	//Error status.
126 	json_object *error_status =
127 		cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
128 	json_object_object_add(section_ir, "errorStatus", error_status);
129 
130 	//Bank.
131 	json_object *bank = json_object_new_object();
132 	if ((memory_error->ValidFields >> 5) & 0x1) {
133 		//Entire bank address mode.
134 		json_object_object_add(
135 			bank, "value",
136 			json_object_new_uint64(memory_error->Bank));
137 	} else {
138 		//Address/group address mode.
139 		json_object_object_add(
140 			bank, "address",
141 			json_object_new_uint64(memory_error->Bank & 0xFF));
142 		json_object_object_add(
143 			bank, "group",
144 			json_object_new_uint64(memory_error->Bank >> 8));
145 	}
146 	json_object_object_add(section_ir, "bank", bank);
147 
148 	//Memory error type.
149 	json_object *memory_error_type = integer_to_readable_pair(
150 		memory_error->MemErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
151 		MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
152 	json_object_object_add(section_ir, "memoryErrorType",
153 			       memory_error_type);
154 
155 	//Status.
156 	json_object *status = json_object_new_object();
157 	json_object_object_add(status, "value",
158 			       json_object_new_int(memory_error->Status));
159 	json_object_object_add(
160 		status, "state",
161 		json_object_new_string((memory_error->Status & 0x1) == 0 ?
162 					       "Corrected" :
163 					       "Uncorrected"));
164 	json_object_object_add(section_ir, "status", status);
165 
166 	//Miscellaneous numeric fields.
167 	json_object_object_add(
168 		section_ir, "physicalAddress",
169 		json_object_new_uint64(memory_error->PhysicalAddress));
170 	json_object_object_add(
171 		section_ir, "physicalAddressMask",
172 		json_object_new_uint64(memory_error->PhysicalAddressMask));
173 	json_object_object_add(section_ir, "node",
174 			       json_object_new_uint64(memory_error->Node));
175 	json_object_object_add(section_ir, "card",
176 			       json_object_new_uint64(memory_error->Card));
177 	json_object_object_add(section_ir, "module",
178 			       json_object_new_uint64(memory_error->Module));
179 	json_object_object_add(section_ir, "device",
180 			       json_object_new_uint64(memory_error->Device));
181 	json_object_object_add(section_ir, "row",
182 			       json_object_new_uint64(memory_error->Row));
183 	json_object_object_add(section_ir, "column",
184 			       json_object_new_uint64(memory_error->Column));
185 	json_object_object_add(section_ir, "rank",
186 			       json_object_new_uint64(memory_error->Rank));
187 	json_object_object_add(
188 		section_ir, "bitPosition",
189 		json_object_new_uint64(memory_error->BitPosition));
190 	json_object_object_add(section_ir, "chipID",
191 			       json_object_new_uint64(memory_error->ChipId));
192 	json_object_object_add(
193 		section_ir, "requestorID",
194 		json_object_new_uint64(memory_error->RequestorId));
195 	json_object_object_add(
196 		section_ir, "responderID",
197 		json_object_new_uint64(memory_error->ResponderId));
198 	json_object_object_add(section_ir, "targetID",
199 			       json_object_new_uint64(memory_error->TargetId));
200 	json_object_object_add(
201 		section_ir, "cardSmbiosHandle",
202 		json_object_new_uint64(memory_error->CardHandle));
203 	json_object_object_add(
204 		section_ir, "moduleSmbiosHandle",
205 		json_object_new_uint64(memory_error->ModuleHandle));
206 
207 	return section_ir;
208 }
209 
210 //Converts a single Memory Error IR section into CPER binary, outputting to the provided stream.
ir_section_memory_to_cper(json_object * section,FILE * out)211 void ir_section_memory_to_cper(json_object *section, FILE *out)
212 {
213 	EFI_PLATFORM_MEMORY_ERROR_DATA *section_cper =
214 		(EFI_PLATFORM_MEMORY_ERROR_DATA *)calloc(
215 			1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA));
216 
217 	//Validation bits.
218 	section_cper->ValidFields = ir_to_bitfield(
219 		json_object_object_get(section, "validationBits"), 22,
220 		MEMORY_ERROR_VALID_BITFIELD_NAMES);
221 
222 	//Error status.
223 	ir_generic_error_status_to_cper(json_object_object_get(section,
224 							       "errorStatus"),
225 					&section_cper->ErrorStatus);
226 
227 	//Bank.
228 	json_object *bank = json_object_object_get(section, "bank");
229 	if ((section_cper->ValidFields >> 5) & 0x1) {
230 		//Bank just uses simple address.
231 		section_cper->Bank = (UINT16)json_object_get_uint64(
232 			json_object_object_get(bank, "value"));
233 	} else {
234 		//Bank uses address/group style address.
235 		UINT16 address = (UINT8)json_object_get_uint64(
236 			json_object_object_get(bank, "address"));
237 		UINT16 group = (UINT8)json_object_get_uint64(
238 			json_object_object_get(bank, "group"));
239 		section_cper->Bank = address + (group << 8);
240 	}
241 
242 	//"Extended" field.
243 	json_object *extended = json_object_object_get(section, "extended");
244 	section_cper->Extended = 0;
245 	section_cper->Extended |= json_object_get_boolean(
246 		json_object_object_get(extended, "rowBit16"));
247 	section_cper->Extended |=
248 		json_object_get_boolean(
249 			json_object_object_get(extended, "rowBit17"))
250 		<< 1;
251 	section_cper->Extended |= json_object_get_int(json_object_object_get(
252 					  extended, "chipIdentification"))
253 				  << 5;
254 
255 	//Miscellaneous value fields.
256 	section_cper->ErrorType = (UINT8)readable_pair_to_integer(
257 		json_object_object_get(section, "memoryErrorType"));
258 	section_cper->PhysicalAddress = json_object_get_uint64(
259 		json_object_object_get(section, "physicalAddress"));
260 	section_cper->PhysicalAddressMask = json_object_get_uint64(
261 		json_object_object_get(section, "physicalAddressMask"));
262 	section_cper->Node = (UINT16)json_object_get_uint64(
263 		json_object_object_get(section, "node"));
264 	section_cper->Card = (UINT16)json_object_get_uint64(
265 		json_object_object_get(section, "card"));
266 	section_cper->ModuleRank = (UINT16)json_object_get_uint64(
267 		json_object_object_get(section, "moduleRank"));
268 	section_cper->Device = (UINT16)json_object_get_uint64(
269 		json_object_object_get(section, "device"));
270 	section_cper->Row = (UINT16)json_object_get_uint64(
271 		json_object_object_get(section, "row"));
272 	section_cper->Column = (UINT16)json_object_get_uint64(
273 		json_object_object_get(section, "column"));
274 	section_cper->BitPosition = (UINT16)json_object_get_uint64(
275 		json_object_object_get(section, "bitPosition"));
276 	section_cper->RequestorId = json_object_get_uint64(
277 		json_object_object_get(section, "requestorID"));
278 	section_cper->ResponderId = json_object_get_uint64(
279 		json_object_object_get(section, "responderID"));
280 	section_cper->TargetId = json_object_get_uint64(
281 		json_object_object_get(section, "targetID"));
282 	section_cper->RankNum = (UINT16)json_object_get_uint64(
283 		json_object_object_get(section, "rankNumber"));
284 	section_cper->CardHandle = (UINT16)json_object_get_uint64(
285 		json_object_object_get(section, "cardSmbiosHandle"));
286 	section_cper->ModuleHandle = (UINT16)json_object_get_uint64(
287 		json_object_object_get(section, "moduleSmbiosHandle"));
288 
289 	//Write to stream, free up resources.
290 	fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA), 1, out);
291 	fflush(out);
292 	free(section_cper);
293 }
294 
295 //Converts a single Memory Error 2 IR section into CPER binary, outputting to the provided stream.
ir_section_memory2_to_cper(json_object * section,FILE * out)296 void ir_section_memory2_to_cper(json_object *section, FILE *out)
297 {
298 	EFI_PLATFORM_MEMORY2_ERROR_DATA *section_cper =
299 		(EFI_PLATFORM_MEMORY2_ERROR_DATA *)calloc(
300 			1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA));
301 
302 	//Validation bits.
303 	section_cper->ValidFields = ir_to_bitfield(
304 		json_object_object_get(section, "validationBits"), 22,
305 		MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
306 
307 	//Error status.
308 	ir_generic_error_status_to_cper(json_object_object_get(section,
309 							       "errorStatus"),
310 					&section_cper->ErrorStatus);
311 
312 	//Bank.
313 	json_object *bank = json_object_object_get(section, "bank");
314 	if ((section_cper->ValidFields >> 5) & 0x1) {
315 		//Bank just uses simple address.
316 		section_cper->Bank = (UINT16)json_object_get_uint64(
317 			json_object_object_get(bank, "value"));
318 	} else {
319 		//Bank uses address/group style address.
320 		UINT16 address = (UINT8)json_object_get_uint64(
321 			json_object_object_get(bank, "address"));
322 		UINT16 group = (UINT8)json_object_get_uint64(
323 			json_object_object_get(bank, "group"));
324 		section_cper->Bank = address + (group << 8);
325 	}
326 
327 	//Miscellaneous value fields.
328 	section_cper->MemErrorType = readable_pair_to_integer(
329 		json_object_object_get(section, "memoryErrorType"));
330 	section_cper->Status = (UINT8)readable_pair_to_integer(
331 		json_object_object_get(section, "status"));
332 	section_cper->PhysicalAddress = json_object_get_uint64(
333 		json_object_object_get(section, "physicalAddress"));
334 	section_cper->PhysicalAddressMask = json_object_get_uint64(
335 		json_object_object_get(section, "physicalAddressMask"));
336 	section_cper->Node = (UINT16)json_object_get_uint64(
337 		json_object_object_get(section, "node"));
338 	section_cper->Card = (UINT16)json_object_get_uint64(
339 		json_object_object_get(section, "card"));
340 	section_cper->Module = (UINT32)json_object_get_uint64(
341 		json_object_object_get(section, "module"));
342 	section_cper->Device = (UINT32)json_object_get_uint64(
343 		json_object_object_get(section, "device"));
344 	section_cper->Row = (UINT32)json_object_get_uint64(
345 		json_object_object_get(section, "row"));
346 	section_cper->Column = (UINT32)json_object_get_uint64(
347 		json_object_object_get(section, "column"));
348 	section_cper->Rank = (UINT32)json_object_get_uint64(
349 		json_object_object_get(section, "rank"));
350 	section_cper->BitPosition = (UINT32)json_object_get_uint64(
351 		json_object_object_get(section, "bitPosition"));
352 	section_cper->ChipId = (UINT8)json_object_get_uint64(
353 		json_object_object_get(section, "chipID"));
354 	section_cper->RequestorId = json_object_get_uint64(
355 		json_object_object_get(section, "requestorID"));
356 	section_cper->ResponderId = json_object_get_uint64(
357 		json_object_object_get(section, "responderID"));
358 	section_cper->TargetId = json_object_get_uint64(
359 		json_object_object_get(section, "targetID"));
360 	section_cper->CardHandle = (UINT32)json_object_get_uint64(
361 		json_object_object_get(section, "cardSmbiosHandle"));
362 	section_cper->ModuleHandle = (UINT32)json_object_get_uint64(
363 		json_object_object_get(section, "moduleSmbiosHandle"));
364 
365 	//Write to stream, free up resources.
366 	fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out);
367 	fflush(out);
368 	free(section_cper);
369 }
370