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