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