1a416ec93SLawrence Tang /**
2a416ec93SLawrence Tang  * Describes functions for converting PCI/PCI-X device CPER sections from binary and JSON format
3a416ec93SLawrence Tang  * into an intermediate format.
4a416ec93SLawrence Tang  *
5a416ec93SLawrence Tang  * Author: Lawrence.Tang@arm.com
6a416ec93SLawrence Tang  **/
7a416ec93SLawrence Tang #include <stdio.h>
85202bbb4SLawrence Tang #include <json.h>
9a416ec93SLawrence Tang #include "../edk/Cper.h"
10a416ec93SLawrence Tang #include "../cper-utils.h"
11a416ec93SLawrence Tang #include "cper-section-pci-dev.h"
12a416ec93SLawrence Tang 
13a416ec93SLawrence Tang //Converts a single PCI/PCI-X device CPER section into JSON IR.
cper_section_pci_dev_to_ir(void * section)14*f8fc7052SJohn Chung json_object *cper_section_pci_dev_to_ir(void *section)
15a416ec93SLawrence Tang {
16e407b4c8SLawrence Tang 	EFI_PCI_PCIX_DEVICE_ERROR_DATA *dev_error =
17e407b4c8SLawrence Tang 		(EFI_PCI_PCIX_DEVICE_ERROR_DATA *)section;
18a416ec93SLawrence Tang 	json_object *section_ir = json_object_new_object();
19a416ec93SLawrence Tang 
20a416ec93SLawrence Tang 	//Validation bits.
21e407b4c8SLawrence Tang 	json_object *validation = bitfield_to_ir(
22e407b4c8SLawrence Tang 		dev_error->ValidFields, 5, PCI_DEV_ERROR_VALID_BITFIELD_NAMES);
23a416ec93SLawrence Tang 	json_object_object_add(section_ir, "validationBits", validation);
24a416ec93SLawrence Tang 
25a416ec93SLawrence Tang 	//Error status.
26e407b4c8SLawrence Tang 	json_object *error_status =
27e407b4c8SLawrence Tang 		cper_generic_error_status_to_ir(&dev_error->ErrorStatus);
28a416ec93SLawrence Tang 	json_object_object_add(section_ir, "errorStatus", error_status);
29a416ec93SLawrence Tang 
30a416ec93SLawrence Tang 	//ID information.
31a416ec93SLawrence Tang 	json_object *id_info = json_object_new_object();
32e407b4c8SLawrence Tang 	json_object_object_add(
33e407b4c8SLawrence Tang 		id_info, "vendorID",
34e407b4c8SLawrence Tang 		json_object_new_uint64(dev_error->IdInfo.VendorId));
35e407b4c8SLawrence Tang 	json_object_object_add(
36e407b4c8SLawrence Tang 		id_info, "deviceID",
37e407b4c8SLawrence Tang 		json_object_new_uint64(dev_error->IdInfo.DeviceId));
38e407b4c8SLawrence Tang 	json_object_object_add(
39e407b4c8SLawrence Tang 		id_info, "classCode",
40e407b4c8SLawrence Tang 		json_object_new_uint64(dev_error->IdInfo.ClassCode));
41e407b4c8SLawrence Tang 	json_object_object_add(
42e407b4c8SLawrence Tang 		id_info, "functionNumber",
43e407b4c8SLawrence Tang 		json_object_new_uint64(dev_error->IdInfo.FunctionNumber));
44e407b4c8SLawrence Tang 	json_object_object_add(
45e407b4c8SLawrence Tang 		id_info, "deviceNumber",
46e407b4c8SLawrence Tang 		json_object_new_uint64(dev_error->IdInfo.DeviceNumber));
47e407b4c8SLawrence Tang 	json_object_object_add(
48e407b4c8SLawrence Tang 		id_info, "busNumber",
49e407b4c8SLawrence Tang 		json_object_new_uint64(dev_error->IdInfo.BusNumber));
50e407b4c8SLawrence Tang 	json_object_object_add(
51e407b4c8SLawrence Tang 		id_info, "segmentNumber",
52e407b4c8SLawrence Tang 		json_object_new_uint64(dev_error->IdInfo.SegmentNumber));
53a416ec93SLawrence Tang 	json_object_object_add(section_ir, "idInfo", id_info);
54a416ec93SLawrence Tang 
55a416ec93SLawrence Tang 	//Number of following register data pairs.
56e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "memoryNumber",
57e407b4c8SLawrence Tang 			       json_object_new_uint64(dev_error->MemoryNumber));
58e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "ioNumber",
59e407b4c8SLawrence Tang 			       json_object_new_uint64(dev_error->IoNumber));
60a416ec93SLawrence Tang 	int num_data_pairs = dev_error->MemoryNumber + dev_error->IoNumber;
61a416ec93SLawrence Tang 
62a416ec93SLawrence Tang 	//Register pairs, described by the numeric fields.
63a416ec93SLawrence Tang 	//The actual "pairs" of address and data aren't necessarily 8 bytes long, so can't assume the contents.
64a416ec93SLawrence Tang 	//Hence the naming "firstHalf" and "secondHalf" rather than "address" and "data".
65a416ec93SLawrence Tang 	json_object *register_data_pair_array = json_object_new_array();
66a416ec93SLawrence Tang 	UINT64 *cur_pos = (UINT64 *)(dev_error + 1);
67e407b4c8SLawrence Tang 	for (int i = 0; i < num_data_pairs; i++) {
68a416ec93SLawrence Tang 		//Save current pair to array.
69a416ec93SLawrence Tang 		json_object *register_data_pair = json_object_new_object();
70e407b4c8SLawrence Tang 		json_object_object_add(register_data_pair, "firstHalf",
71e407b4c8SLawrence Tang 				       json_object_new_uint64(*cur_pos));
72e407b4c8SLawrence Tang 		json_object_object_add(register_data_pair, "secondHalf",
73e407b4c8SLawrence Tang 				       json_object_new_uint64(*(cur_pos + 1)));
74e407b4c8SLawrence Tang 		json_object_array_add(register_data_pair_array,
75e407b4c8SLawrence Tang 				      register_data_pair);
76a416ec93SLawrence Tang 
77a416ec93SLawrence Tang 		//Move to next pair.
78a416ec93SLawrence Tang 		cur_pos += 2;
79a416ec93SLawrence Tang 	}
80e407b4c8SLawrence Tang 	json_object_object_add(section_ir, "registerDataPairs",
81e407b4c8SLawrence Tang 			       register_data_pair_array);
82a416ec93SLawrence Tang 
83a416ec93SLawrence Tang 	return section_ir;
84a416ec93SLawrence Tang }
85205dd1d7SLawrence Tang 
ir_section_pci_dev_to_cper(json_object * section,FILE * out)86205dd1d7SLawrence Tang void ir_section_pci_dev_to_cper(json_object *section, FILE *out)
87205dd1d7SLawrence Tang {
88205dd1d7SLawrence Tang 	EFI_PCI_PCIX_DEVICE_ERROR_DATA *section_cper =
89e407b4c8SLawrence Tang 		(EFI_PCI_PCIX_DEVICE_ERROR_DATA *)calloc(
90e407b4c8SLawrence Tang 			1, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA));
91205dd1d7SLawrence Tang 
92205dd1d7SLawrence Tang 	//Validation bits.
93e407b4c8SLawrence Tang 	section_cper->ValidFields = ir_to_bitfield(
94e407b4c8SLawrence Tang 		json_object_object_get(section, "validationBits"), 5,
95e407b4c8SLawrence Tang 		PCI_DEV_ERROR_VALID_BITFIELD_NAMES);
96205dd1d7SLawrence Tang 
97205dd1d7SLawrence Tang 	//Error status.
98e407b4c8SLawrence Tang 	ir_generic_error_status_to_cper(json_object_object_get(section,
99e407b4c8SLawrence Tang 							       "errorStatus"),
100e407b4c8SLawrence Tang 					&section_cper->ErrorStatus);
101205dd1d7SLawrence Tang 
102205dd1d7SLawrence Tang 	//Device ID information.
103205dd1d7SLawrence Tang 	json_object *id_info = json_object_object_get(section, "idInfo");
104e407b4c8SLawrence Tang 	section_cper->IdInfo.VendorId = json_object_get_uint64(
105e407b4c8SLawrence Tang 		json_object_object_get(id_info, "vendorID"));
106e407b4c8SLawrence Tang 	section_cper->IdInfo.DeviceId = json_object_get_uint64(
107e407b4c8SLawrence Tang 		json_object_object_get(id_info, "deviceID"));
108e407b4c8SLawrence Tang 	section_cper->IdInfo.ClassCode = json_object_get_uint64(
109e407b4c8SLawrence Tang 		json_object_object_get(id_info, "classCode"));
110e407b4c8SLawrence Tang 	section_cper->IdInfo.FunctionNumber = json_object_get_uint64(
111e407b4c8SLawrence Tang 		json_object_object_get(id_info, "functionNumber"));
112e407b4c8SLawrence Tang 	section_cper->IdInfo.DeviceNumber = json_object_get_uint64(
113e407b4c8SLawrence Tang 		json_object_object_get(id_info, "deviceNumber"));
114e407b4c8SLawrence Tang 	section_cper->IdInfo.BusNumber = json_object_get_uint64(
115e407b4c8SLawrence Tang 		json_object_object_get(id_info, "busNumber"));
116e407b4c8SLawrence Tang 	section_cper->IdInfo.SegmentNumber = json_object_get_uint64(
117e407b4c8SLawrence Tang 		json_object_object_get(id_info, "segmentNumber"));
118205dd1d7SLawrence Tang 
119205dd1d7SLawrence Tang 	//Amount of following data pairs.
120e407b4c8SLawrence Tang 	section_cper->MemoryNumber = (UINT32)json_object_get_uint64(
121e407b4c8SLawrence Tang 		json_object_object_get(section, "memoryNumber"));
122e407b4c8SLawrence Tang 	section_cper->IoNumber = (UINT32)json_object_get_uint64(
123e407b4c8SLawrence Tang 		json_object_object_get(section, "ioNumber"));
124205dd1d7SLawrence Tang 
125205dd1d7SLawrence Tang 	//Write header out to stream, free it.
1260a4b3f2dSLawrence Tang 	fwrite(section_cper, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA), 1, out);
127205dd1d7SLawrence Tang 	fflush(out);
128205dd1d7SLawrence Tang 	free(section_cper);
129205dd1d7SLawrence Tang 
130205dd1d7SLawrence Tang 	//Begin writing register pairs.
131e407b4c8SLawrence Tang 	json_object *register_pairs =
132e407b4c8SLawrence Tang 		json_object_object_get(section, "registerDataPairs");
133205dd1d7SLawrence Tang 	int num_pairs = json_object_array_length(register_pairs);
134e407b4c8SLawrence Tang 	for (int i = 0; i < num_pairs; i++) {
135205dd1d7SLawrence Tang 		//Get the pair array item out.
136e407b4c8SLawrence Tang 		json_object *register_pair =
137e407b4c8SLawrence Tang 			json_object_array_get_idx(register_pairs, i);
138205dd1d7SLawrence Tang 
139205dd1d7SLawrence Tang 		//Create the pair array.
140205dd1d7SLawrence Tang 		UINT64 pair[2];
141e407b4c8SLawrence Tang 		pair[0] = json_object_get_uint64(
142e407b4c8SLawrence Tang 			json_object_object_get(register_pair, "firstHalf"));
143e407b4c8SLawrence Tang 		pair[1] = json_object_get_uint64(
144e407b4c8SLawrence Tang 			json_object_object_get(register_pair, "secondHalf"));
145205dd1d7SLawrence Tang 
146205dd1d7SLawrence Tang 		//Push to stream.
147205dd1d7SLawrence Tang 		fwrite(pair, sizeof(UINT64), 2, out);
148205dd1d7SLawrence Tang 		fflush(out);
149205dd1d7SLawrence Tang 	}
150205dd1d7SLawrence Tang }
151