xref: /openbmc/libcper/sections/cper-section-nvidia.c (revision 50b966f7afa31fe39fda70e10eb9139cce39e025)
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