1 #include "inventory_manager.hpp"
2
3 #include "common/utils.hpp"
4 #include "xyz/openbmc_project/Software/Version/server.hpp"
5
6 #include <libpldm/firmware_update.h>
7
8 #include <phosphor-logging/lg2.hpp>
9
10 #include <functional>
11
12 PHOSPHOR_LOG2_USING;
13
14 namespace pldm
15 {
16 namespace fw_update
17 {
discoverFDs(const std::vector<mctp_eid_t> & eids)18 void InventoryManager::discoverFDs(const std::vector<mctp_eid_t>& eids)
19 {
20 for (const auto& eid : eids)
21 {
22 auto instanceId = instanceIdDb.next(eid);
23 Request requestMsg(
24 sizeof(pldm_msg_hdr) + PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES);
25 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
26 auto rc = encode_query_device_identifiers_req(
27 instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request);
28 if (rc)
29 {
30 instanceIdDb.free(eid, instanceId);
31 error(
32 "Failed to encode query device identifiers req for endpoint ID '{EID}', response code '{RC}'",
33 "EID", eid, "RC", rc);
34 continue;
35 }
36
37 rc = handler.registerRequest(
38 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS,
39 std::move(requestMsg),
40 std::bind_front(&InventoryManager::queryDeviceIdentifiers, this));
41 if (rc)
42 {
43 error(
44 "Failed to send query device identifiers request for endpoint ID '{EID}', response code '{RC}'",
45 "EID", eid, "RC", rc);
46 }
47 }
48 }
49
queryDeviceIdentifiers(mctp_eid_t eid,const pldm_msg * response,size_t respMsgLen)50 void InventoryManager::queryDeviceIdentifiers(
51 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
52 {
53 if (response == nullptr || !respMsgLen)
54 {
55 error(
56 "No response received for query device identifiers for endpoint ID '{EID}'",
57 "EID", eid);
58 return;
59 }
60
61 uint8_t completionCode = PLDM_SUCCESS;
62 uint32_t deviceIdentifiersLen = 0;
63 uint8_t descriptorCount = 0;
64 uint8_t* descriptorPtr = nullptr;
65
66 auto rc = decode_query_device_identifiers_resp(
67 response, respMsgLen, &completionCode, &deviceIdentifiersLen,
68 &descriptorCount, &descriptorPtr);
69 if (rc)
70 {
71 error(
72 "Failed to decode query device identifiers response for endpoint ID '{EID}' and descriptor count '{DESCRIPTOR_COUNT}', response code '{RC}'",
73 "EID", eid, "DESCRIPTOR_COUNT", descriptorCount, "RC", rc);
74 return;
75 }
76
77 if (completionCode)
78 {
79 error(
80 "Failed to query device identifiers response for endpoint ID '{EID}', completion code '{CC}'",
81 "EID", eid, "CC", completionCode);
82 return;
83 }
84
85 Descriptors descriptors{};
86 while (descriptorCount-- && (deviceIdentifiersLen > 0))
87 {
88 uint16_t descriptorType = 0;
89 variable_field descriptorData{};
90
91 rc = decode_descriptor_type_length_value(
92 descriptorPtr, deviceIdentifiersLen, &descriptorType,
93 &descriptorData);
94 if (rc)
95 {
96 error(
97 "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID '{EID}', response code '{RC}'",
98 "TYPE", descriptorType, "LENGTH", deviceIdentifiersLen, "EID",
99 eid, "RC", rc);
100 return;
101 }
102
103 if (descriptorType != PLDM_FWUP_VENDOR_DEFINED)
104 {
105 std::vector<uint8_t> descData(
106 descriptorData.ptr, descriptorData.ptr + descriptorData.length);
107 descriptors.emplace(descriptorType, std::move(descData));
108 }
109 else
110 {
111 uint8_t descriptorTitleStrType = 0;
112 variable_field descriptorTitleStr{};
113 variable_field vendorDefinedDescriptorData{};
114
115 rc = decode_vendor_defined_descriptor_value(
116 descriptorData.ptr, descriptorData.length,
117 &descriptorTitleStrType, &descriptorTitleStr,
118 &vendorDefinedDescriptorData);
119 if (rc)
120 {
121 error(
122 "Failed to decode vendor-defined descriptor value for endpoint ID '{EID}', response code '{RC}'",
123 "EID", eid, "RC", rc);
124 return;
125 }
126
127 auto vendorDefinedDescriptorTitleStr =
128 utils::toString(descriptorTitleStr);
129 std::vector<uint8_t> vendorDescData(
130 vendorDefinedDescriptorData.ptr,
131 vendorDefinedDescriptorData.ptr +
132 vendorDefinedDescriptorData.length);
133 descriptors.emplace(descriptorType,
134 std::make_tuple(vendorDefinedDescriptorTitleStr,
135 vendorDescData));
136 }
137 auto nextDescriptorOffset =
138 sizeof(pldm_descriptor_tlv().descriptor_type) +
139 sizeof(pldm_descriptor_tlv().descriptor_length) +
140 descriptorData.length;
141 descriptorPtr += nextDescriptorOffset;
142 deviceIdentifiersLen -= nextDescriptorOffset;
143 }
144
145 descriptorMap.emplace(eid, std::move(descriptors));
146
147 // Send GetFirmwareParameters request
148 sendGetFirmwareParametersRequest(eid);
149 }
150
sendGetFirmwareParametersRequest(mctp_eid_t eid)151 void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid)
152 {
153 auto instanceId = instanceIdDb.next(eid);
154 Request requestMsg(
155 sizeof(pldm_msg_hdr) + PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES);
156 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
157 auto rc = encode_get_firmware_parameters_req(
158 instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request);
159 if (rc)
160 {
161 instanceIdDb.free(eid, instanceId);
162 error(
163 "Failed to encode get firmware parameters req for endpoint ID '{EID}', response code '{RC}'",
164 "EID", eid, "RC", rc);
165 return;
166 }
167
168 rc = handler.registerRequest(
169 eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS,
170 std::move(requestMsg),
171 std::bind_front(&InventoryManager::getFirmwareParameters, this));
172 if (rc)
173 {
174 error(
175 "Failed to send get firmware parameters request for endpoint ID '{EID}', response code '{RC}'",
176 "EID", eid, "RC", rc);
177 }
178 }
179
getFirmwareParameters(mctp_eid_t eid,const pldm_msg * response,size_t respMsgLen)180 void InventoryManager::getFirmwareParameters(
181 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
182 {
183 if (response == nullptr || !respMsgLen)
184 {
185 error(
186 "No response received for get firmware parameters for endpoint ID '{EID}'",
187 "EID", eid);
188 descriptorMap.erase(eid);
189 return;
190 }
191
192 pldm_get_firmware_parameters_resp fwParams{};
193 variable_field activeCompImageSetVerStr{};
194 variable_field pendingCompImageSetVerStr{};
195 variable_field compParamTable{};
196
197 auto rc = decode_get_firmware_parameters_resp(
198 response, respMsgLen, &fwParams, &activeCompImageSetVerStr,
199 &pendingCompImageSetVerStr, &compParamTable);
200 if (rc)
201 {
202 error(
203 "Failed to decode get firmware parameters response for endpoint ID '{EID}', response code '{RC}'",
204 "EID", eid, "RC", rc);
205 return;
206 }
207
208 if (fwParams.completion_code)
209 {
210 auto fw_param_cc = fwParams.completion_code;
211 error(
212 "Failed to get firmware parameters response for endpoint ID '{EID}', completion code '{CC}'",
213 "EID", eid, "CC", fw_param_cc);
214 return;
215 }
216
217 auto compParamPtr = compParamTable.ptr;
218 auto compParamTableLen = compParamTable.length;
219 pldm_component_parameter_entry compEntry{};
220 variable_field activeCompVerStr{};
221 variable_field pendingCompVerStr{};
222
223 ComponentInfo componentInfo{};
224 while (fwParams.comp_count-- && (compParamTableLen > 0))
225 {
226 auto rc = decode_get_firmware_parameters_resp_comp_entry(
227 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr,
228 &pendingCompVerStr);
229 if (rc)
230 {
231 error(
232 "Failed to decode component parameter table entry for endpoint ID '{EID}', response code '{RC}'",
233 "EID", eid, "RC", rc);
234 return;
235 }
236
237 auto compClassification = compEntry.comp_classification;
238 auto compIdentifier = compEntry.comp_identifier;
239 componentInfo.emplace(
240 std::make_pair(compClassification, compIdentifier),
241 compEntry.comp_classification_index);
242 compParamPtr += sizeof(pldm_component_parameter_entry) +
243 activeCompVerStr.length + pendingCompVerStr.length;
244 compParamTableLen -= sizeof(pldm_component_parameter_entry) +
245 activeCompVerStr.length + pendingCompVerStr.length;
246 }
247 componentInfoMap.emplace(eid, std::move(componentInfo));
248 }
249
250 } // namespace fw_update
251
252 } // namespace pldm
253