blob: 9f8949490b5c4e4ecc9b3398b49b3e9044c66d3b [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.
Ed Tanous12dbd4f2025-03-08 19:05:01 -080014json_object *cper_section_pci_dev_to_ir(const UINT8 *section, UINT32 size)
Lawrence Tanga416ec92022-07-06 14:34:40 +010015{
Ed Tanous12dbd4f2025-03-08 19:05:01 -080016 if (size < sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA)) {
17 return NULL;
18 }
19
Lawrence Tange407b4c2022-07-21 13:54:01 +010020 EFI_PCI_PCIX_DEVICE_ERROR_DATA *dev_error =
21 (EFI_PCI_PCIX_DEVICE_ERROR_DATA *)section;
Ed Tanous12dbd4f2025-03-08 19:05:01 -080022
23 if (size < sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA) +
24 ((dev_error->MemoryNumber + dev_error->IoNumber) *
25 sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA_REGISTER))) {
26 return NULL;
27 }
28
Lawrence Tange407b4c2022-07-21 13:54:01 +010029 json_object *section_ir = json_object_new_object();
Lawrence Tanga416ec92022-07-06 14:34:40 +010030
Lawrence Tange407b4c2022-07-21 13:54:01 +010031 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080032 ValidationTypes ui64Type = { UINT_64T,
33 .value.ui64 = dev_error->ValidFields };
Lawrence Tanga416ec92022-07-06 14:34:40 +010034
Lawrence Tange407b4c2022-07-21 13:54:01 +010035 //Error status.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080036 if (isvalid_prop_to_ir(&ui64Type, 0)) {
37 json_object *error_status = cper_generic_error_status_to_ir(
38 &dev_error->ErrorStatus);
39 json_object_object_add(section_ir, "errorStatus", error_status);
40 }
Lawrence Tanga416ec92022-07-06 14:34:40 +010041
Lawrence Tange407b4c2022-07-21 13:54:01 +010042 //ID information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080043 if (isvalid_prop_to_ir(&ui64Type, 1)) {
44 json_object *id_info = json_object_new_object();
45 json_object_object_add(
46 id_info, "vendorID",
47 json_object_new_uint64(dev_error->IdInfo.VendorId));
48 json_object_object_add(
49 id_info, "deviceID",
50 json_object_new_uint64(dev_error->IdInfo.DeviceId));
51 json_object_object_add(
52 id_info, "classCode",
53 json_object_new_uint64(dev_error->IdInfo.ClassCode));
54 json_object_object_add(
55 id_info, "functionNumber",
56 json_object_new_uint64(
57 dev_error->IdInfo.FunctionNumber));
58 json_object_object_add(
59 id_info, "deviceNumber",
60 json_object_new_uint64(dev_error->IdInfo.DeviceNumber));
61 json_object_object_add(
62 id_info, "busNumber",
63 json_object_new_uint64(dev_error->IdInfo.BusNumber));
64 json_object_object_add(
65 id_info, "segmentNumber",
66 json_object_new_uint64(
67 dev_error->IdInfo.SegmentNumber));
68 json_object_object_add(section_ir, "idInfo", id_info);
69 }
Lawrence Tanga416ec92022-07-06 14:34:40 +010070
Lawrence Tange407b4c2022-07-21 13:54:01 +010071 //Number of following register data pairs.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080072 if (isvalid_prop_to_ir(&ui64Type, 2)) {
73 json_object_object_add(
74 section_ir, "memoryNumber",
75 json_object_new_uint64(dev_error->MemoryNumber));
Lawrence Tange407b4c2022-07-21 13:54:01 +010076 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080077 if (isvalid_prop_to_ir(&ui64Type, 3)) {
78 json_object_object_add(
79 section_ir, "ioNumber",
80 json_object_new_uint64(dev_error->IoNumber));
81 }
82
83 if (isvalid_prop_to_ir(&ui64Type, 4)) {
84 int num_data_pairs =
85 dev_error->MemoryNumber + dev_error->IoNumber;
86
87 //Register pairs, described by the numeric fields.
88 //The actual "pairs" of address and data aren't necessarily 8 bytes long, so can't assume the contents.
89 //Hence the naming "firstHalf" and "secondHalf" rather than "address" and "data".
90 json_object *register_data_pair_array = json_object_new_array();
91 UINT64 *cur_pos = (UINT64 *)(dev_error + 1);
92 for (int i = 0; i < num_data_pairs; i++) {
93 //Save current pair to array.
94 json_object *register_data_pair =
95 json_object_new_object();
96 json_object_object_add(
97 register_data_pair, "firstHalf",
98 json_object_new_uint64(*cur_pos));
99 json_object_object_add(
100 register_data_pair, "secondHalf",
101 json_object_new_uint64(*(cur_pos + 1)));
102 json_object_array_add(register_data_pair_array,
103 register_data_pair);
104
105 //Move to next pair.
106 cur_pos += 2;
107 }
108 json_object_object_add(section_ir, "registerDataPairs",
109 register_data_pair_array);
110 }
Lawrence Tanga416ec92022-07-06 14:34:40 +0100111
Lawrence Tange407b4c2022-07-21 13:54:01 +0100112 return section_ir;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100113}
114
Lawrence Tange407b4c2022-07-21 13:54:01 +0100115void ir_section_pci_dev_to_cper(json_object *section, FILE *out)
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100116{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100117 EFI_PCI_PCIX_DEVICE_ERROR_DATA *section_cper =
118 (EFI_PCI_PCIX_DEVICE_ERROR_DATA *)calloc(
119 1, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100120
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800122 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
123 struct json_object *obj = NULL;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100124
Lawrence Tange407b4c2022-07-21 13:54:01 +0100125 //Error status.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800126 if (json_object_object_get_ex(section, "errorStatus", &obj)) {
127 ir_generic_error_status_to_cper(obj,
128 &section_cper->ErrorStatus);
129 add_to_valid_bitfield(&ui64Type, 0);
130 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100131
Lawrence Tange407b4c2022-07-21 13:54:01 +0100132 //Device ID information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800133 if (json_object_object_get_ex(section, "idInfo", &obj)) {
134 json_object *id_info = obj;
135 section_cper->IdInfo.VendorId = json_object_get_uint64(
136 json_object_object_get(id_info, "vendorID"));
137 section_cper->IdInfo.DeviceId = json_object_get_uint64(
138 json_object_object_get(id_info, "deviceID"));
139 section_cper->IdInfo.ClassCode = json_object_get_uint64(
140 json_object_object_get(id_info, "classCode"));
141 section_cper->IdInfo.FunctionNumber = json_object_get_uint64(
142 json_object_object_get(id_info, "functionNumber"));
143 section_cper->IdInfo.DeviceNumber = json_object_get_uint64(
144 json_object_object_get(id_info, "deviceNumber"));
145 section_cper->IdInfo.BusNumber = json_object_get_uint64(
146 json_object_object_get(id_info, "busNumber"));
147 section_cper->IdInfo.SegmentNumber = json_object_get_uint64(
148 json_object_object_get(id_info, "segmentNumber"));
149 add_to_valid_bitfield(&ui64Type, 1);
150 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100151
Lawrence Tange407b4c2022-07-21 13:54:01 +0100152 //Amount of following data pairs.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800153 if (json_object_object_get_ex(section, "memoryNumber", &obj)) {
154 section_cper->MemoryNumber =
155 (UINT32)json_object_get_uint64(obj);
156 add_to_valid_bitfield(&ui64Type, 2);
157 }
158 if (json_object_object_get_ex(section, "ioNumber", &obj)) {
159 section_cper->IoNumber = (UINT32)json_object_get_uint64(obj);
160 add_to_valid_bitfield(&ui64Type, 3);
161 }
162 json_object *register_pairs = NULL;
163 if (json_object_object_get_ex(section, "registerDataPairs", &obj)) {
164 register_pairs = obj;
165 add_to_valid_bitfield(&ui64Type, 4);
166 }
167
168 section_cper->ValidFields = ui64Type.value.ui64;
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100169
Lawrence Tange407b4c2022-07-21 13:54:01 +0100170 //Write header out to stream, free it.
171 fwrite(section_cper, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA), 1, out);
172 fflush(out);
173 free(section_cper);
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100174
Lawrence Tange407b4c2022-07-21 13:54:01 +0100175 //Begin writing register pairs.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800176 if (register_pairs != NULL) {
177 int num_pairs = json_object_array_length(register_pairs);
178 for (int i = 0; i < num_pairs; i++) {
179 //Get the pair array item out.
180 json_object *register_pair =
181 json_object_array_get_idx(register_pairs, i);
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100182
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800183 //Create the pair array.
184 UINT64 pair[2];
185 pair[0] = json_object_get_uint64(json_object_object_get(
186 register_pair, "firstHalf"));
187 pair[1] = json_object_get_uint64(json_object_object_get(
188 register_pair, "secondHalf"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100189
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800190 //Push to stream.
191 fwrite(pair, sizeof(UINT64), 2, out);
192 fflush(out);
193 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100194 }
John Chungf8fc7052024-05-03 20:05:29 +0800195}