xref: /openbmc/libcper/sections/cper-section-memory.c (revision da75128c6e2e9a9639d381441573d2e20e3a1ddf)
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 #include <libcper/log.h>
13 #include <string.h>
14 
15 //Converts a single memory error CPER section into JSON IR.
cper_section_platform_memory_to_ir(const UINT8 * section,UINT32 size,char ** desc_string)16 json_object *cper_section_platform_memory_to_ir(const UINT8 *section,
17 						UINT32 size, char **desc_string)
18 {
19 	int outstr_len = 0;
20 	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
21 	if (size < sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)) {
22 		return NULL;
23 	}
24 
25 	EFI_PLATFORM_MEMORY_ERROR_DATA *memory_error =
26 		(EFI_PLATFORM_MEMORY_ERROR_DATA *)section;
27 	json_object *section_ir = json_object_new_object();
28 
29 	ValidationTypes ui64Type = { UINT_64T,
30 				     .value.ui64 = memory_error->ValidFields };
31 
32 	//Error status.
33 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
34 		json_object *error_status = cper_generic_error_status_to_ir(
35 			&memory_error->ErrorStatus);
36 		json_object_object_add(section_ir, "errorStatus", error_status);
37 	}
38 
39 	//Bank
40 	json_object *bank = json_object_new_object();
41 	if (isvalid_prop_to_ir(&ui64Type, 6)) {
42 		//Entire bank address mode.
43 		json_object_object_add(
44 			bank, "value",
45 			json_object_new_uint64(memory_error->Bank));
46 	} else {
47 		//Address/group address mode.
48 		json_object_object_add(
49 			bank, "address",
50 			json_object_new_uint64(memory_error->Bank & 0xFF));
51 		json_object_object_add(
52 			bank, "group",
53 			json_object_new_uint64(memory_error->Bank >> 8));
54 	}
55 	json_object_object_add(section_ir, "bank", bank);
56 
57 	//Memory error type.
58 	const char *mem_type_str = NULL;
59 	if (isvalid_prop_to_ir(&ui64Type, 14)) {
60 		json_object *memory_error_type = integer_to_readable_pair(
61 			memory_error->ErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
62 			MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
63 		json_object_object_add(section_ir, "memoryErrorType",
64 				       memory_error_type);
65 		mem_type_str = json_object_get_string(
66 			json_object_object_get(memory_error_type, "name"));
67 	}
68 	if (mem_type_str != NULL) {
69 		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
70 				      "A %s Memory Error occurred",
71 				      mem_type_str);
72 	} else {
73 		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
74 				      "An Unknown Memory Error occurred");
75 	}
76 	if (outstr_len < 0) {
77 		cper_print_log(
78 			"Error: Could not write to Memory description string\n");
79 	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
80 		cper_print_log(
81 			"Error: Memory description string truncated: %s\n",
82 			*desc_string);
83 	}
84 	//"Extended" row/column indication field + misc.
85 	if (isvalid_prop_to_ir(&ui64Type, 18)) {
86 		json_object *extended = json_object_new_object();
87 		json_object_object_add(
88 			extended, "rowBit16",
89 			json_object_new_boolean(memory_error->Extended & 0x1));
90 		json_object_object_add(
91 			extended, "rowBit17",
92 			json_object_new_boolean((memory_error->Extended >> 1) &
93 						0x1));
94 		if (isvalid_prop_to_ir(&ui64Type, 21)) {
95 			json_object_object_add(
96 				extended, "chipIdentification",
97 				json_object_new_int(memory_error->Extended >>
98 						    5));
99 		}
100 		json_object_object_add(section_ir, "extended", extended);
101 	}
102 
103 	if (isvalid_prop_to_ir(&ui64Type, 16)) {
104 		json_object_object_add(
105 			section_ir, "cardSmbiosHandle",
106 			json_object_new_uint64(memory_error->CardHandle));
107 	}
108 	if (isvalid_prop_to_ir(&ui64Type, 17)) {
109 		json_object_object_add(
110 			section_ir, "moduleSmbiosHandle",
111 			json_object_new_uint64(memory_error->ModuleHandle));
112 	}
113 
114 	//Miscellaneous numeric fields.
115 	if (isvalid_prop_to_ir(&ui64Type, 1)) {
116 		json_object_object_add(
117 			section_ir, "physicalAddress",
118 			json_object_new_uint64(memory_error->PhysicalAddress));
119 
120 		char hexstring_buf[EFI_UINT64_HEX_STRING_LEN];
121 		snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX",
122 			 memory_error->PhysicalAddress);
123 		json_object_object_add(section_ir, "physicalAddressHex",
124 				       json_object_new_string(hexstring_buf));
125 		char physical_address_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
126 		outstr_len = snprintf(physical_address_desc,
127 				      EFI_ERROR_DESCRIPTION_STRING_LEN,
128 				      " at address 0x%016llX",
129 				      memory_error->PhysicalAddress);
130 		if (outstr_len < 0) {
131 			cper_print_log(
132 				"Error: Could not write to physical address description string\n");
133 		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
134 			cper_print_log(
135 				"Error: Physical address description string truncated: %s\n",
136 				physical_address_desc);
137 		} else {
138 			if (strlen(physical_address_desc) +
139 				    strlen(*desc_string) <
140 			    SECTION_DESC_STRING_SIZE) {
141 				strncat(*desc_string, physical_address_desc,
142 					outstr_len);
143 			} else {
144 				cper_print_log(
145 					"Error: Memory description string too long, not added to description string: %s\n",
146 					physical_address_desc);
147 			}
148 		}
149 	}
150 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
151 		json_object_object_add(
152 			section_ir, "physicalAddressMask",
153 			json_object_new_uint64(
154 				memory_error->PhysicalAddressMask));
155 	}
156 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
157 		json_object_object_add(
158 			section_ir, "node",
159 			json_object_new_uint64(memory_error->Node));
160 		char node_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
161 		outstr_len = snprintf(node_desc,
162 				      EFI_ERROR_DESCRIPTION_STRING_LEN,
163 				      " at node %d", memory_error->Node);
164 		if (outstr_len < 0) {
165 			cper_print_log(
166 				"Error: Could not write to node description string\n");
167 		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
168 			cper_print_log(
169 				"Error: Node description string truncated: %s\n",
170 				node_desc);
171 		} else {
172 			if (strlen(node_desc) + strlen(*desc_string) <
173 			    SECTION_DESC_STRING_SIZE) {
174 				strncat(*desc_string, node_desc, outstr_len);
175 			} else {
176 				cper_print_log(
177 					"Error: Memory description string too long, not added to description string: %s\n",
178 					node_desc);
179 			}
180 		}
181 	}
182 
183 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
184 		json_object_object_add(
185 			section_ir, "card",
186 			json_object_new_uint64(memory_error->Card));
187 	}
188 	if (isvalid_prop_to_ir(&ui64Type, 5)) {
189 		json_object_object_add(
190 			section_ir, "moduleRank",
191 			json_object_new_uint64(memory_error->ModuleRank));
192 	}
193 	if (isvalid_prop_to_ir(&ui64Type, 7)) {
194 		json_object_object_add(
195 			section_ir, "device",
196 			json_object_new_uint64(memory_error->Device));
197 	}
198 	if (isvalid_prop_to_ir(&ui64Type, 8)) {
199 		json_object_object_add(
200 			section_ir, "row",
201 			json_object_new_uint64(memory_error->Row));
202 	}
203 	if (isvalid_prop_to_ir(&ui64Type, 9)) {
204 		json_object_object_add(
205 			section_ir, "column",
206 			json_object_new_uint64(memory_error->Column));
207 	}
208 	if (isvalid_prop_to_ir(&ui64Type, 10)) {
209 		json_object_object_add(
210 			section_ir, "bitPosition",
211 			json_object_new_uint64(memory_error->BitPosition));
212 	}
213 	if (isvalid_prop_to_ir(&ui64Type, 11)) {
214 		json_object_object_add(
215 			section_ir, "requestorID",
216 			json_object_new_uint64(memory_error->RequestorId));
217 	}
218 	if (isvalid_prop_to_ir(&ui64Type, 12)) {
219 		json_object_object_add(
220 			section_ir, "responderID",
221 			json_object_new_uint64(memory_error->ResponderId));
222 	}
223 	if (isvalid_prop_to_ir(&ui64Type, 13)) {
224 		json_object_object_add(
225 			section_ir, "targetID",
226 			json_object_new_uint64(memory_error->TargetId));
227 	}
228 	if (isvalid_prop_to_ir(&ui64Type, 15)) {
229 		json_object_object_add(
230 			section_ir, "rankNumber",
231 			json_object_new_uint64(memory_error->RankNum));
232 	}
233 
234 	return section_ir;
235 }
236 
237 //Converts a single memory error 2 CPER section into JSON IR.
cper_section_platform_memory2_to_ir(const UINT8 * section,UINT32 size,char ** desc_string)238 json_object *cper_section_platform_memory2_to_ir(const UINT8 *section,
239 						 UINT32 size,
240 						 char **desc_string)
241 {
242 	int outstr_len = 0;
243 	*desc_string = malloc(SECTION_DESC_STRING_SIZE);
244 
245 	if (size < sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA)) {
246 		return NULL;
247 	}
248 
249 	EFI_PLATFORM_MEMORY2_ERROR_DATA *memory_error =
250 		(EFI_PLATFORM_MEMORY2_ERROR_DATA *)section;
251 	json_object *section_ir = json_object_new_object();
252 
253 	ValidationTypes ui64Type = { UINT_64T,
254 				     .value.ui64 = memory_error->ValidFields };
255 
256 	//Error status.
257 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
258 		json_object *error_status = cper_generic_error_status_to_ir(
259 			&memory_error->ErrorStatus);
260 		json_object_object_add(section_ir, "errorStatus", error_status);
261 	}
262 
263 	//Bank.
264 	json_object *bank = json_object_new_object();
265 	if (isvalid_prop_to_ir(&ui64Type, 6)) {
266 		//Entire bank address mode.
267 		json_object_object_add(
268 			bank, "value",
269 			json_object_new_uint64(memory_error->Bank));
270 	} else {
271 		//Address/group address mode.
272 		json_object_object_add(
273 			bank, "address",
274 			json_object_new_uint64(memory_error->Bank & 0xFF));
275 		json_object_object_add(
276 			bank, "group",
277 			json_object_new_uint64(memory_error->Bank >> 8));
278 	}
279 	json_object_object_add(section_ir, "bank", bank);
280 
281 	//Memory error type.
282 	const char *mem_type_str = NULL;
283 	if (isvalid_prop_to_ir(&ui64Type, 13)) {
284 		json_object *memory_error_type = integer_to_readable_pair(
285 			memory_error->MemErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
286 			MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
287 		json_object_object_add(section_ir, "memoryErrorType",
288 				       memory_error_type);
289 		mem_type_str = json_object_get_string(
290 			json_object_object_get(memory_error_type, "name"));
291 	}
292 	if (mem_type_str != NULL) {
293 		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
294 				      "A %s Memory Error occurred",
295 				      mem_type_str);
296 	} else {
297 		outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
298 				      "An Unknown Memory Error occurred");
299 	}
300 	if (outstr_len < 0) {
301 		cper_print_log(
302 			"Error: Could not write to Memory2 description string\n");
303 	} else if (outstr_len > SECTION_DESC_STRING_SIZE) {
304 		cper_print_log(
305 			"Error: Memory2 description string truncated: %s\n",
306 			*desc_string);
307 	}
308 	//Status.
309 	if (isvalid_prop_to_ir(&ui64Type, 14)) {
310 		json_object *status = json_object_new_object();
311 		json_object_object_add(
312 			status, "value",
313 			json_object_new_int(memory_error->Status));
314 		json_object_object_add(
315 			status, "state",
316 			json_object_new_string((memory_error->Status & 0x1) ==
317 							       0 ?
318 						       "Corrected" :
319 						       "Uncorrected"));
320 		json_object_object_add(section_ir, "status", status);
321 	}
322 
323 	//Miscellaneous numeric fields.
324 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
325 		json_object_object_add(
326 			section_ir, "physicalAddress",
327 			json_object_new_uint64(memory_error->PhysicalAddress));
328 		char physical_address_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
329 		outstr_len = snprintf(physical_address_desc,
330 				      EFI_ERROR_DESCRIPTION_STRING_LEN,
331 				      " at address 0x%016llX",
332 				      memory_error->PhysicalAddress);
333 		if (outstr_len < 0) {
334 			cper_print_log(
335 				"Error: Could not write to physical address description string\n");
336 		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
337 			cper_print_log(
338 				"Error: Physical address description string truncated: %s\n",
339 				physical_address_desc);
340 		} else {
341 			if (strlen(physical_address_desc) +
342 				    strlen(*desc_string) <
343 			    SECTION_DESC_STRING_SIZE) {
344 				strncat(*desc_string, physical_address_desc,
345 					outstr_len);
346 			} else {
347 				cper_print_log(
348 					"Error: Memory2 description string too long, not added to description string: %s\n",
349 					physical_address_desc);
350 			}
351 		}
352 	}
353 
354 	char hexstring_buf[EFI_UINT64_HEX_STRING_LEN];
355 	snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX",
356 		 memory_error->PhysicalAddress);
357 	json_object_object_add(section_ir, "physicalAddressHex",
358 			       json_object_new_string(hexstring_buf));
359 
360 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
361 		json_object_object_add(
362 			section_ir, "physicalAddressMask",
363 			json_object_new_uint64(
364 				memory_error->PhysicalAddressMask));
365 	}
366 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
367 		json_object_object_add(
368 			section_ir, "node",
369 			json_object_new_uint64(memory_error->Node));
370 		char node_desc[EFI_ERROR_DESCRIPTION_STRING_LEN];
371 		outstr_len = snprintf(node_desc,
372 				      EFI_ERROR_DESCRIPTION_STRING_LEN,
373 				      " on node %d", memory_error->Node);
374 		if (outstr_len < 0) {
375 			cper_print_log(
376 				"Error: Could not write to node description string\n");
377 		} else if (outstr_len > EFI_ERROR_DESCRIPTION_STRING_LEN) {
378 			cper_print_log(
379 				"Error: Node description string truncated: %s\n",
380 				node_desc);
381 		} else {
382 			if (strlen(node_desc) + strlen(*desc_string) <
383 			    SECTION_DESC_STRING_SIZE) {
384 				strncat(*desc_string, node_desc, outstr_len);
385 			} else {
386 				cper_print_log(
387 					"Error: Memory2 description string too long, not added to description string: %s\n",
388 					node_desc);
389 			}
390 		}
391 	}
392 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
393 		json_object_object_add(
394 			section_ir, "card",
395 			json_object_new_uint64(memory_error->Card));
396 	}
397 	if (isvalid_prop_to_ir(&ui64Type, 5)) {
398 		json_object_object_add(
399 			section_ir, "module",
400 			json_object_new_uint64(memory_error->Module));
401 	}
402 	if (isvalid_prop_to_ir(&ui64Type, 7)) {
403 		json_object_object_add(
404 			section_ir, "device",
405 			json_object_new_uint64(memory_error->Device));
406 	}
407 	if (isvalid_prop_to_ir(&ui64Type, 8)) {
408 		json_object_object_add(
409 			section_ir, "row",
410 			json_object_new_uint64(memory_error->Row));
411 	}
412 	if (isvalid_prop_to_ir(&ui64Type, 9)) {
413 		json_object_object_add(
414 			section_ir, "column",
415 			json_object_new_uint64(memory_error->Column));
416 	}
417 	if (isvalid_prop_to_ir(&ui64Type, 10)) {
418 		json_object_object_add(
419 			section_ir, "rank",
420 			json_object_new_uint64(memory_error->Rank));
421 	}
422 	if (isvalid_prop_to_ir(&ui64Type, 11)) {
423 		json_object_object_add(
424 			section_ir, "bitPosition",
425 			json_object_new_uint64(memory_error->BitPosition));
426 	}
427 	if (isvalid_prop_to_ir(&ui64Type, 12)) {
428 		json_object_object_add(
429 			section_ir, "chipID",
430 			json_object_new_uint64(memory_error->ChipId));
431 	}
432 	if (isvalid_prop_to_ir(&ui64Type, 15)) {
433 		json_object_object_add(
434 			section_ir, "requestorID",
435 			json_object_new_uint64(memory_error->RequestorId));
436 	}
437 	if (isvalid_prop_to_ir(&ui64Type, 16)) {
438 		json_object_object_add(
439 			section_ir, "responderID",
440 			json_object_new_uint64(memory_error->ResponderId));
441 	}
442 	if (isvalid_prop_to_ir(&ui64Type, 17)) {
443 		json_object_object_add(
444 			section_ir, "targetID",
445 			json_object_new_uint64(memory_error->TargetId));
446 	}
447 	if (isvalid_prop_to_ir(&ui64Type, 18)) {
448 		json_object_object_add(
449 			section_ir, "cardSmbiosHandle",
450 			json_object_new_uint64(memory_error->CardHandle));
451 	}
452 	if (isvalid_prop_to_ir(&ui64Type, 19)) {
453 		json_object_object_add(
454 			section_ir, "moduleSmbiosHandle",
455 			json_object_new_uint64(memory_error->ModuleHandle));
456 	}
457 
458 	return section_ir;
459 }
460 
461 //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)462 void ir_section_memory_to_cper(json_object *section, FILE *out)
463 {
464 	EFI_PLATFORM_MEMORY_ERROR_DATA *section_cper =
465 		(EFI_PLATFORM_MEMORY_ERROR_DATA *)calloc(
466 			1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA));
467 
468 	ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
469 	struct json_object *obj = NULL;
470 
471 	//Error status.
472 	if (json_object_object_get_ex(section, "errorStatus", &obj)) {
473 		ir_generic_error_status_to_cper(obj,
474 						&section_cper->ErrorStatus);
475 		add_to_valid_bitfield(&ui64Type, 0);
476 	}
477 
478 	//Bank.
479 	if (json_object_object_get_ex(section, "bank", &obj)) {
480 		json_object *bank = obj;
481 		if (json_object_object_get_ex(bank, "value", &obj)) {
482 			//Bank just uses simple address.
483 			section_cper->Bank =
484 				(UINT16)json_object_get_uint64(obj);
485 			add_to_valid_bitfield(&ui64Type, 6);
486 		} else {
487 			//Bank uses address/group style address.
488 			UINT16 address = (UINT8)json_object_get_uint64(
489 				json_object_object_get(bank, "address"));
490 			UINT16 group = (UINT8)json_object_get_uint64(
491 				json_object_object_get(bank, "group"));
492 			section_cper->Bank = address + (group << 8);
493 			add_to_valid_bitfield(&ui64Type, 19);
494 			add_to_valid_bitfield(&ui64Type, 20);
495 		}
496 	}
497 
498 	//"Extended" field.
499 	if (json_object_object_get_ex(section, "extended", &obj)) {
500 		json_object *extended = obj;
501 		section_cper->Extended = 0;
502 		section_cper->Extended |= json_object_get_boolean(
503 			json_object_object_get(extended, "rowBit16"));
504 		section_cper->Extended |=
505 			json_object_get_boolean(
506 				json_object_object_get(extended, "rowBit17"))
507 			<< 1;
508 		if (json_object_object_get_ex(extended, "chipIdentification",
509 					      &obj)) {
510 			section_cper->Extended |= json_object_get_int(obj) << 5;
511 			add_to_valid_bitfield(&ui64Type, 21);
512 		}
513 		add_to_valid_bitfield(&ui64Type, 18);
514 	}
515 
516 	//Miscellaneous value fields.
517 	if (json_object_object_get_ex(section, "memoryErrorType", &obj)) {
518 		section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj);
519 		add_to_valid_bitfield(&ui64Type, 14);
520 	}
521 	if (json_object_object_get_ex(section, "physicalAddress", &obj)) {
522 		section_cper->PhysicalAddress = json_object_get_uint64(obj);
523 		add_to_valid_bitfield(&ui64Type, 1);
524 	}
525 	if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) {
526 		section_cper->PhysicalAddressMask = json_object_get_uint64(obj);
527 		add_to_valid_bitfield(&ui64Type, 2);
528 	}
529 	if (json_object_object_get_ex(section, "node", &obj)) {
530 		section_cper->Node = (UINT16)json_object_get_uint64(obj);
531 		add_to_valid_bitfield(&ui64Type, 3);
532 	}
533 	if (json_object_object_get_ex(section, "card", &obj)) {
534 		section_cper->Card = (UINT16)json_object_get_uint64(obj);
535 		add_to_valid_bitfield(&ui64Type, 4);
536 	}
537 	if (json_object_object_get_ex(section, "moduleRank", &obj)) {
538 		section_cper->ModuleRank = (UINT16)json_object_get_uint64(obj);
539 		add_to_valid_bitfield(&ui64Type, 5);
540 	}
541 	if (json_object_object_get_ex(section, "device", &obj)) {
542 		section_cper->Device = (UINT16)json_object_get_uint64(obj);
543 		add_to_valid_bitfield(&ui64Type, 7);
544 	}
545 	if (json_object_object_get_ex(section, "row", &obj)) {
546 		section_cper->Row = (UINT16)json_object_get_uint64(obj);
547 		add_to_valid_bitfield(&ui64Type, 8);
548 	}
549 	if (json_object_object_get_ex(section, "column", &obj)) {
550 		section_cper->Column = (UINT16)json_object_get_uint64(obj);
551 		add_to_valid_bitfield(&ui64Type, 9);
552 	}
553 	if (json_object_object_get_ex(section, "bitPosition", &obj)) {
554 		section_cper->BitPosition = (UINT16)json_object_get_uint64(obj);
555 		add_to_valid_bitfield(&ui64Type, 10);
556 	}
557 	if (json_object_object_get_ex(section, "requestorID", &obj)) {
558 		section_cper->RequestorId = json_object_get_uint64(obj);
559 		add_to_valid_bitfield(&ui64Type, 11);
560 	}
561 	if (json_object_object_get_ex(section, "responderID", &obj)) {
562 		section_cper->ResponderId = json_object_get_uint64(obj);
563 		add_to_valid_bitfield(&ui64Type, 12);
564 	}
565 	if (json_object_object_get_ex(section, "targetID", &obj)) {
566 		section_cper->TargetId = json_object_get_uint64(obj);
567 		add_to_valid_bitfield(&ui64Type, 13);
568 	}
569 	if (json_object_object_get_ex(section, "rankNumber", &obj)) {
570 		section_cper->RankNum = (UINT16)json_object_get_uint64(
571 			json_object_object_get(section, "rankNumber"));
572 		add_to_valid_bitfield(&ui64Type, 15);
573 	}
574 	if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) {
575 		section_cper->CardHandle = (UINT16)json_object_get_uint64(obj);
576 		add_to_valid_bitfield(&ui64Type, 16);
577 	}
578 	if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) {
579 		section_cper->ModuleHandle =
580 			(UINT16)json_object_get_uint64(obj);
581 		add_to_valid_bitfield(&ui64Type, 17);
582 	}
583 	section_cper->ValidFields = ui64Type.value.ui64;
584 
585 	//Write to stream, free up resources.
586 	fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA), 1, out);
587 	fflush(out);
588 	free(section_cper);
589 }
590 
591 //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)592 void ir_section_memory2_to_cper(json_object *section, FILE *out)
593 {
594 	EFI_PLATFORM_MEMORY2_ERROR_DATA *section_cper =
595 		(EFI_PLATFORM_MEMORY2_ERROR_DATA *)calloc(
596 			1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA));
597 
598 	//Validation bits.
599 	ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
600 	struct json_object *obj = NULL;
601 
602 	//Error status.
603 	if (json_object_object_get_ex(section, "errorStatus", &obj)) {
604 		ir_generic_error_status_to_cper(obj,
605 						&section_cper->ErrorStatus);
606 		add_to_valid_bitfield(&ui64Type, 0);
607 	}
608 
609 	//Bank.
610 	json_object *bank = json_object_object_get(section, "bank");
611 	if (json_object_object_get_ex(bank, "value", &obj)) {
612 		//Bank just uses simple address.
613 		section_cper->Bank = (UINT16)json_object_get_uint64(obj);
614 		add_to_valid_bitfield(&ui64Type, 6);
615 	} else {
616 		//Bank uses address/group style address.
617 		UINT16 address = (UINT8)json_object_get_uint64(
618 			json_object_object_get(bank, "address"));
619 		UINT16 group = (UINT8)json_object_get_uint64(
620 			json_object_object_get(bank, "group"));
621 		section_cper->Bank = address + (group << 8);
622 		add_to_valid_bitfield(&ui64Type, 20);
623 		add_to_valid_bitfield(&ui64Type, 21);
624 	}
625 
626 	//Miscellaneous value fields.
627 	if (json_object_object_get_ex(section, "memoryErrorType", &obj)) {
628 		section_cper->MemErrorType = readable_pair_to_integer(obj);
629 		add_to_valid_bitfield(&ui64Type, 13);
630 	}
631 	if (json_object_object_get_ex(section, "status", &obj)) {
632 		section_cper->Status = (UINT8)readable_pair_to_integer(obj);
633 		add_to_valid_bitfield(&ui64Type, 14);
634 	}
635 	if (json_object_object_get_ex(section, "physicalAddress", &obj)) {
636 		section_cper->PhysicalAddress = json_object_get_uint64(obj);
637 		add_to_valid_bitfield(&ui64Type, 1);
638 	}
639 	if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) {
640 		section_cper->PhysicalAddressMask = json_object_get_uint64(obj);
641 		add_to_valid_bitfield(&ui64Type, 2);
642 	}
643 	if (json_object_object_get_ex(section, "node", &obj)) {
644 		section_cper->Node = (UINT16)json_object_get_uint64(obj);
645 		add_to_valid_bitfield(&ui64Type, 3);
646 	}
647 	if (json_object_object_get_ex(section, "card", &obj)) {
648 		section_cper->Card = (UINT16)json_object_get_uint64(obj);
649 		add_to_valid_bitfield(&ui64Type, 4);
650 	}
651 	if (json_object_object_get_ex(section, "module", &obj)) {
652 		section_cper->Module = (UINT32)json_object_get_uint64(obj);
653 		add_to_valid_bitfield(&ui64Type, 5);
654 	}
655 	if (json_object_object_get_ex(section, "device", &obj)) {
656 		section_cper->Device = (UINT32)json_object_get_uint64(obj);
657 		add_to_valid_bitfield(&ui64Type, 7);
658 	}
659 	if (json_object_object_get_ex(section, "row", &obj)) {
660 		section_cper->Row = (UINT32)json_object_get_uint64(obj);
661 		add_to_valid_bitfield(&ui64Type, 8);
662 	}
663 	if (json_object_object_get_ex(section, "column", &obj)) {
664 		section_cper->Column = (UINT32)json_object_get_uint64(obj);
665 		add_to_valid_bitfield(&ui64Type, 9);
666 	}
667 	if (json_object_object_get_ex(section, "rank", &obj)) {
668 		section_cper->Rank = (UINT32)json_object_get_uint64(obj);
669 		add_to_valid_bitfield(&ui64Type, 10);
670 	}
671 	if (json_object_object_get_ex(section, "bitPosition", &obj)) {
672 		section_cper->BitPosition = (UINT32)json_object_get_uint64(obj);
673 		add_to_valid_bitfield(&ui64Type, 11);
674 	}
675 	if (json_object_object_get_ex(section, "chipID", &obj)) {
676 		section_cper->ChipId = (UINT8)json_object_get_uint64(obj);
677 		add_to_valid_bitfield(&ui64Type, 12);
678 	}
679 	if (json_object_object_get_ex(section, "requestorID", &obj)) {
680 		section_cper->RequestorId = json_object_get_uint64(obj);
681 		add_to_valid_bitfield(&ui64Type, 15);
682 	}
683 	if (json_object_object_get_ex(section, "responderID", &obj)) {
684 		section_cper->ResponderId = json_object_get_uint64(obj);
685 		add_to_valid_bitfield(&ui64Type, 16);
686 	}
687 	if (json_object_object_get_ex(section, "targetID", &obj)) {
688 		section_cper->TargetId = json_object_get_uint64(obj);
689 		add_to_valid_bitfield(&ui64Type, 17);
690 	}
691 	if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) {
692 		section_cper->CardHandle = (UINT32)json_object_get_uint64(obj);
693 		add_to_valid_bitfield(&ui64Type, 18);
694 	}
695 	if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) {
696 		section_cper->ModuleHandle =
697 			(UINT32)json_object_get_uint64(obj);
698 		add_to_valid_bitfield(&ui64Type, 19);
699 	}
700 
701 	section_cper->ValidFields = ui64Type.value.ui64;
702 
703 	//Write to stream, free up resources.
704 	fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out);
705 	fflush(out);
706 	free(section_cper);
707 }
708