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