1 /**
2 * Describes functions for converting NVIDIA CPER sections from binary and JSON format
3 * into an intermediate format.
4 **/
5
6 #include <stdio.h>
7 #include <stddef.h>
8 #include <string.h>
9 #include <json.h>
10 #include <libcper/Cper.h>
11 #include <libcper/cper-utils.h>
12 #include <libcper/sections/cper-section-nvidia.h>
13 #include <libcper/log.h>
14
15 //Converts a single NVIDIA CPER section into JSON IR.
cper_section_nvidia_to_ir(const UINT8 * section,UINT32 size)16 json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size)
17 {
18 if (size < sizeof(EFI_NVIDIA_ERROR_DATA)) {
19 return NULL;
20 }
21
22 EFI_NVIDIA_ERROR_DATA *nvidia_error = (EFI_NVIDIA_ERROR_DATA *)section;
23 if (size < sizeof(EFI_NVIDIA_ERROR_DATA) +
24 nvidia_error->NumberRegs *
25 sizeof(EFI_NVIDIA_REGISTER_DATA)) {
26 return NULL;
27 }
28
29 json_object *section_ir = json_object_new_object();
30
31 add_untrusted_string(section_ir, "signature", nvidia_error->Signature,
32 sizeof(nvidia_error->Signature));
33
34 json_object *severity = json_object_new_object();
35 json_object_object_add(severity, "code",
36 json_object_new_uint64(nvidia_error->Severity));
37 json_object_object_add(severity, "name",
38 json_object_new_string(severity_to_string(
39 nvidia_error->Severity)));
40 json_object_object_add(section_ir, "severity", severity);
41
42 json_object_object_add(section_ir, "errorType",
43 json_object_new_int(nvidia_error->ErrorType));
44 json_object_object_add(
45 section_ir, "errorInstance",
46 json_object_new_int(nvidia_error->ErrorInstance));
47 json_object_object_add(section_ir, "socket",
48 json_object_new_int(nvidia_error->Socket));
49 json_object_object_add(section_ir, "registerCount",
50 json_object_new_int(nvidia_error->NumberRegs));
51 json_object_object_add(
52 section_ir, "instanceBase",
53 json_object_new_uint64(nvidia_error->InstanceBase));
54
55 // Registers (Address Value pairs).
56 json_object *regarr = json_object_new_array();
57 EFI_NVIDIA_REGISTER_DATA *regPtr = nvidia_error->Register;
58 for (int i = 0; i < nvidia_error->NumberRegs; i++, regPtr++) {
59 json_object *reg = json_object_new_object();
60 json_object_object_add(reg, "address",
61 json_object_new_uint64(regPtr->Address));
62 json_object_object_add(reg, "value",
63 json_object_new_uint64(regPtr->Value));
64 json_object_array_add(regarr, reg);
65 }
66 json_object_object_add(section_ir, "registers", regarr);
67
68 return section_ir;
69 }
70
71 //Converts a single NVIDIA CPER-JSON section into CPER binary, outputting to the given stream.
ir_section_nvidia_to_cper(json_object * section,FILE * out)72 void ir_section_nvidia_to_cper(json_object *section, FILE *out)
73 {
74 json_object *regarr = json_object_object_get(section, "registers");
75 int numRegs = json_object_array_length(regarr);
76
77 size_t section_sz = offsetof(EFI_NVIDIA_ERROR_DATA, Register) +
78 numRegs * sizeof(EFI_NVIDIA_REGISTER_DATA);
79 EFI_NVIDIA_ERROR_DATA *section_cper =
80 (EFI_NVIDIA_ERROR_DATA *)calloc(1, section_sz);
81
82 //Signature.
83 strncpy(section_cper->Signature,
84 json_object_get_string(
85 json_object_object_get(section, "signature")),
86 sizeof(section_cper->Signature) - 1);
87 section_cper->Signature[sizeof(section_cper->Signature) - 1] = '\0';
88
89 //Fields.
90 section_cper->ErrorType = json_object_get_int(
91 json_object_object_get(section, "errorType"));
92 section_cper->ErrorInstance = json_object_get_int(
93 json_object_object_get(section, "errorInstance"));
94 json_object *severity = json_object_object_get(section, "severity");
95 section_cper->Severity = (UINT8)json_object_get_uint64(
96 json_object_object_get(severity, "code"));
97 section_cper->Socket =
98 json_object_get_int(json_object_object_get(section, "socket"));
99 section_cper->NumberRegs = json_object_get_int(
100 json_object_object_get(section, "registerCount"));
101 section_cper->InstanceBase = json_object_get_uint64(
102 json_object_object_get(section, "instanceBase"));
103
104 // Registers (Address Value pairs).
105 EFI_NVIDIA_REGISTER_DATA *regPtr = section_cper->Register;
106 for (int i = 0; i < numRegs; i++, regPtr++) {
107 json_object *reg = json_object_array_get_idx(regarr, i);
108 regPtr->Address = json_object_get_uint64(
109 json_object_object_get(reg, "address"));
110 regPtr->Value = json_object_get_uint64(
111 json_object_object_get(reg, "value"));
112 }
113
114 //Write to stream, free resources.
115 fwrite(section_cper, section_sz, 1, out);
116 fflush(out);
117 free(section_cper);
118 }
119