xref: /openbmc/libcper/sections/cper-section-nvidia.c (revision a3663051b36d33dc4b102109666ee31b0c23582f)
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.
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 
24 	json_object *section_ir = json_object_new_object();
25 
26 	add_untrusted_string(section_ir, "signature", nvidia_error->Signature,
27 			     sizeof(nvidia_error->Signature));
28 
29 	json_object *severity = json_object_new_object();
30 	json_object_object_add(severity, "code",
31 			       json_object_new_uint64(nvidia_error->Severity));
32 	json_object_object_add(severity, "name",
33 			       json_object_new_string(severity_to_string(
34 				       nvidia_error->Severity)));
35 	json_object_object_add(section_ir, "severity", severity);
36 
37 	json_object_object_add(section_ir, "errorType",
38 			       json_object_new_int(nvidia_error->ErrorType));
39 	json_object_object_add(
40 		section_ir, "errorInstance",
41 		json_object_new_int(nvidia_error->ErrorInstance));
42 	json_object_object_add(section_ir, "socket",
43 			       json_object_new_int(nvidia_error->Socket));
44 	json_object_object_add(section_ir, "registerCount",
45 			       json_object_new_int(nvidia_error->NumberRegs));
46 	json_object_object_add(
47 		section_ir, "instanceBase",
48 		json_object_new_uint64(nvidia_error->InstanceBase));
49 
50 	// Registers (Address Value pairs).
51 	json_object *regarr = json_object_new_array();
52 	EFI_NVIDIA_REGISTER_DATA *regPtr = nvidia_error->Register;
53 	for (int i = 0; i < nvidia_error->NumberRegs; i++, regPtr++) {
54 		json_object *reg = NULL;
55 		if (sizeof(EFI_NVIDIA_ERROR_DATA) +
56 			    i * sizeof(EFI_NVIDIA_REGISTER_DATA) <
57 		    size) {
58 			reg = json_object_new_object();
59 			json_object_object_add(
60 				reg, "address",
61 				json_object_new_uint64(regPtr->Address));
62 			json_object_object_add(
63 				reg, "value",
64 				json_object_new_uint64(regPtr->Value));
65 		} else {
66 			reg = json_object_new_null();
67 		}
68 
69 		json_object_array_add(regarr, reg);
70 	}
71 	json_object_object_add(section_ir, "registers", regarr);
72 
73 	return section_ir;
74 }
75 
76 //Converts a single NVIDIA CPER-JSON section into CPER binary, outputting to the given stream.
77 void ir_section_nvidia_to_cper(json_object *section, FILE *out)
78 {
79 	json_object *regarr = json_object_object_get(section, "registers");
80 	int numRegs = json_object_array_length(regarr);
81 
82 	size_t section_sz = offsetof(EFI_NVIDIA_ERROR_DATA, Register) +
83 			    numRegs * sizeof(EFI_NVIDIA_REGISTER_DATA);
84 	EFI_NVIDIA_ERROR_DATA *section_cper =
85 		(EFI_NVIDIA_ERROR_DATA *)calloc(1, section_sz);
86 
87 	//Signature.
88 	strncpy(section_cper->Signature,
89 		json_object_get_string(
90 			json_object_object_get(section, "signature")),
91 		sizeof(section_cper->Signature) - 1);
92 	section_cper->Signature[sizeof(section_cper->Signature) - 1] = '\0';
93 
94 	//Fields.
95 	section_cper->ErrorType = json_object_get_int(
96 		json_object_object_get(section, "errorType"));
97 	section_cper->ErrorInstance = json_object_get_int(
98 		json_object_object_get(section, "errorInstance"));
99 	json_object *severity = json_object_object_get(section, "severity");
100 	section_cper->Severity = (UINT8)json_object_get_uint64(
101 		json_object_object_get(severity, "code"));
102 	section_cper->Socket =
103 		json_object_get_int(json_object_object_get(section, "socket"));
104 	section_cper->NumberRegs = json_object_get_int(
105 		json_object_object_get(section, "registerCount"));
106 	section_cper->InstanceBase = json_object_get_uint64(
107 		json_object_object_get(section, "instanceBase"));
108 
109 	// Registers (Address Value pairs).
110 	EFI_NVIDIA_REGISTER_DATA *regPtr = section_cper->Register;
111 	for (int i = 0; i < numRegs; i++, regPtr++) {
112 		json_object *reg = json_object_array_get_idx(regarr, i);
113 		regPtr->Address = json_object_get_uint64(
114 			json_object_object_get(reg, "address"));
115 		regPtr->Value = json_object_get_uint64(
116 			json_object_object_get(reg, "value"));
117 	}
118 
119 	//Write to stream, free resources.
120 	fwrite(section_cper, section_sz, 1, out);
121 	fflush(out);
122 	free(section_cper);
123 }
124