blob: 8dc899b47d49bed1f9285445d8ee6d9fc8bee7c7 [file] [log] [blame]
Lawrence Tanga416ec92022-07-06 14:34:40 +01001/**
2 * Describes functions for converting PCI/PCI-X device CPER sections from binary and JSON format
3 * into an intermediate format.
Ed Tanousfedd4572024-07-12 13:56:00 -07004 *
Lawrence Tanga416ec92022-07-06 14:34:40 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7#include <stdio.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01008#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +00009#include <libcper/Cper.h>
10#include <libcper/cper-utils.h>
11#include <libcper/sections/cper-section-pci-dev.h>
Lawrence Tanga416ec92022-07-06 14:34:40 +010012
13//Converts a single PCI/PCI-X device CPER section into JSON IR.
John Chungf8fc7052024-05-03 20:05:29 +080014json_object *cper_section_pci_dev_to_ir(void *section)
Lawrence Tanga416ec92022-07-06 14:34:40 +010015{
Lawrence Tange407b4c2022-07-21 13:54:01 +010016 EFI_PCI_PCIX_DEVICE_ERROR_DATA *dev_error =
17 (EFI_PCI_PCIX_DEVICE_ERROR_DATA *)section;
18 json_object *section_ir = json_object_new_object();
Lawrence Tanga416ec92022-07-06 14:34:40 +010019
Lawrence Tange407b4c2022-07-21 13:54:01 +010020 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080021 ValidationTypes ui64Type = { UINT_64T,
22 .value.ui64 = dev_error->ValidFields };
Lawrence Tanga416ec92022-07-06 14:34:40 +010023
Lawrence Tange407b4c2022-07-21 13:54:01 +010024 //Error status.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080025 if (isvalid_prop_to_ir(&ui64Type, 0)) {
26 json_object *error_status = cper_generic_error_status_to_ir(
27 &dev_error->ErrorStatus);
28 json_object_object_add(section_ir, "errorStatus", error_status);
29 }
Lawrence Tanga416ec92022-07-06 14:34:40 +010030
Lawrence Tange407b4c2022-07-21 13:54:01 +010031 //ID information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080032 if (isvalid_prop_to_ir(&ui64Type, 1)) {
33 json_object *id_info = json_object_new_object();
34 json_object_object_add(
35 id_info, "vendorID",
36 json_object_new_uint64(dev_error->IdInfo.VendorId));
37 json_object_object_add(
38 id_info, "deviceID",
39 json_object_new_uint64(dev_error->IdInfo.DeviceId));
40 json_object_object_add(
41 id_info, "classCode",
42 json_object_new_uint64(dev_error->IdInfo.ClassCode));
43 json_object_object_add(
44 id_info, "functionNumber",
45 json_object_new_uint64(
46 dev_error->IdInfo.FunctionNumber));
47 json_object_object_add(
48 id_info, "deviceNumber",
49 json_object_new_uint64(dev_error->IdInfo.DeviceNumber));
50 json_object_object_add(
51 id_info, "busNumber",
52 json_object_new_uint64(dev_error->IdInfo.BusNumber));
53 json_object_object_add(
54 id_info, "segmentNumber",
55 json_object_new_uint64(
56 dev_error->IdInfo.SegmentNumber));
57 json_object_object_add(section_ir, "idInfo", id_info);
58 }
Lawrence Tanga416ec92022-07-06 14:34:40 +010059
Lawrence Tange407b4c2022-07-21 13:54:01 +010060 //Number of following register data pairs.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080061 if (isvalid_prop_to_ir(&ui64Type, 2)) {
62 json_object_object_add(
63 section_ir, "memoryNumber",
64 json_object_new_uint64(dev_error->MemoryNumber));
Lawrence Tange407b4c2022-07-21 13:54:01 +010065 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080066 if (isvalid_prop_to_ir(&ui64Type, 3)) {
67 json_object_object_add(
68 section_ir, "ioNumber",
69 json_object_new_uint64(dev_error->IoNumber));
70 }
71
72 if (isvalid_prop_to_ir(&ui64Type, 4)) {
73 int num_data_pairs =
74 dev_error->MemoryNumber + dev_error->IoNumber;
75
76 //Register pairs, described by the numeric fields.
77 //The actual "pairs" of address and data aren't necessarily 8 bytes long, so can't assume the contents.
78 //Hence the naming "firstHalf" and "secondHalf" rather than "address" and "data".
79 json_object *register_data_pair_array = json_object_new_array();
80 UINT64 *cur_pos = (UINT64 *)(dev_error + 1);
81 for (int i = 0; i < num_data_pairs; i++) {
82 //Save current pair to array.
83 json_object *register_data_pair =
84 json_object_new_object();
85 json_object_object_add(
86 register_data_pair, "firstHalf",
87 json_object_new_uint64(*cur_pos));
88 json_object_object_add(
89 register_data_pair, "secondHalf",
90 json_object_new_uint64(*(cur_pos + 1)));
91 json_object_array_add(register_data_pair_array,
92 register_data_pair);
93
94 //Move to next pair.
95 cur_pos += 2;
96 }
97 json_object_object_add(section_ir, "registerDataPairs",
98 register_data_pair_array);
99 }
Lawrence Tanga416ec92022-07-06 14:34:40 +0100100
Lawrence Tange407b4c2022-07-21 13:54:01 +0100101 return section_ir;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100102}
103
Lawrence Tange407b4c2022-07-21 13:54:01 +0100104void ir_section_pci_dev_to_cper(json_object *section, FILE *out)
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100105{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100106 EFI_PCI_PCIX_DEVICE_ERROR_DATA *section_cper =
107 (EFI_PCI_PCIX_DEVICE_ERROR_DATA *)calloc(
108 1, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100109
Lawrence Tange407b4c2022-07-21 13:54:01 +0100110 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800111 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
112 struct json_object *obj = NULL;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100113
Lawrence Tange407b4c2022-07-21 13:54:01 +0100114 //Error status.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800115 if (json_object_object_get_ex(section, "errorStatus", &obj)) {
116 ir_generic_error_status_to_cper(obj,
117 &section_cper->ErrorStatus);
118 add_to_valid_bitfield(&ui64Type, 0);
119 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100120
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 //Device ID information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800122 if (json_object_object_get_ex(section, "idInfo", &obj)) {
123 json_object *id_info = obj;
124 section_cper->IdInfo.VendorId = json_object_get_uint64(
125 json_object_object_get(id_info, "vendorID"));
126 section_cper->IdInfo.DeviceId = json_object_get_uint64(
127 json_object_object_get(id_info, "deviceID"));
128 section_cper->IdInfo.ClassCode = json_object_get_uint64(
129 json_object_object_get(id_info, "classCode"));
130 section_cper->IdInfo.FunctionNumber = json_object_get_uint64(
131 json_object_object_get(id_info, "functionNumber"));
132 section_cper->IdInfo.DeviceNumber = json_object_get_uint64(
133 json_object_object_get(id_info, "deviceNumber"));
134 section_cper->IdInfo.BusNumber = json_object_get_uint64(
135 json_object_object_get(id_info, "busNumber"));
136 section_cper->IdInfo.SegmentNumber = json_object_get_uint64(
137 json_object_object_get(id_info, "segmentNumber"));
138 add_to_valid_bitfield(&ui64Type, 1);
139 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100140
Lawrence Tange407b4c2022-07-21 13:54:01 +0100141 //Amount of following data pairs.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800142 if (json_object_object_get_ex(section, "memoryNumber", &obj)) {
143 section_cper->MemoryNumber =
144 (UINT32)json_object_get_uint64(obj);
145 add_to_valid_bitfield(&ui64Type, 2);
146 }
147 if (json_object_object_get_ex(section, "ioNumber", &obj)) {
148 section_cper->IoNumber = (UINT32)json_object_get_uint64(obj);
149 add_to_valid_bitfield(&ui64Type, 3);
150 }
151 json_object *register_pairs = NULL;
152 if (json_object_object_get_ex(section, "registerDataPairs", &obj)) {
153 register_pairs = obj;
154 add_to_valid_bitfield(&ui64Type, 4);
155 }
156
157 section_cper->ValidFields = ui64Type.value.ui64;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100158
Lawrence Tange407b4c2022-07-21 13:54:01 +0100159 //Write header out to stream, free it.
160 fwrite(section_cper, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA), 1, out);
161 fflush(out);
162 free(section_cper);
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100163
Lawrence Tange407b4c2022-07-21 13:54:01 +0100164 //Begin writing register pairs.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800165 if (register_pairs != NULL) {
166 int num_pairs = json_object_array_length(register_pairs);
167 for (int i = 0; i < num_pairs; i++) {
168 //Get the pair array item out.
169 json_object *register_pair =
170 json_object_array_get_idx(register_pairs, i);
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100171
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800172 //Create the pair array.
173 UINT64 pair[2];
174 pair[0] = json_object_get_uint64(json_object_object_get(
175 register_pair, "firstHalf"));
176 pair[1] = json_object_get_uint64(json_object_object_get(
177 register_pair, "secondHalf"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100178
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800179 //Push to stream.
180 fwrite(pair, sizeof(UINT64), 2, out);
181 fflush(out);
182 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100183 }
John Chungf8fc7052024-05-03 20:05:29 +0800184}