1 /**
2  * Describes functions for converting memory error CPER sections from binary and JSON format
3  * into an intermediate format.
4  *
5  * Author: Lawrence.Tang@arm.com
6  **/
7 #include <stdio.h>
8 #include <json.h>
9 #include "../edk/Cper.h"
10 #include "../cper-utils.h"
11 #include "cper-section-memory.h"
12 
13 //Converts a single memory error CPER section into JSON IR.
14 json_object *
15 cper_section_platform_memory_to_ir(void *section,
16 				   EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
17 {
18 	EFI_PLATFORM_MEMORY_ERROR_DATA *memory_error =
19 		(EFI_PLATFORM_MEMORY_ERROR_DATA *)section;
20 	json_object *section_ir = json_object_new_object();
21 
22 	//Validation bitfield.
23 	json_object *validation =
24 		bitfield_to_ir(memory_error->ValidFields, 22,
25 			       MEMORY_ERROR_VALID_BITFIELD_NAMES);
26 	json_object_object_add(section_ir, "validationBits", validation);
27 
28 	//Error status.
29 	json_object *error_status =
30 		cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
31 	json_object_object_add(section_ir, "errorStatus", error_status);
32 
33 	//Bank.
34 	json_object *bank = json_object_new_object();
35 	if ((memory_error->ValidFields >> 5) & 0x1) {
36 		//Entire bank address mode.
37 		json_object_object_add(
38 			bank, "value",
39 			json_object_new_uint64(memory_error->Bank));
40 	} else {
41 		//Address/group address mode.
42 		json_object_object_add(
43 			bank, "address",
44 			json_object_new_uint64(memory_error->Bank & 0xFF));
45 		json_object_object_add(
46 			bank, "group",
47 			json_object_new_uint64(memory_error->Bank >> 8));
48 	}
49 	json_object_object_add(section_ir, "bank", bank);
50 
51 	//Memory error type.
52 	json_object *memory_error_type = integer_to_readable_pair(
53 		memory_error->ErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
54 		MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
55 	json_object_object_add(section_ir, "memoryErrorType",
56 			       memory_error_type);
57 
58 	//"Extended" row/column indication field + misc.
59 	json_object *extended = json_object_new_object();
60 	json_object_object_add(extended, "rowBit16",
61 			       json_object_new_boolean(memory_error->Extended &
62 						       0b1));
63 	json_object_object_add(
64 		extended, "rowBit17",
65 		json_object_new_boolean((memory_error->Extended >> 1) & 0b1));
66 	json_object_object_add(extended, "chipIdentification",
67 			       json_object_new_int(memory_error->Extended >>
68 						   5));
69 	json_object_object_add(section_ir, "extended", extended);
70 
71 	//Miscellaneous numeric fields.
72 	json_object_object_add(
73 		section_ir, "physicalAddress",
74 		json_object_new_uint64(memory_error->PhysicalAddress));
75 	json_object_object_add(
76 		section_ir, "physicalAddressMask",
77 		json_object_new_uint64(memory_error->PhysicalAddressMask));
78 	json_object_object_add(section_ir, "node",
79 			       json_object_new_uint64(memory_error->Node));
80 	json_object_object_add(section_ir, "card",
81 			       json_object_new_uint64(memory_error->Card));
82 	json_object_object_add(
83 		section_ir, "moduleRank",
84 		json_object_new_uint64(memory_error->ModuleRank));
85 	json_object_object_add(section_ir, "device",
86 			       json_object_new_uint64(memory_error->Device));
87 	json_object_object_add(section_ir, "row",
88 			       json_object_new_uint64(memory_error->Row));
89 	json_object_object_add(section_ir, "column",
90 			       json_object_new_uint64(memory_error->Column));
91 	json_object_object_add(
92 		section_ir, "bitPosition",
93 		json_object_new_uint64(memory_error->BitPosition));
94 	json_object_object_add(
95 		section_ir, "requestorID",
96 		json_object_new_uint64(memory_error->RequestorId));
97 	json_object_object_add(
98 		section_ir, "responderID",
99 		json_object_new_uint64(memory_error->ResponderId));
100 	json_object_object_add(section_ir, "targetID",
101 			       json_object_new_uint64(memory_error->TargetId));
102 	json_object_object_add(section_ir, "rankNumber",
103 			       json_object_new_uint64(memory_error->RankNum));
104 	json_object_object_add(
105 		section_ir, "cardSmbiosHandle",
106 		json_object_new_uint64(memory_error->CardHandle));
107 	json_object_object_add(
108 		section_ir, "moduleSmbiosHandle",
109 		json_object_new_uint64(memory_error->ModuleHandle));
110 
111 	return section_ir;
112 }
113 
114 //Converts a single memory error 2 CPER section into JSON IR.
115 json_object *
116 cper_section_platform_memory2_to_ir(void *section,
117 				    EFI_ERROR_SECTION_DESCRIPTOR *descriptor)
118 {
119 	EFI_PLATFORM_MEMORY2_ERROR_DATA *memory_error =
120 		(EFI_PLATFORM_MEMORY2_ERROR_DATA *)section;
121 	json_object *section_ir = json_object_new_object();
122 
123 	//Validation bits.
124 	json_object *validation =
125 		bitfield_to_ir(memory_error->ValidFields, 22,
126 			       MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
127 	json_object_object_add(section_ir, "validationBits", validation);
128 
129 	//Error status.
130 	json_object *error_status =
131 		cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
132 	json_object_object_add(section_ir, "errorStatus", error_status);
133 
134 	//Bank.
135 	json_object *bank = json_object_new_object();
136 	if ((memory_error->ValidFields >> 5) & 0x1) {
137 		//Entire bank address mode.
138 		json_object_object_add(
139 			bank, "value",
140 			json_object_new_uint64(memory_error->Bank));
141 	} else {
142 		//Address/group address mode.
143 		json_object_object_add(
144 			bank, "address",
145 			json_object_new_uint64(memory_error->Bank & 0xFF));
146 		json_object_object_add(
147 			bank, "group",
148 			json_object_new_uint64(memory_error->Bank >> 8));
149 	}
150 	json_object_object_add(section_ir, "bank", bank);
151 
152 	//Memory error type.
153 	json_object *memory_error_type = integer_to_readable_pair(
154 		memory_error->MemErrorType, 16, MEMORY_ERROR_TYPES_KEYS,
155 		MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)");
156 	json_object_object_add(section_ir, "memoryErrorType",
157 			       memory_error_type);
158 
159 	//Status.
160 	json_object *status = json_object_new_object();
161 	json_object_object_add(status, "value",
162 			       json_object_new_int(memory_error->Status));
163 	json_object_object_add(status, "state",
164 			       json_object_new_string(memory_error->Status &
165 								      0b1 == 0 ?
166 								    "Corrected" :
167 								    "Uncorrected"));
168 	json_object_object_add(section_ir, "status", status);
169 
170 	//Miscellaneous numeric fields.
171 	json_object_object_add(
172 		section_ir, "physicalAddress",
173 		json_object_new_uint64(memory_error->PhysicalAddress));
174 	json_object_object_add(
175 		section_ir, "physicalAddressMask",
176 		json_object_new_uint64(memory_error->PhysicalAddressMask));
177 	json_object_object_add(section_ir, "node",
178 			       json_object_new_uint64(memory_error->Node));
179 	json_object_object_add(section_ir, "card",
180 			       json_object_new_uint64(memory_error->Card));
181 	json_object_object_add(section_ir, "module",
182 			       json_object_new_uint64(memory_error->Module));
183 	json_object_object_add(section_ir, "device",
184 			       json_object_new_uint64(memory_error->Device));
185 	json_object_object_add(section_ir, "row",
186 			       json_object_new_uint64(memory_error->Row));
187 	json_object_object_add(section_ir, "column",
188 			       json_object_new_uint64(memory_error->Column));
189 	json_object_object_add(section_ir, "rank",
190 			       json_object_new_uint64(memory_error->Rank));
191 	json_object_object_add(
192 		section_ir, "bitPosition",
193 		json_object_new_uint64(memory_error->BitPosition));
194 	json_object_object_add(section_ir, "chipID",
195 			       json_object_new_uint64(memory_error->ChipId));
196 	json_object_object_add(
197 		section_ir, "requestorID",
198 		json_object_new_uint64(memory_error->RequestorId));
199 	json_object_object_add(
200 		section_ir, "responderID",
201 		json_object_new_uint64(memory_error->ResponderId));
202 	json_object_object_add(section_ir, "targetID",
203 			       json_object_new_uint64(memory_error->TargetId));
204 	json_object_object_add(
205 		section_ir, "cardSmbiosHandle",
206 		json_object_new_uint64(memory_error->CardHandle));
207 	json_object_object_add(
208 		section_ir, "moduleSmbiosHandle",
209 		json_object_new_uint64(memory_error->ModuleHandle));
210 
211 	return section_ir;
212 }
213 
214 //Converts a single Memory Error IR section into CPER binary, outputting to the provided stream.
215 void ir_section_memory_to_cper(json_object *section, FILE *out)
216 {
217 	EFI_PLATFORM_MEMORY_ERROR_DATA *section_cper =
218 		(EFI_PLATFORM_MEMORY_ERROR_DATA *)calloc(
219 			1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA));
220 
221 	//Validation bits.
222 	section_cper->ValidFields = ir_to_bitfield(
223 		json_object_object_get(section, "validationBits"), 22,
224 		MEMORY_ERROR_VALID_BITFIELD_NAMES);
225 
226 	//Error status.
227 	ir_generic_error_status_to_cper(json_object_object_get(section,
228 							       "errorStatus"),
229 					&section_cper->ErrorStatus);
230 
231 	//Bank.
232 	json_object *bank = json_object_object_get(section, "bank");
233 	if ((section_cper->ValidFields >> 5) & 0x1) {
234 		//Bank just uses simple address.
235 		section_cper->Bank = (UINT16)json_object_get_uint64(
236 			json_object_object_get(bank, "value"));
237 	} else {
238 		//Bank uses address/group style address.
239 		UINT16 address = (UINT8)json_object_get_uint64(
240 			json_object_object_get(bank, "address"));
241 		UINT16 group = (UINT8)json_object_get_uint64(
242 			json_object_object_get(bank, "group"));
243 		section_cper->Bank = address + (group << 8);
244 	}
245 
246 	//"Extended" field.
247 	json_object *extended = json_object_object_get(section, "extended");
248 	section_cper->Extended = 0;
249 	section_cper->Extended |= json_object_get_boolean(
250 		json_object_object_get(extended, "rowBit16"));
251 	section_cper->Extended |=
252 		json_object_get_boolean(
253 			json_object_object_get(extended, "rowBit17"))
254 		<< 1;
255 	section_cper->Extended |= json_object_get_int(json_object_object_get(
256 					  extended, "chipIdentification"))
257 				  << 5;
258 
259 	//Miscellaneous value fields.
260 	section_cper->ErrorType = (UINT8)readable_pair_to_integer(
261 		json_object_object_get(section, "memoryErrorType"));
262 	section_cper->PhysicalAddress = json_object_get_uint64(
263 		json_object_object_get(section, "physicalAddress"));
264 	section_cper->PhysicalAddressMask = json_object_get_uint64(
265 		json_object_object_get(section, "physicalAddressMask"));
266 	section_cper->Node = (UINT16)json_object_get_uint64(
267 		json_object_object_get(section, "node"));
268 	section_cper->Card = (UINT16)json_object_get_uint64(
269 		json_object_object_get(section, "card"));
270 	section_cper->ModuleRank = (UINT16)json_object_get_uint64(
271 		json_object_object_get(section, "moduleRank"));
272 	section_cper->Device = (UINT16)json_object_get_uint64(
273 		json_object_object_get(section, "device"));
274 	section_cper->Row = (UINT16)json_object_get_uint64(
275 		json_object_object_get(section, "row"));
276 	section_cper->Column = (UINT16)json_object_get_uint64(
277 		json_object_object_get(section, "column"));
278 	section_cper->BitPosition = (UINT16)json_object_get_uint64(
279 		json_object_object_get(section, "bitPosition"));
280 	section_cper->RequestorId = json_object_get_uint64(
281 		json_object_object_get(section, "requestorID"));
282 	section_cper->ResponderId = json_object_get_uint64(
283 		json_object_object_get(section, "responderID"));
284 	section_cper->TargetId = json_object_get_uint64(
285 		json_object_object_get(section, "targetID"));
286 	section_cper->RankNum = (UINT16)json_object_get_uint64(
287 		json_object_object_get(section, "rankNumber"));
288 	section_cper->CardHandle = (UINT16)json_object_get_uint64(
289 		json_object_object_get(section, "cardSmbiosHandle"));
290 	section_cper->ModuleHandle = (UINT16)json_object_get_uint64(
291 		json_object_object_get(section, "moduleSmbiosHandle"));
292 
293 	//Write to stream, free up resources.
294 	fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA), 1, out);
295 	fflush(out);
296 	free(section_cper);
297 }
298 
299 //Converts a single Memory Error 2 IR section into CPER binary, outputting to the provided stream.
300 void ir_section_memory2_to_cper(json_object *section, FILE *out)
301 {
302 	EFI_PLATFORM_MEMORY2_ERROR_DATA *section_cper =
303 		(EFI_PLATFORM_MEMORY2_ERROR_DATA *)calloc(
304 			1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA));
305 
306 	//Validation bits.
307 	section_cper->ValidFields = ir_to_bitfield(
308 		json_object_object_get(section, "validationBits"), 22,
309 		MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
310 
311 	//Error status.
312 	ir_generic_error_status_to_cper(json_object_object_get(section,
313 							       "errorStatus"),
314 					&section_cper->ErrorStatus);
315 
316 	//Bank.
317 	json_object *bank = json_object_object_get(section, "bank");
318 	if ((section_cper->ValidFields >> 5) & 0x1) {
319 		//Bank just uses simple address.
320 		section_cper->Bank = (UINT16)json_object_get_uint64(
321 			json_object_object_get(bank, "value"));
322 	} else {
323 		//Bank uses address/group style address.
324 		UINT16 address = (UINT8)json_object_get_uint64(
325 			json_object_object_get(bank, "address"));
326 		UINT16 group = (UINT8)json_object_get_uint64(
327 			json_object_object_get(bank, "group"));
328 		section_cper->Bank = address + (group << 8);
329 	}
330 
331 	//Miscellaneous value fields.
332 	section_cper->MemErrorType = readable_pair_to_integer(
333 		json_object_object_get(section, "memoryErrorType"));
334 	section_cper->Status = (UINT8)readable_pair_to_integer(
335 		json_object_object_get(section, "status"));
336 	section_cper->PhysicalAddress = json_object_get_uint64(
337 		json_object_object_get(section, "physicalAddress"));
338 	section_cper->PhysicalAddressMask = json_object_get_uint64(
339 		json_object_object_get(section, "physicalAddressMask"));
340 	section_cper->Node = (UINT16)json_object_get_uint64(
341 		json_object_object_get(section, "node"));
342 	section_cper->Card = (UINT16)json_object_get_uint64(
343 		json_object_object_get(section, "card"));
344 	section_cper->Module = (UINT32)json_object_get_uint64(
345 		json_object_object_get(section, "module"));
346 	section_cper->Device = (UINT32)json_object_get_uint64(
347 		json_object_object_get(section, "device"));
348 	section_cper->Row = (UINT32)json_object_get_uint64(
349 		json_object_object_get(section, "row"));
350 	section_cper->Column = (UINT32)json_object_get_uint64(
351 		json_object_object_get(section, "column"));
352 	section_cper->Rank = (UINT32)json_object_get_uint64(
353 		json_object_object_get(section, "rank"));
354 	section_cper->BitPosition = (UINT32)json_object_get_uint64(
355 		json_object_object_get(section, "bitPosition"));
356 	section_cper->ChipId = (UINT8)json_object_get_uint64(
357 		json_object_object_get(section, "chipID"));
358 	section_cper->RequestorId = json_object_get_uint64(
359 		json_object_object_get(section, "requestorID"));
360 	section_cper->ResponderId = json_object_get_uint64(
361 		json_object_object_get(section, "responderID"));
362 	section_cper->TargetId = json_object_get_uint64(
363 		json_object_object_get(section, "targetID"));
364 	section_cper->CardHandle = (UINT32)json_object_get_uint64(
365 		json_object_object_get(section, "cardSmbiosHandle"));
366 	section_cper->ModuleHandle = (UINT32)json_object_get_uint64(
367 		json_object_object_get(section, "moduleSmbiosHandle"));
368 
369 	//Write to stream, free up resources.
370 	fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out);
371 	fflush(out);
372 	free(section_cper);
373 }