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