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 ValidationTypes ui64Type = { UINT_64T,
21 .value.ui64 = memory_error->ValidFields };
22
23 //Error status.
24 if (isvalid_prop_to_ir(&ui64Type, 0)) {
25 json_object *error_status = cper_generic_error_status_to_ir(
26 &memory_error->ErrorStatus);
27 json_object_object_add(section_ir, "errorStatus", error_status);
28 }
29
30 //Bank
31 json_object *bank = json_object_new_object();
32 if (isvalid_prop_to_ir(&ui64Type, 6)) {
33 //Entire bank address mode.
34 json_object_object_add(
35 bank, "value",
36 json_object_new_uint64(memory_error->Bank));
37 } else {
38 //Address/group address mode.
39 json_object_object_add(
40 bank, "address",
41 json_object_new_uint64(memory_error->Bank & 0xFF));
42 json_object_object_add(
43 bank, "group",
44 json_object_new_uint64(memory_error->Bank >> 8));
45 }
46 json_object_object_add(section_ir, "bank", bank);
47
48 //Memory error type.
49 if (isvalid_prop_to_ir(&ui64Type, 14)) {
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
57 //"Extended" row/column indication field + misc.
58 // Review this
59 if (isvalid_prop_to_ir(&ui64Type, 18)) {
60 json_object *extended = json_object_new_object();
61 json_object_object_add(
62 extended, "rowBit16",
63 json_object_new_boolean(memory_error->Extended & 0x1));
64 json_object_object_add(
65 extended, "rowBit17",
66 json_object_new_boolean((memory_error->Extended >> 1) &
67 0x1));
68 if (isvalid_prop_to_ir(&ui64Type, 21)) {
69 json_object_object_add(
70 extended, "chipIdentification",
71 json_object_new_int(memory_error->Extended >>
72 5));
73 }
74 json_object_object_add(section_ir, "extended", extended);
75
76 //bit 16 and 17 are valid only if extended is valid
77 if (isvalid_prop_to_ir(&ui64Type, 16)) {
78 json_object_object_add(
79 section_ir, "cardSmbiosHandle",
80 json_object_new_uint64(
81 memory_error->CardHandle));
82 }
83 if (isvalid_prop_to_ir(&ui64Type, 17)) {
84 json_object_object_add(
85 section_ir, "moduleSmbiosHandle",
86 json_object_new_uint64(
87 memory_error->ModuleHandle));
88 }
89 }
90
91 //Miscellaneous numeric fields.
92 if (isvalid_prop_to_ir(&ui64Type, 1)) {
93 json_object_object_add(
94 section_ir, "physicalAddress",
95 json_object_new_uint64(memory_error->PhysicalAddress));
96
97 char hexstring_buf[EFI_UINT64_HEX_STRING_LEN];
98 snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX",
99 memory_error->PhysicalAddress);
100 json_object_object_add(section_ir, "physicalAddressHex",
101 json_object_new_string(hexstring_buf));
102 }
103 if (isvalid_prop_to_ir(&ui64Type, 2)) {
104 json_object_object_add(
105 section_ir, "physicalAddressMask",
106 json_object_new_uint64(
107 memory_error->PhysicalAddressMask));
108 }
109 if (isvalid_prop_to_ir(&ui64Type, 3)) {
110 json_object_object_add(
111 section_ir, "node",
112 json_object_new_uint64(memory_error->Node));
113 }
114 if (isvalid_prop_to_ir(&ui64Type, 4)) {
115 json_object_object_add(
116 section_ir, "card",
117 json_object_new_uint64(memory_error->Card));
118 }
119 if (isvalid_prop_to_ir(&ui64Type, 5)) {
120 json_object_object_add(
121 section_ir, "moduleRank",
122 json_object_new_uint64(memory_error->ModuleRank));
123 }
124 if (isvalid_prop_to_ir(&ui64Type, 7)) {
125 json_object_object_add(
126 section_ir, "device",
127 json_object_new_uint64(memory_error->Device));
128 }
129 if (isvalid_prop_to_ir(&ui64Type, 8)) {
130 json_object_object_add(
131 section_ir, "row",
132 json_object_new_uint64(memory_error->Row));
133 }
134 if (isvalid_prop_to_ir(&ui64Type, 9)) {
135 json_object_object_add(
136 section_ir, "column",
137 json_object_new_uint64(memory_error->Column));
138 }
139 if (isvalid_prop_to_ir(&ui64Type, 10)) {
140 json_object_object_add(
141 section_ir, "bitPosition",
142 json_object_new_uint64(memory_error->BitPosition));
143 }
144 if (isvalid_prop_to_ir(&ui64Type, 11)) {
145 json_object_object_add(
146 section_ir, "requestorID",
147 json_object_new_uint64(memory_error->RequestorId));
148 }
149 if (isvalid_prop_to_ir(&ui64Type, 12)) {
150 json_object_object_add(
151 section_ir, "responderID",
152 json_object_new_uint64(memory_error->ResponderId));
153 }
154 if (isvalid_prop_to_ir(&ui64Type, 13)) {
155 json_object_object_add(
156 section_ir, "targetID",
157 json_object_new_uint64(memory_error->TargetId));
158 }
159 if (isvalid_prop_to_ir(&ui64Type, 15)) {
160 json_object_object_add(
161 section_ir, "rankNumber",
162 json_object_new_uint64(memory_error->RankNum));
163 }
164
165 return section_ir;
166 }
167
168 //Converts a single memory error 2 CPER section into JSON IR.
cper_section_platform_memory2_to_ir(void * section)169 json_object *cper_section_platform_memory2_to_ir(void *section)
170 {
171 EFI_PLATFORM_MEMORY2_ERROR_DATA *memory_error =
172 (EFI_PLATFORM_MEMORY2_ERROR_DATA *)section;
173 json_object *section_ir = json_object_new_object();
174
175 ValidationTypes ui64Type = { UINT_64T,
176 .value.ui64 = memory_error->ValidFields };
177
178 //Error status.
179 if (isvalid_prop_to_ir(&ui64Type, 0)) {
180 json_object *error_status = cper_generic_error_status_to_ir(
181 &memory_error->ErrorStatus);
182 json_object_object_add(section_ir, "errorStatus", error_status);
183 }
184
185 //Bank.
186 json_object *bank = json_object_new_object();
187 if (isvalid_prop_to_ir(&ui64Type, 6)) {
188 //Entire bank address mode.
189 json_object_object_add(
190 bank, "value",
191 json_object_new_uint64(memory_error->Bank));
192 } else {
193 //Address/group address mode.
194 json_object_object_add(
195 bank, "address",
196 json_object_new_uint64(memory_error->Bank & 0xFF));
197 json_object_object_add(
198 bank, "group",
199 json_object_new_uint64(memory_error->Bank >> 8));
200 }
201 json_object_object_add(section_ir, "bank", bank);
202
203 //Memory error type.
204 if (isvalid_prop_to_ir(&ui64Type, 13)) {
205 json_object *memory_error_type = integer_to_readable_pair(
206 memory_error->MemErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
207 MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
208 json_object_object_add(section_ir, "memoryErrorType",
209 memory_error_type);
210 }
211
212 //Status.
213 if (isvalid_prop_to_ir(&ui64Type, 14)) {
214 json_object *status = json_object_new_object();
215 json_object_object_add(
216 status, "value",
217 json_object_new_int(memory_error->Status));
218 json_object_object_add(
219 status, "state",
220 json_object_new_string((memory_error->Status & 0x1) ==
221 0 ?
222 "Corrected" :
223 "Uncorrected"));
224 json_object_object_add(section_ir, "status", status);
225 }
226
227 //Miscellaneous numeric fields.
228 if (isvalid_prop_to_ir(&ui64Type, 0)) {
229 json_object_object_add(
230 section_ir, "physicalAddress",
231 json_object_new_uint64(memory_error->PhysicalAddress));
232 }
233
234 char hexstring_buf[EFI_UINT64_HEX_STRING_LEN];
235 snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX",
236 memory_error->PhysicalAddress);
237 json_object_object_add(section_ir, "physicalAddressHex",
238 json_object_new_string(hexstring_buf));
239
240 if (isvalid_prop_to_ir(&ui64Type, 2)) {
241 json_object_object_add(
242 section_ir, "physicalAddressMask",
243 json_object_new_uint64(
244 memory_error->PhysicalAddressMask));
245 }
246 if (isvalid_prop_to_ir(&ui64Type, 3)) {
247 json_object_object_add(
248 section_ir, "node",
249 json_object_new_uint64(memory_error->Node));
250 }
251 if (isvalid_prop_to_ir(&ui64Type, 4)) {
252 json_object_object_add(
253 section_ir, "card",
254 json_object_new_uint64(memory_error->Card));
255 }
256 if (isvalid_prop_to_ir(&ui64Type, 5)) {
257 json_object_object_add(
258 section_ir, "module",
259 json_object_new_uint64(memory_error->Module));
260 }
261 if (isvalid_prop_to_ir(&ui64Type, 7)) {
262 json_object_object_add(
263 section_ir, "device",
264 json_object_new_uint64(memory_error->Device));
265 }
266 if (isvalid_prop_to_ir(&ui64Type, 8)) {
267 json_object_object_add(
268 section_ir, "row",
269 json_object_new_uint64(memory_error->Row));
270 }
271 if (isvalid_prop_to_ir(&ui64Type, 9)) {
272 json_object_object_add(
273 section_ir, "column",
274 json_object_new_uint64(memory_error->Column));
275 }
276 if (isvalid_prop_to_ir(&ui64Type, 10)) {
277 json_object_object_add(
278 section_ir, "rank",
279 json_object_new_uint64(memory_error->Rank));
280 }
281 if (isvalid_prop_to_ir(&ui64Type, 11)) {
282 json_object_object_add(
283 section_ir, "bitPosition",
284 json_object_new_uint64(memory_error->BitPosition));
285 }
286 if (isvalid_prop_to_ir(&ui64Type, 12)) {
287 json_object_object_add(
288 section_ir, "chipID",
289 json_object_new_uint64(memory_error->ChipId));
290 }
291 if (isvalid_prop_to_ir(&ui64Type, 15)) {
292 json_object_object_add(
293 section_ir, "requestorID",
294 json_object_new_uint64(memory_error->RequestorId));
295 }
296 if (isvalid_prop_to_ir(&ui64Type, 16)) {
297 json_object_object_add(
298 section_ir, "responderID",
299 json_object_new_uint64(memory_error->ResponderId));
300 }
301 if (isvalid_prop_to_ir(&ui64Type, 17)) {
302 json_object_object_add(
303 section_ir, "targetID",
304 json_object_new_uint64(memory_error->TargetId));
305 }
306 if (isvalid_prop_to_ir(&ui64Type, 18)) {
307 json_object_object_add(
308 section_ir, "cardSmbiosHandle",
309 json_object_new_uint64(memory_error->CardHandle));
310 }
311 if (isvalid_prop_to_ir(&ui64Type, 19)) {
312 json_object_object_add(
313 section_ir, "moduleSmbiosHandle",
314 json_object_new_uint64(memory_error->ModuleHandle));
315 }
316
317 return section_ir;
318 }
319
320 //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)321 void ir_section_memory_to_cper(json_object *section, FILE *out)
322 {
323 EFI_PLATFORM_MEMORY_ERROR_DATA *section_cper =
324 (EFI_PLATFORM_MEMORY_ERROR_DATA *)calloc(
325 1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA));
326
327 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
328 struct json_object *obj = NULL;
329
330 //Error status.
331 if (json_object_object_get_ex(section, "errorStatus", &obj)) {
332 ir_generic_error_status_to_cper(obj,
333 §ion_cper->ErrorStatus);
334 add_to_valid_bitfield(&ui64Type, 0);
335 }
336
337 //Bank.
338 if (json_object_object_get_ex(section, "bank", &obj)) {
339 json_object *bank = obj;
340 if (json_object_object_get_ex(bank, "value", &obj)) {
341 //Bank just uses simple address.
342 section_cper->Bank =
343 (UINT16)json_object_get_uint64(obj);
344 add_to_valid_bitfield(&ui64Type, 6);
345 } else {
346 //Bank uses address/group style address.
347 UINT16 address = (UINT8)json_object_get_uint64(
348 json_object_object_get(bank, "address"));
349 UINT16 group = (UINT8)json_object_get_uint64(
350 json_object_object_get(bank, "group"));
351 section_cper->Bank = address + (group << 8);
352 add_to_valid_bitfield(&ui64Type, 19);
353 add_to_valid_bitfield(&ui64Type, 20);
354 }
355 }
356
357 //"Extended" field.
358 if (json_object_object_get_ex(section, "extended", &obj)) {
359 json_object *extended = obj;
360 section_cper->Extended = 0;
361 section_cper->Extended |= json_object_get_boolean(
362 json_object_object_get(extended, "rowBit16"));
363 section_cper->Extended |=
364 json_object_get_boolean(
365 json_object_object_get(extended, "rowBit17"))
366 << 1;
367 if (json_object_object_get_ex(extended, "chipIdentification",
368 &obj)) {
369 section_cper->Extended |= json_object_get_int(obj) << 5;
370 add_to_valid_bitfield(&ui64Type, 21);
371 }
372 add_to_valid_bitfield(&ui64Type, 18);
373 }
374
375 //Miscellaneous value fields.
376 if (json_object_object_get_ex(section, "memoryErrorType", &obj)) {
377 section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj);
378 add_to_valid_bitfield(&ui64Type, 14);
379 }
380 if (json_object_object_get_ex(section, "physicalAddress", &obj)) {
381 section_cper->PhysicalAddress = json_object_get_uint64(obj);
382 add_to_valid_bitfield(&ui64Type, 1);
383 }
384 if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) {
385 section_cper->PhysicalAddressMask = json_object_get_uint64(obj);
386 add_to_valid_bitfield(&ui64Type, 2);
387 }
388 if (json_object_object_get_ex(section, "node", &obj)) {
389 section_cper->Node = (UINT16)json_object_get_uint64(obj);
390 add_to_valid_bitfield(&ui64Type, 3);
391 }
392 if (json_object_object_get_ex(section, "card", &obj)) {
393 section_cper->Card = (UINT16)json_object_get_uint64(obj);
394 add_to_valid_bitfield(&ui64Type, 4);
395 }
396 if (json_object_object_get_ex(section, "moduleRank", &obj)) {
397 section_cper->ModuleRank = (UINT16)json_object_get_uint64(obj);
398 add_to_valid_bitfield(&ui64Type, 5);
399 }
400 if (json_object_object_get_ex(section, "device", &obj)) {
401 section_cper->Device = (UINT16)json_object_get_uint64(obj);
402 add_to_valid_bitfield(&ui64Type, 7);
403 }
404 if (json_object_object_get_ex(section, "row", &obj)) {
405 section_cper->Row = (UINT16)json_object_get_uint64(obj);
406 add_to_valid_bitfield(&ui64Type, 8);
407 }
408 if (json_object_object_get_ex(section, "column", &obj)) {
409 section_cper->Column = (UINT16)json_object_get_uint64(obj);
410 add_to_valid_bitfield(&ui64Type, 9);
411 }
412 if (json_object_object_get_ex(section, "bitPosition", &obj)) {
413 section_cper->BitPosition = (UINT16)json_object_get_uint64(obj);
414 add_to_valid_bitfield(&ui64Type, 10);
415 }
416 if (json_object_object_get_ex(section, "requestorID", &obj)) {
417 section_cper->RequestorId = json_object_get_uint64(obj);
418 add_to_valid_bitfield(&ui64Type, 11);
419 }
420 if (json_object_object_get_ex(section, "responderID", &obj)) {
421 section_cper->ResponderId = json_object_get_uint64(obj);
422 add_to_valid_bitfield(&ui64Type, 12);
423 }
424 if (json_object_object_get_ex(section, "targetID", &obj)) {
425 section_cper->TargetId = json_object_get_uint64(obj);
426 add_to_valid_bitfield(&ui64Type, 13);
427 }
428 if (json_object_object_get_ex(section, "rankNumber", &obj)) {
429 section_cper->RankNum = (UINT16)json_object_get_uint64(
430 json_object_object_get(section, "rankNumber"));
431 add_to_valid_bitfield(&ui64Type, 15);
432 }
433 if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) {
434 section_cper->CardHandle = (UINT16)json_object_get_uint64(obj);
435 add_to_valid_bitfield(&ui64Type, 16);
436 }
437 if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) {
438 section_cper->ModuleHandle =
439 (UINT16)json_object_get_uint64(obj);
440 add_to_valid_bitfield(&ui64Type, 17);
441 }
442 section_cper->ValidFields = ui64Type.value.ui64;
443
444 //Write to stream, free up resources.
445 fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA), 1, out);
446 fflush(out);
447 free(section_cper);
448 }
449
450 //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)451 void ir_section_memory2_to_cper(json_object *section, FILE *out)
452 {
453 EFI_PLATFORM_MEMORY2_ERROR_DATA *section_cper =
454 (EFI_PLATFORM_MEMORY2_ERROR_DATA *)calloc(
455 1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA));
456
457 //Validation bits.
458 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
459 struct json_object *obj = NULL;
460
461 //Error status.
462 if (json_object_object_get_ex(section, "errorStatus", &obj)) {
463 ir_generic_error_status_to_cper(obj,
464 §ion_cper->ErrorStatus);
465 add_to_valid_bitfield(&ui64Type, 0);
466 }
467
468 //Bank.
469 json_object *bank = json_object_object_get(section, "bank");
470 if (json_object_object_get_ex(bank, "value", &obj)) {
471 //Bank just uses simple address.
472 section_cper->Bank = (UINT16)json_object_get_uint64(obj);
473 add_to_valid_bitfield(&ui64Type, 6);
474 } else {
475 //Bank uses address/group style address.
476 UINT16 address = (UINT8)json_object_get_uint64(
477 json_object_object_get(bank, "address"));
478 UINT16 group = (UINT8)json_object_get_uint64(
479 json_object_object_get(bank, "group"));
480 section_cper->Bank = address + (group << 8);
481 add_to_valid_bitfield(&ui64Type, 20);
482 add_to_valid_bitfield(&ui64Type, 21);
483 }
484
485 //Miscellaneous value fields.
486 if (json_object_object_get_ex(section, "memoryErrorType", &obj)) {
487 section_cper->MemErrorType = readable_pair_to_integer(obj);
488 add_to_valid_bitfield(&ui64Type, 13);
489 }
490 if (json_object_object_get_ex(section, "status", &obj)) {
491 section_cper->Status = (UINT8)readable_pair_to_integer(obj);
492 add_to_valid_bitfield(&ui64Type, 14);
493 }
494 if (json_object_object_get_ex(section, "physicalAddress", &obj)) {
495 section_cper->PhysicalAddress = json_object_get_uint64(obj);
496 add_to_valid_bitfield(&ui64Type, 1);
497 }
498 if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) {
499 section_cper->PhysicalAddressMask = json_object_get_uint64(obj);
500 add_to_valid_bitfield(&ui64Type, 2);
501 }
502 if (json_object_object_get_ex(section, "node", &obj)) {
503 section_cper->Node = (UINT16)json_object_get_uint64(obj);
504 add_to_valid_bitfield(&ui64Type, 3);
505 }
506 if (json_object_object_get_ex(section, "card", &obj)) {
507 section_cper->Card = (UINT16)json_object_get_uint64(obj);
508 add_to_valid_bitfield(&ui64Type, 4);
509 }
510 if (json_object_object_get_ex(section, "module", &obj)) {
511 section_cper->Module = (UINT32)json_object_get_uint64(obj);
512 add_to_valid_bitfield(&ui64Type, 5);
513 }
514 if (json_object_object_get_ex(section, "device", &obj)) {
515 section_cper->Device = (UINT32)json_object_get_uint64(obj);
516 add_to_valid_bitfield(&ui64Type, 7);
517 }
518 if (json_object_object_get_ex(section, "row", &obj)) {
519 section_cper->Row = (UINT32)json_object_get_uint64(obj);
520 add_to_valid_bitfield(&ui64Type, 8);
521 }
522 if (json_object_object_get_ex(section, "column", &obj)) {
523 section_cper->Column = (UINT32)json_object_get_uint64(obj);
524 add_to_valid_bitfield(&ui64Type, 9);
525 }
526 if (json_object_object_get_ex(section, "rank", &obj)) {
527 section_cper->Rank = (UINT32)json_object_get_uint64(obj);
528 add_to_valid_bitfield(&ui64Type, 10);
529 }
530 if (json_object_object_get_ex(section, "bitPosition", &obj)) {
531 section_cper->BitPosition = (UINT32)json_object_get_uint64(obj);
532 add_to_valid_bitfield(&ui64Type, 11);
533 }
534 if (json_object_object_get_ex(section, "chipID", &obj)) {
535 section_cper->ChipId = (UINT8)json_object_get_uint64(obj);
536 add_to_valid_bitfield(&ui64Type, 12);
537 }
538 if (json_object_object_get_ex(section, "requestorID", &obj)) {
539 section_cper->RequestorId = json_object_get_uint64(obj);
540 add_to_valid_bitfield(&ui64Type, 15);
541 }
542 if (json_object_object_get_ex(section, "responderID", &obj)) {
543 section_cper->ResponderId = json_object_get_uint64(obj);
544 add_to_valid_bitfield(&ui64Type, 16);
545 }
546 if (json_object_object_get_ex(section, "targetID", &obj)) {
547 section_cper->TargetId = json_object_get_uint64(obj);
548 add_to_valid_bitfield(&ui64Type, 17);
549 }
550 if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) {
551 section_cper->CardHandle = (UINT32)json_object_get_uint64(obj);
552 add_to_valid_bitfield(&ui64Type, 18);
553 }
554 if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) {
555 section_cper->ModuleHandle =
556 (UINT32)json_object_get_uint64(obj);
557 add_to_valid_bitfield(&ui64Type, 19);
558 }
559
560 section_cper->ValidFields = ui64Type.value.ui64;
561
562 //Write to stream, free up resources.
563 fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out);
564 fflush(out);
565 free(section_cper);
566 }
567