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