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