blob: b6333963e1133c0a1bf482870939866028fdcc14 [file] [log] [blame]
Karthik Rajagopalan683e0552024-03-07 12:30:43 -08001/**
2 * Describes functions for converting NVIDIA CPER sections from binary and JSON format
3 * into an intermediate format.
4 **/
5
6#include <stdio.h>
Ed Tanous2d17ace2024-08-27 14:45:38 -07007#include <stddef.h>
Karthik Rajagopalan683e0552024-03-07 12:30:43 -08008#include <string.h>
9#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000010#include <libcper/Cper.h>
11#include <libcper/cper-utils.h>
12#include <libcper/sections/cper-section-nvidia.h>
Ed Tanous50b966f2025-03-11 09:06:19 -070013#include <libcper/log.h>
Karthik Rajagopalan683e0552024-03-07 12:30:43 -080014
Ed Tanous55968b12025-05-06 21:04:52 -070015void parse_cmet_info(EFI_NVIDIA_REGISTER_DATA *regPtr, UINT8 NumberRegs,
16 size_t size, json_object *section_ir)
17{
18 json_object *regarr = json_object_new_array();
19 for (int i = 0; i < NumberRegs; i++, regPtr++) {
20 json_object *reg = NULL;
21 if (sizeof(EFI_NVIDIA_ERROR_DATA) +
22 i * sizeof(EFI_NVIDIA_REGISTER_DATA) <
23 size) {
24 reg = json_object_new_object();
25 add_int_hex_64(reg, "ChannelAddress", regPtr->Address);
26 add_int(reg, "ErrorCount", regPtr->CmetInfo.ErrorCount);
27 add_bool(reg, "ChannelEnabled",
28 regPtr->CmetInfo.ChannelEnabled);
29 add_bool(reg, "ChannelIsSpare",
30 regPtr->CmetInfo.ChannelIsSpare);
31 add_dict(reg, "DisabledReason",
32 regPtr->CmetInfo.DisabledReason,
33 channel_disable_reason_dict,
34 channel_disable_reason_dict_size);
35 } else {
36 reg = json_object_new_null();
37 }
38
39 json_object_array_add(regarr, reg);
40 }
41
42 json_object_object_add(section_ir, "CMETInfo", regarr);
43}
44
45void parse_fwerror(EFI_NVIDIA_REGISTER_DATA *regPtr, UINT8 NumberRegs,
46 size_t size, json_object *section_ir)
47{
48 (void)NumberRegs;
49 json_object *fwinfo;
50 if (sizeof(EFI_NVIDIA_ERROR_DATA) + sizeof(EFI_NVIDIA_FWERROR) > size) {
51 fwinfo = json_object_new_null();
52 } else {
53 fwinfo = json_object_new_object();
54 EFI_NVIDIA_FWERROR *fwerror = (EFI_NVIDIA_FWERROR *)regPtr;
55 add_untrusted_string(fwinfo, "initiating_firmware",
56 fwerror->initiating_firmware,
57 sizeof(fwerror->initiating_firmware));
58 add_int_hex_64(fwinfo, "task_checkpoint",
59 fwerror->task_checkpoint);
60 add_int_hex_64(fwinfo, "mb1_error_code",
61 fwerror->mb1_error_code);
62 add_untrusted_string(fwinfo, "mb1_version_string",
63 fwerror->mb1_version_string,
64 sizeof(fwerror->mb1_version_string));
65 add_int_hex_64(fwinfo, "bad_pages_retired_mask",
66 fwerror->bad_pages_retired_mask);
67 add_int_hex_64(fwinfo, "training_or_alias_check_retired_mask",
68 fwerror->training_or_alias_check_retired_mask);
69 }
70
71 json_object_object_add(section_ir, "FWErrorInfo", fwinfo);
72}
73
74void parse_registers(EFI_NVIDIA_REGISTER_DATA *regPtr, UINT8 NumberRegs,
75 size_t size, json_object *section_ir)
76{
77 // Registers (Address Value pairs).
78 json_object *regarr = json_object_new_array();
79 for (int i = 0; i < NumberRegs; i++, regPtr++) {
80 json_object *reg = NULL;
81 if (sizeof(EFI_NVIDIA_ERROR_DATA) +
82 i * sizeof(EFI_NVIDIA_REGISTER_DATA) <
83 size) {
84 reg = json_object_new_object();
85 json_object_object_add(
86 reg, "address",
87 json_object_new_uint64(regPtr->Address));
88 json_object_object_add(
89 reg, "value",
90 json_object_new_uint64(regPtr->Value));
91 } else {
92 reg = json_object_new_null();
93 }
94
95 json_object_array_add(regarr, reg);
96 }
97 json_object_object_add(section_ir, "registers", regarr);
98}
99
100typedef struct {
101 const char *ip_signature;
102 void (*callback)(EFI_NVIDIA_REGISTER_DATA *, UINT8, size_t,
103 json_object *);
104} NV_SECTION_CALLBACKS;
105
106NV_SECTION_CALLBACKS section_handlers[] = {
107 { "CMET-INFO\0", &parse_cmet_info },
108 { "FWERROR\0", &parse_fwerror },
109 { "", &parse_registers },
110};
111
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800112//Converts a single NVIDIA CPER section into JSON IR.
Ed Tanous12dbd4f2025-03-08 19:05:01 -0800113json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size)
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800114{
Ed Tanous12dbd4f2025-03-08 19:05:01 -0800115 if (size < sizeof(EFI_NVIDIA_ERROR_DATA)) {
116 return NULL;
117 }
118
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800119 EFI_NVIDIA_ERROR_DATA *nvidia_error = (EFI_NVIDIA_ERROR_DATA *)section;
Ed Tanous12dbd4f2025-03-08 19:05:01 -0800120
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800121 json_object *section_ir = json_object_new_object();
122
Ed Tanous5e2164a2025-03-09 09:20:44 -0700123 add_untrusted_string(section_ir, "signature", nvidia_error->Signature,
124 sizeof(nvidia_error->Signature));
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800125
Ed Tanous2d17ace2024-08-27 14:45:38 -0700126 json_object *severity = json_object_new_object();
127 json_object_object_add(severity, "code",
128 json_object_new_uint64(nvidia_error->Severity));
129 json_object_object_add(severity, "name",
130 json_object_new_string(severity_to_string(
131 nvidia_error->Severity)));
132 json_object_object_add(section_ir, "severity", severity);
133
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800134 json_object_object_add(section_ir, "errorType",
135 json_object_new_int(nvidia_error->ErrorType));
136 json_object_object_add(
137 section_ir, "errorInstance",
138 json_object_new_int(nvidia_error->ErrorInstance));
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800139 json_object_object_add(section_ir, "socket",
140 json_object_new_int(nvidia_error->Socket));
Ed Tanous2d17ace2024-08-27 14:45:38 -0700141 json_object_object_add(section_ir, "registerCount",
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800142 json_object_new_int(nvidia_error->NumberRegs));
143 json_object_object_add(
144 section_ir, "instanceBase",
145 json_object_new_uint64(nvidia_error->InstanceBase));
146
Ed Tanous55968b12025-05-06 21:04:52 -0700147 for (long unsigned int i = 0;
148 i < sizeof(section_handlers) / sizeof(section_handlers[0]); i++) {
149 const char *ip_signature = section_handlers[i].ip_signature;
150 if (strncmp(nvidia_error->Signature, ip_signature,
151 strlen(ip_signature)) == 0) {
152 section_handlers[i].callback(&nvidia_error->Register[0],
153 nvidia_error->NumberRegs,
154 size, section_ir);
155 break;
Ed Tanous1bc852a2025-04-09 15:33:12 -0700156 }
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800157 }
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800158 return section_ir;
159}
160
161//Converts a single NVIDIA CPER-JSON section into CPER binary, outputting to the given stream.
162void ir_section_nvidia_to_cper(json_object *section, FILE *out)
163{
164 json_object *regarr = json_object_object_get(section, "registers");
165 int numRegs = json_object_array_length(regarr);
166
Ed Tanous2d17ace2024-08-27 14:45:38 -0700167 size_t section_sz = offsetof(EFI_NVIDIA_ERROR_DATA, Register) +
168 numRegs * sizeof(EFI_NVIDIA_REGISTER_DATA);
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800169 EFI_NVIDIA_ERROR_DATA *section_cper =
170 (EFI_NVIDIA_ERROR_DATA *)calloc(1, section_sz);
171
172 //Signature.
173 strncpy(section_cper->Signature,
174 json_object_get_string(
175 json_object_object_get(section, "signature")),
Patrick Williams379e4922024-08-28 11:14:34 -0400176 sizeof(section_cper->Signature) - 1);
177 section_cper->Signature[sizeof(section_cper->Signature) - 1] = '\0';
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800178
179 //Fields.
180 section_cper->ErrorType = json_object_get_int(
181 json_object_object_get(section, "errorType"));
182 section_cper->ErrorInstance = json_object_get_int(
183 json_object_object_get(section, "errorInstance"));
Ed Tanous2d17ace2024-08-27 14:45:38 -0700184 json_object *severity = json_object_object_get(section, "severity");
185 section_cper->Severity = (UINT8)json_object_get_uint64(
186 json_object_object_get(severity, "code"));
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800187 section_cper->Socket =
188 json_object_get_int(json_object_object_get(section, "socket"));
189 section_cper->NumberRegs = json_object_get_int(
Ed Tanous2d17ace2024-08-27 14:45:38 -0700190 json_object_object_get(section, "registerCount"));
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800191 section_cper->InstanceBase = json_object_get_uint64(
192 json_object_object_get(section, "instanceBase"));
193
194 // Registers (Address Value pairs).
Ed Tanous2d17ace2024-08-27 14:45:38 -0700195 EFI_NVIDIA_REGISTER_DATA *regPtr = section_cper->Register;
196 for (int i = 0; i < numRegs; i++, regPtr++) {
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800197 json_object *reg = json_object_array_get_idx(regarr, i);
Ed Tanous2d17ace2024-08-27 14:45:38 -0700198 regPtr->Address = json_object_get_uint64(
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800199 json_object_object_get(reg, "address"));
Ed Tanous2d17ace2024-08-27 14:45:38 -0700200 regPtr->Value = json_object_get_uint64(
Karthik Rajagopalan683e0552024-03-07 12:30:43 -0800201 json_object_object_get(reg, "value"));
202 }
203
204 //Write to stream, free resources.
205 fwrite(section_cper, section_sz, 1, out);
206 fflush(out);
207 free(section_cper);
208}