xref: /openbmc/libcper/sections/cper-section-generic.c (revision ae8f6d9aaeaf37332e8924dd2c0b6f320335548c)
1 /**
2  * Describes functions for converting processor-generic CPER sections from binary and JSON format
3  * into an intermediate format.
4  *
5  * Author: Lawrence.Tang@arm.com
6  **/
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <json.h>
11 #include <libcper/Cper.h>
12 #include <libcper/cper-utils.h>
13 #include <libcper/sections/cper-section-generic.h>
14 
15 //Converts the given processor-generic CPER section into JSON IR.
cper_section_generic_to_ir(void * section)16 json_object *cper_section_generic_to_ir(void *section)
17 {
18 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic =
19 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)section;
20 	json_object *section_ir = json_object_new_object();
21 
22 	ValidationTypes ui64Type = {
23 		UINT_64T, .value.ui64 = section_generic->ValidFields
24 	};
25 
26 	if (isvalid_prop_to_ir(&ui64Type, 0)) {
27 		//Processor type, with human readable name if possible.
28 		json_object *processor_type = integer_to_readable_pair(
29 			section_generic->Type,
30 			sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int),
31 			GENERIC_PROC_TYPES_KEYS, GENERIC_PROC_TYPES_VALUES,
32 			"Unknown (Reserved)");
33 		json_object_object_add(section_ir, "processorType",
34 				       processor_type);
35 	}
36 
37 	if (isvalid_prop_to_ir(&ui64Type, 1)) {
38 		//Processor ISA, with human readable name if possible.
39 		json_object *processor_isa = integer_to_readable_pair(
40 			section_generic->Isa,
41 			sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int),
42 			GENERIC_ISA_TYPES_KEYS, GENERIC_ISA_TYPES_VALUES,
43 			"Unknown (Reserved)");
44 		json_object_object_add(section_ir, "processorISA",
45 				       processor_isa);
46 	}
47 
48 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
49 		//Processor error type, with human readable name if possible.
50 		json_object *processor_error_type = integer_to_readable_pair(
51 			section_generic->ErrorType,
52 			sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int),
53 			GENERIC_ERROR_TYPES_KEYS, GENERIC_ERROR_TYPES_VALUES,
54 			"Unknown (Reserved)");
55 		json_object_object_add(section_ir, "errorType",
56 				       processor_error_type);
57 	}
58 
59 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
60 		//The operation performed, with a human readable name if possible.
61 		json_object *operation = integer_to_readable_pair(
62 			section_generic->Operation,
63 			sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int),
64 			GENERIC_OPERATION_TYPES_KEYS,
65 			GENERIC_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
66 		json_object_object_add(section_ir, "operation", operation);
67 	}
68 
69 	if (isvalid_prop_to_ir(&ui64Type, 4)) {
70 		//Flags, additional information about the error.
71 		json_object *flags =
72 			bitfield_to_ir(section_generic->Flags, 4,
73 				       GENERIC_FLAGS_BITFIELD_NAMES);
74 		json_object_object_add(section_ir, "flags", flags);
75 	}
76 
77 	if (isvalid_prop_to_ir(&ui64Type, 5)) {
78 		//The level of the error.
79 		json_object_object_add(
80 			section_ir, "level",
81 			json_object_new_int(section_generic->Level));
82 	}
83 
84 	if (isvalid_prop_to_ir(&ui64Type, 6)) {
85 		//CPU version information.
86 		json_object_object_add(
87 			section_ir, "cpuVersionInfo",
88 			json_object_new_uint64(section_generic->VersionInfo));
89 	}
90 
91 	if (isvalid_prop_to_ir(&ui64Type, 7)) {
92 		//CPU brand string. May not exist if on ARM.
93 		json_object_object_add(
94 			section_ir, "cpuBrandString",
95 			json_object_new_string(section_generic->BrandString));
96 	}
97 
98 	if (isvalid_prop_to_ir(&ui64Type, 8)) {
99 		//Remaining 64-bit fields.
100 		json_object_object_add(
101 			section_ir, "processorID",
102 			json_object_new_uint64(section_generic->ApicId));
103 	}
104 
105 	if (isvalid_prop_to_ir(&ui64Type, 9)) {
106 		json_object_object_add(
107 			section_ir, "targetAddress",
108 			json_object_new_uint64(section_generic->TargetAddr));
109 	}
110 
111 	if (isvalid_prop_to_ir(&ui64Type, 10)) {
112 		json_object_object_add(
113 			section_ir, "requestorID",
114 			json_object_new_uint64(section_generic->RequestorId));
115 	}
116 
117 	if (isvalid_prop_to_ir(&ui64Type, 11)) {
118 		json_object_object_add(
119 			section_ir, "responderID",
120 			json_object_new_uint64(section_generic->ResponderId));
121 	}
122 
123 	if (isvalid_prop_to_ir(&ui64Type, 12)) {
124 		json_object_object_add(
125 			section_ir, "instructionIP",
126 			json_object_new_uint64(section_generic->InstructionIP));
127 	}
128 
129 	return section_ir;
130 }
131 
132 //Converts the given CPER-JSON processor-generic error section into CPER binary,
133 //outputting to the provided stream.
ir_section_generic_to_cper(json_object * section,FILE * out)134 void ir_section_generic_to_cper(json_object *section, FILE *out)
135 {
136 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_cper =
137 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc(
138 			1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA));
139 
140 	//Validation bits.
141 	//Remove
142 	// section_cper->ValidFields = ir_to_bitfield(
143 	// 	json_object_object_get(section, "validationBits"), 13,
144 	// 	GENERIC_VALIDATION_BITFIELD_NAMES);
145 	ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
146 	struct json_object *obj = NULL;
147 	//Various name/value pair fields.
148 	if (json_object_object_get_ex(section, "processorType", &obj)) {
149 		section_cper->Type = (UINT8)readable_pair_to_integer(obj);
150 		add_to_valid_bitfield(&ui64Type, 0);
151 	}
152 	if (json_object_object_get_ex(section, "processorISA", &obj)) {
153 		section_cper->Isa = (UINT8)readable_pair_to_integer(obj);
154 		add_to_valid_bitfield(&ui64Type, 1);
155 	}
156 	if (json_object_object_get_ex(section, "errorType", &obj)) {
157 		section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj);
158 		add_to_valid_bitfield(&ui64Type, 2);
159 	}
160 	if (json_object_object_get_ex(section, "operation", &obj)) {
161 		section_cper->Operation = (UINT8)readable_pair_to_integer(obj);
162 		add_to_valid_bitfield(&ui64Type, 3);
163 	}
164 	//Flags.
165 	if (json_object_object_get_ex(section, "flags", &obj)) {
166 		section_cper->Flags = (UINT8)ir_to_bitfield(
167 			obj, 4, GENERIC_FLAGS_BITFIELD_NAMES);
168 		add_to_valid_bitfield(&ui64Type, 4);
169 	}
170 
171 	//Various numeric/string fields.
172 	if (json_object_object_get_ex(section, "level", &obj)) {
173 		section_cper->Level = (UINT8)json_object_get_int(obj);
174 		add_to_valid_bitfield(&ui64Type, 5);
175 	}
176 	if (json_object_object_get_ex(section, "cpuVersionInfo", &obj)) {
177 		section_cper->VersionInfo = json_object_get_uint64(obj);
178 		add_to_valid_bitfield(&ui64Type, 6);
179 	}
180 	if (json_object_object_get_ex(section, "processorID", &obj)) {
181 		section_cper->ApicId = json_object_get_uint64(obj);
182 		add_to_valid_bitfield(&ui64Type, 8);
183 	}
184 	if (json_object_object_get_ex(section, "targetAddress", &obj)) {
185 		section_cper->TargetAddr = json_object_get_uint64(obj);
186 		add_to_valid_bitfield(&ui64Type, 9);
187 	}
188 	if (json_object_object_get_ex(section, "requestorID", &obj)) {
189 		section_cper->RequestorId = json_object_get_uint64(obj);
190 		add_to_valid_bitfield(&ui64Type, 10);
191 	}
192 	if (json_object_object_get_ex(section, "responderID", &obj)) {
193 		section_cper->ResponderId = json_object_get_uint64(obj);
194 		add_to_valid_bitfield(&ui64Type, 11);
195 	}
196 	if (json_object_object_get_ex(section, "instructionIP", &obj)) {
197 		section_cper->InstructionIP = json_object_get_uint64(obj);
198 		add_to_valid_bitfield(&ui64Type, 12);
199 	}
200 
201 	//CPU brand string.
202 	if (json_object_object_get_ex(section, "cpuBrandString", &obj)) {
203 		const char *brand_string = json_object_get_string(obj);
204 		if (brand_string != NULL) {
205 			strncpy(section_cper->BrandString, brand_string,
206 				sizeof(section_cper->BrandString) - 1);
207 			section_cper
208 				->BrandString[sizeof(section_cper->BrandString) -
209 					      1] = '\0';
210 		}
211 		add_to_valid_bitfield(&ui64Type, 7);
212 	}
213 	section_cper->ValidFields = ui64Type.value.ui64;
214 
215 	//Write & flush out to file, free memory.
216 	fwrite(section_cper, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA), 1, out);
217 	fflush(out);
218 	free(section_cper);
219 }
220