blob: 6ad9f395e9d4baf3577e55d7b75b5382bb9704f6 [file] [log] [blame]
Tom Joseph75356c12021-06-20 03:52:40 -07001#include "inventory_manager.hpp"
2
Tom Joseph75356c12021-06-20 03:52:40 -07003#include "common/utils.hpp"
4#include "xyz/openbmc_project/Software/Version/server.hpp"
5
George Liuc453e162022-12-21 17:16:23 +08006#include <libpldm/firmware_update.h>
7
Riya Dixit49cfb132023-03-02 04:26:53 -06008#include <phosphor-logging/lg2.hpp>
9
Tom Joseph75356c12021-06-20 03:52:40 -070010#include <functional>
11
Riya Dixit49cfb132023-03-02 04:26:53 -060012PHOSPHOR_LOG2_USING;
13
Tom Joseph75356c12021-06-20 03:52:40 -070014namespace pldm
15{
Tom Joseph75356c12021-06-20 03:52:40 -070016namespace fw_update
17{
Unive Tien7ad45b42025-08-18 06:04:53 +000018void InventoryManager::discoverFDs(const MctpInfos& mctpInfos)
Tom Joseph75356c12021-06-20 03:52:40 -070019{
Unive Tien7ad45b42025-08-18 06:04:53 +000020 for (const auto& mctpInfo : mctpInfos)
Tom Joseph75356c12021-06-20 03:52:40 -070021 {
Unive Tien7ad45b42025-08-18 06:04:53 +000022 auto eid = std::get<pldm::eid>(mctpInfo);
Unive Tien8b169dc2024-11-25 09:34:39 +080023 try
Tom Joseph75356c12021-06-20 03:52:40 -070024 {
Unive Tien8b169dc2024-11-25 09:34:39 +080025 sendQueryDeviceIdentifiersRequest(eid);
Tom Joseph75356c12021-06-20 03:52:40 -070026 }
Unive Tien8b169dc2024-11-25 09:34:39 +080027 catch (const std::exception& e)
28 {
29 error(
Unive Tien863b09b2025-02-07 16:51:37 +080030 "Failed to discover file descriptors for endpoint ID {EID} with {ERROR}",
Unive Tien8b169dc2024-11-25 09:34:39 +080031 "EID", eid, "ERROR", e);
32 }
33 }
34}
Tom Joseph75356c12021-06-20 03:52:40 -070035
Unive Tien7ad45b42025-08-18 06:04:53 +000036void InventoryManager::removeFDs(const MctpInfos& mctpInfos)
37{
38 for (const auto& mctpInfo : mctpInfos)
39 {
40 auto eid = std::get<pldm::eid>(mctpInfo);
41 firmwareDeviceNameMap.erase(eid);
42 descriptorMap.erase(eid);
43 downstreamDescriptorMap.erase(eid);
44 componentInfoMap.erase(eid);
45 firmwareInventoryManager.deleteFirmwareEntry(eid);
46 }
47}
48
Unive Tien8b169dc2024-11-25 09:34:39 +080049void InventoryManager::sendQueryDeviceIdentifiersRequest(mctp_eid_t eid)
50{
ManojKiran Eda22bcb072025-07-11 23:49:43 +000051 auto instanceId = instanceIdDb.next(eid);
Unive Tien8b169dc2024-11-25 09:34:39 +080052 Request requestMsg(
53 sizeof(pldm_msg_hdr) + PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES);
54 auto request = new (requestMsg.data()) pldm_msg;
55 auto rc = encode_query_device_identifiers_req(
56 instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request);
57 if (rc)
58 {
59 instanceIdDb.free(eid, instanceId);
60 error(
61 "Failed to encode query device identifiers request for endpoint ID {EID} with response code {RC}",
62 "EID", eid, "RC", rc);
63 throw std::runtime_error(
64 "Failed to encode QueryDeviceIdentifiers request");
65 }
66
67 rc = handler.registerRequest(
68 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS,
69 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +080070 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
71 this->queryDeviceIdentifiers(eid, response, respMsgLen);
72 });
Unive Tien8b169dc2024-11-25 09:34:39 +080073 if (rc)
74 {
75 error(
76 "Failed to send query device identifiers request for endpoint ID {EID} with response code {RC}",
77 "EID", eid, "RC", rc);
78 throw std::runtime_error(
79 "Failed to send QueryDeviceIdentifiers request");
Tom Joseph75356c12021-06-20 03:52:40 -070080 }
81}
82
Patrick Williams16c2a0a2024-08-16 15:20:59 -040083void InventoryManager::queryDeviceIdentifiers(
84 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
Tom Joseph75356c12021-06-20 03:52:40 -070085{
86 if (response == nullptr || !respMsgLen)
87 {
Riya Dixit76f2c602024-03-28 07:34:12 -050088 error(
Unive Tien8b169dc2024-11-25 09:34:39 +080089 "No response received for query device identifiers for endpoint ID {EID}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050090 "EID", eid);
Tom Joseph75356c12021-06-20 03:52:40 -070091 return;
92 }
93
94 uint8_t completionCode = PLDM_SUCCESS;
95 uint32_t deviceIdentifiersLen = 0;
96 uint8_t descriptorCount = 0;
97 uint8_t* descriptorPtr = nullptr;
98
99 auto rc = decode_query_device_identifiers_resp(
100 response, respMsgLen, &completionCode, &deviceIdentifiersLen,
101 &descriptorCount, &descriptorPtr);
102 if (rc)
103 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600104 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800105 "Failed to decode query device identifiers response for endpoint ID {EID} and descriptor count {DESCRIPTOR_COUNT}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500106 "EID", eid, "DESCRIPTOR_COUNT", descriptorCount, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700107 return;
108 }
109
110 if (completionCode)
111 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600112 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800113 "Failed to query device identifiers response for endpoint ID {EID}, completion code {CC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500114 "EID", eid, "CC", completionCode);
Tom Joseph75356c12021-06-20 03:52:40 -0700115 return;
116 }
117
118 Descriptors descriptors{};
119 while (descriptorCount-- && (deviceIdentifiersLen > 0))
120 {
121 uint16_t descriptorType = 0;
122 variable_field descriptorData{};
123
124 rc = decode_descriptor_type_length_value(
125 descriptorPtr, deviceIdentifiersLen, &descriptorType,
126 &descriptorData);
127 if (rc)
128 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600129 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800130 "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID {EID}, response code {RC}",
Riya Dixit76f2c602024-03-28 07:34:12 -0500131 "TYPE", descriptorType, "LENGTH", deviceIdentifiersLen, "EID",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500132 eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700133 return;
134 }
135
136 if (descriptorType != PLDM_FWUP_VENDOR_DEFINED)
137 {
138 std::vector<uint8_t> descData(
139 descriptorData.ptr, descriptorData.ptr + descriptorData.length);
140 descriptors.emplace(descriptorType, std::move(descData));
141 }
142 else
143 {
144 uint8_t descriptorTitleStrType = 0;
145 variable_field descriptorTitleStr{};
146 variable_field vendorDefinedDescriptorData{};
147
148 rc = decode_vendor_defined_descriptor_value(
149 descriptorData.ptr, descriptorData.length,
150 &descriptorTitleStrType, &descriptorTitleStr,
151 &vendorDefinedDescriptorData);
152 if (rc)
153 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600154 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800155 "Failed to decode vendor-defined descriptor value for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500156 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700157 return;
158 }
159
160 auto vendorDefinedDescriptorTitleStr =
161 utils::toString(descriptorTitleStr);
162 std::vector<uint8_t> vendorDescData(
163 vendorDefinedDescriptorData.ptr,
164 vendorDefinedDescriptorData.ptr +
165 vendorDefinedDescriptorData.length);
166 descriptors.emplace(descriptorType,
167 std::make_tuple(vendorDefinedDescriptorTitleStr,
168 vendorDescData));
169 }
170 auto nextDescriptorOffset =
171 sizeof(pldm_descriptor_tlv().descriptor_type) +
172 sizeof(pldm_descriptor_tlv().descriptor_length) +
173 descriptorData.length;
174 descriptorPtr += nextDescriptorOffset;
175 deviceIdentifiersLen -= nextDescriptorOffset;
176 }
177
Unive Tien7ad45b42025-08-18 06:04:53 +0000178 obtainFirmwareDeviceName(eid, descriptors);
179 descriptorMap.insert_or_assign(eid, std::move(descriptors));
Tom Joseph75356c12021-06-20 03:52:40 -0700180
181 // Send GetFirmwareParameters request
182 sendGetFirmwareParametersRequest(eid);
183}
184
Unive Tien8b169dc2024-11-25 09:34:39 +0800185void InventoryManager::sendQueryDownstreamDevicesRequest(mctp_eid_t eid)
186{
187 Request requestMsg(sizeof(pldm_msg_hdr));
ManojKiran Eda22bcb072025-07-11 23:49:43 +0000188 auto instanceId = instanceIdDb.next(eid);
Unive Tien8b169dc2024-11-25 09:34:39 +0800189 auto request = new (requestMsg.data()) pldm_msg;
190 auto rc = encode_query_downstream_devices_req(instanceId, request);
191 if (rc)
192 {
193 instanceIdDb.free(eid, instanceId);
194 error(
195 "Failed to encode query downstream devices request for endpoint ID EID {EID} with response code {RC}",
196 "EID", eid, "RC", rc);
197 throw std::runtime_error(
198 "Failed to encode query downstream devices request");
199 }
200
201 rc = handler.registerRequest(
202 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_DEVICES,
203 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800204 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
205 this->queryDownstreamDevices(eid, response, respMsgLen);
206 });
Unive Tien8b169dc2024-11-25 09:34:39 +0800207 if (rc)
208 {
209 error(
210 "Failed to send QueryDownstreamDevices request for endpoint ID {EID} with response code {RC}",
211 "EID", eid, "RC", rc);
212 }
213}
214
215void InventoryManager::queryDownstreamDevices(
216 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
217{
218 if (!response || !respMsgLen)
219 {
220 error(
221 "No response received for QueryDownstreamDevices for endpoint ID {EID}",
222 "EID", eid);
223 return;
224 }
225
226 pldm_query_downstream_devices_resp downstreamDevicesResp{};
227 auto rc = decode_query_downstream_devices_resp(response, respMsgLen,
228 &downstreamDevicesResp);
229 if (rc)
230 {
231 error(
232 "Decoding QueryDownstreamDevices response failed for endpoint ID {EID} with response code {RC}",
233 "EID", eid, "RC", rc);
234 return;
235 }
236
237 switch (downstreamDevicesResp.completion_code)
238 {
239 case PLDM_SUCCESS:
240 break;
241 case PLDM_ERROR_UNSUPPORTED_PLDM_CMD:
242 /* QueryDownstreamDevices is optional, consider the device does not
243 * support Downstream Devices.
244 */
245 info("Endpoint ID {EID} does not support QueryDownstreamDevices",
246 "EID", eid);
247 return;
248 default:
249 error(
250 "QueryDownstreamDevices response failed with error completion code for endpoint ID {EID} with completion code {CC}",
251 "EID", eid, "CC", downstreamDevicesResp.completion_code);
252 return;
253 }
254
255 switch (downstreamDevicesResp.downstream_device_update_supported)
256 {
257 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
258 /** DataTransferHandle will be skipped when TransferOperationFlag is
259 * `GetFirstPart`. Use 0x0 as default by following example in
260 * Figure 9 in DSP0267 1.1.0
261 */
262 try
263 {
264 sendQueryDownstreamIdentifiersRequest(eid, 0x0,
265 PLDM_GET_FIRSTPART);
266 }
267 catch (const std::exception& e)
268 {
269 error(
270 "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with {ERROR}",
271 "EID", eid, "ERROR", e);
272 }
273 break;
274 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
275 /* The FDP does not support firmware updates but may report
276 * inventory information on downstream devices.
277 * In this scenario, sends only GetDownstreamFirmwareParameters
278 * to the FDP.
279 * The definition can be found at Table 15 of DSP0267_1.1.0
280 */
281 break;
282 default:
283 error(
284 "Unknown response of DownstreamDeviceUpdateSupported from endpoint ID {EID} with value {VALUE}",
285 "EID", eid, "VALUE",
286 downstreamDevicesResp.downstream_device_update_supported);
287 return;
288 }
289}
290
291void InventoryManager::sendQueryDownstreamIdentifiersRequest(
292 mctp_eid_t eid, uint32_t dataTransferHandle,
293 enum transfer_op_flag transferOperationFlag)
294{
ManojKiran Eda22bcb072025-07-11 23:49:43 +0000295 auto instanceId = instanceIdDb.next(eid);
Unive Tien8b169dc2024-11-25 09:34:39 +0800296 Request requestMsg(
297 sizeof(pldm_msg_hdr) + PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES);
298 auto request = new (requestMsg.data()) pldm_msg;
299 pldm_query_downstream_identifiers_req requestParameters{
300 dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)};
301
302 auto rc = encode_query_downstream_identifiers_req(
303 instanceId, &requestParameters, request,
304 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES);
305 if (rc)
306 {
307 instanceIdDb.free(eid, instanceId);
308 error(
309 "Failed to encode query downstream identifiers request for endpoint ID {EID} with response code {RC}",
310 "EID", eid, "RC", rc);
311 throw std::runtime_error(
312 "Failed to encode query downstream identifiers request");
313 }
314
315 rc = handler.registerRequest(
316 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS,
317 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800318 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
319 this->queryDownstreamIdentifiers(eid, response, respMsgLen);
320 });
Unive Tien8b169dc2024-11-25 09:34:39 +0800321 if (rc)
322 {
323 error(
324 "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with response code {RC}",
325 "EID", eid, "RC", rc);
326 }
327}
328
329void InventoryManager::queryDownstreamIdentifiers(
330 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
331{
332 if (!response || !respMsgLen)
333 {
334 error(
335 "No response received for QueryDownstreamIdentifiers for endpoint ID {EID}",
336 "EID", eid);
337 descriptorMap.erase(eid);
338 return;
339 }
340
341 pldm_query_downstream_identifiers_resp downstreamIds{};
342 pldm_downstream_device_iter devs{};
343
344 auto rc = decode_query_downstream_identifiers_resp(response, respMsgLen,
345 &downstreamIds, &devs);
346 if (rc)
347 {
348 error(
349 "Decoding QueryDownstreamIdentifiers response failed for endpoint ID {EID} with response code {RC}",
350 "EID", eid, "RC", rc);
351 return;
352 }
353
354 if (downstreamIds.completion_code)
355 {
356 error(
357 "QueryDownstreamIdentifiers response failed with error completion code for endpoint ID {EID} with completion code {CC}",
358 "EID", eid, "CC", unsigned(downstreamIds.completion_code));
359 return;
360 }
361
362 DownstreamDeviceInfo initialDownstreamDevices{};
363 DownstreamDeviceInfo* downstreamDevices;
364 if (!downstreamDescriptorMap.contains(eid) ||
365 downstreamIds.transfer_flag == PLDM_START ||
366 downstreamIds.transfer_flag == PLDM_START_AND_END)
367 {
368 downstreamDevices = &initialDownstreamDevices;
369 }
370 else
371 {
372 downstreamDevices = &downstreamDescriptorMap.at(eid);
373 }
374
375 pldm_downstream_device dev;
376 foreach_pldm_downstream_device(devs, dev, rc)
377 {
378 pldm_descriptor desc;
379 Descriptors descriptors{};
380 foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)
381 {
382 const auto descriptorData =
383 new (const_cast<void*>(desc.descriptor_data))
384 uint8_t[desc.descriptor_length];
385 if (desc.descriptor_type != PLDM_FWUP_VENDOR_DEFINED)
386 {
387 std::vector<uint8_t> descData(
388 descriptorData, descriptorData + desc.descriptor_length);
389 descriptors.emplace(desc.descriptor_type, std::move(descData));
390 }
391 else
392 {
393 uint8_t descriptorTitleStrType = 0;
394 variable_field descriptorTitleStr{};
395 variable_field vendorDefinedDescriptorData{};
396
397 rc = decode_vendor_defined_descriptor_value(
398 descriptorData, desc.descriptor_length,
399 &descriptorTitleStrType, &descriptorTitleStr,
400 &vendorDefinedDescriptorData);
401
402 if (rc)
403 {
404 error(
405 "Decoding Vendor-defined descriptor value failed for endpoint ID {EID} with response code {RC}",
406 "EID", eid, "RC", rc);
407 return;
408 }
409
410 auto vendorDefinedDescriptorTitleStr =
411 utils::toString(descriptorTitleStr);
412 std::vector<uint8_t> vendorDescData(
413 vendorDefinedDescriptorData.ptr,
414 vendorDefinedDescriptorData.ptr +
415 vendorDefinedDescriptorData.length);
416 descriptors.emplace(
417 desc.descriptor_type,
418 std::make_tuple(vendorDefinedDescriptorTitleStr,
419 vendorDescData));
420 }
421 }
422 if (rc)
423 {
424 error(
425 "Failed to decode downstream device descriptor for endpoint ID {EID} with response code {RC}",
426 "EID", eid, "RC", rc);
427 return;
428 }
429 downstreamDevices->emplace(dev.downstream_device_index, descriptors);
430 }
431 if (rc)
432 {
433 error(
434 "Failed to decode downstream devices from iterator for endpoint ID {EID} with response code {RC}",
435 "EID", eid, "RC", rc);
436 return;
437 }
438
439 switch (downstreamIds.transfer_flag)
440 {
441 case PLDM_START:
442 downstreamDescriptorMap.insert_or_assign(
443 eid, std::move(initialDownstreamDevices));
444 [[fallthrough]];
445 case PLDM_MIDDLE:
446 sendQueryDownstreamIdentifiersRequest(
447 eid, downstreamIds.next_data_transfer_handle,
448 PLDM_GET_NEXTPART);
449 break;
450 case PLDM_START_AND_END:
451 downstreamDescriptorMap.insert_or_assign(
452 eid, std::move(initialDownstreamDevices));
453 /** DataTransferHandle will be skipped when TransferOperationFlag is
454 * `GetFirstPart`. Use 0x0 as default by following example in
455 * Figure 9 in DSP0267 1.1.0
456 */
457 [[fallthrough]];
458 case PLDM_END:
459 sendGetDownstreamFirmwareParametersRequest(eid, 0x0,
460 PLDM_GET_FIRSTPART);
461 break;
462 }
463}
464
465void InventoryManager::sendGetDownstreamFirmwareParametersRequest(
466 mctp_eid_t eid, uint32_t dataTransferHandle,
467 enum transfer_op_flag transferOperationFlag)
468{
469 Request requestMsg(sizeof(pldm_msg_hdr) +
470 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES);
ManojKiran Eda22bcb072025-07-11 23:49:43 +0000471 auto instanceId = instanceIdDb.next(eid);
Unive Tien8b169dc2024-11-25 09:34:39 +0800472 auto request = new (requestMsg.data()) pldm_msg;
473 pldm_get_downstream_firmware_parameters_req requestParameters{
474 dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)};
475 auto rc = encode_get_downstream_firmware_parameters_req(
476 instanceId, &requestParameters, request,
477 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES);
478 if (rc)
479 {
480 instanceIdDb.free(eid, instanceId);
481 error(
482 "Failed to encode query downstream firmware parameters request for endpoint ID {EID} with response code {RC}",
483 "EID", eid, "RC", rc);
484 throw std::runtime_error(
485 "Failed to encode query downstream firmware parameters request");
486 }
487
488 rc = handler.registerRequest(
489 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS,
490 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800491 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
492 this->getDownstreamFirmwareParameters(eid, response, respMsgLen);
493 });
Unive Tien8b169dc2024-11-25 09:34:39 +0800494 if (rc)
495 {
496 error(
497 "Failed to send QueryDownstreamFirmwareParameters request for endpoint ID {EID} with response code {RC}",
498 "EID", eid, "RC", rc);
499 }
500}
501
502void InventoryManager::getDownstreamFirmwareParameters(
503 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
504{
505 if (!response || !respMsgLen)
506 {
507 error(
508 "No response received for QueryDownstreamFirmwareParameters for endpoint ID {EID}",
509 "EID", eid);
510 descriptorMap.erase(eid);
511 return;
512 }
513
514 pldm_get_downstream_firmware_parameters_resp resp{};
515 pldm_downstream_device_parameters_iter params{};
516 pldm_downstream_device_parameters_entry entry{};
517
518 auto rc = decode_get_downstream_firmware_parameters_resp(
519 response, respMsgLen, &resp, &params);
520
521 if (rc)
522 {
523 error(
524 "Decoding QueryDownstreamFirmwareParameters response failed for endpoint ID {EID} with response code {RC}",
525 "EID", eid, "RC", rc);
526 return;
527 }
528
529 if (resp.completion_code)
530 {
531 error(
532 "QueryDownstreamFirmwareParameters response failed with error completion code for endpoint ID {EID} with completion code {CC}",
533 "EID", eid, "CC", resp.completion_code);
534 return;
535 }
536
537 foreach_pldm_downstream_device_parameters_entry(params, entry, rc)
538 {
539 // Reserved for upcoming use
540 [[maybe_unused]] variable_field activeCompVerStr{
541 reinterpret_cast<const uint8_t*>(entry.active_comp_ver_str),
542 entry.active_comp_ver_str_len};
543 }
544 if (rc)
545 {
546 error(
547 "Failed to decode downstream device parameters from iterator for endpoint ID {EID} with response code {RC}",
548 "EID", eid, "RC", rc);
549 return;
550 }
551
552 switch (resp.transfer_flag)
553 {
554 case PLDM_START:
555 case PLDM_MIDDLE:
556 sendGetDownstreamFirmwareParametersRequest(
557 eid, resp.next_data_transfer_handle, PLDM_GET_NEXTPART);
558 break;
559 }
560}
561
Unive Tien7ad45b42025-08-18 06:04:53 +0000562void InventoryManager::obtainFirmwareDeviceName(pldm::eid eid,
563 const Descriptors& descriptors)
564{
565 auto firmwareDeviceName =
566 obtainDeviceNameFromConfigurations(configurations, eid);
567
568 if (!firmwareDeviceName)
569 {
570 firmwareDeviceName = obtainDeviceNameFromDescriptors(descriptors);
571 }
572
573 if (!firmwareDeviceName)
574 {
575 firmwareDeviceName = std::format("Firmware_Device_{}", eid);
576 }
577
578 firmwareDeviceNameMap.insert_or_assign(eid, *firmwareDeviceName);
579}
580
Tom Joseph75356c12021-06-20 03:52:40 -0700581void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid)
582{
ManojKiran Eda22bcb072025-07-11 23:49:43 +0000583 auto instanceId = instanceIdDb.next(eid);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400584 Request requestMsg(
585 sizeof(pldm_msg_hdr) + PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES);
Pavithra Barithaya1039a8a2025-01-31 11:30:14 +0530586 auto request = new (requestMsg.data()) pldm_msg;
Tom Joseph75356c12021-06-20 03:52:40 -0700587 auto rc = encode_get_firmware_parameters_req(
588 instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request);
589 if (rc)
590 {
Andrew Jefferya330b2f2023-05-04 14:55:37 +0930591 instanceIdDb.free(eid, instanceId);
Riya Dixit76f2c602024-03-28 07:34:12 -0500592 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800593 "Failed to encode get firmware parameters req for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500594 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700595 return;
596 }
597
598 rc = handler.registerRequest(
599 eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS,
600 std::move(requestMsg),
Eric Yang70eca962025-05-11 01:48:15 +0800601 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
602 this->getFirmwareParameters(eid, response, respMsgLen);
603 });
Tom Joseph75356c12021-06-20 03:52:40 -0700604 if (rc)
605 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600606 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800607 "Failed to send get firmware parameters request for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500608 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700609 }
610}
611
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400612void InventoryManager::getFirmwareParameters(
613 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
Tom Joseph75356c12021-06-20 03:52:40 -0700614{
615 if (response == nullptr || !respMsgLen)
616 {
Riya Dixit76f2c602024-03-28 07:34:12 -0500617 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800618 "No response received for get firmware parameters for endpoint ID {EID}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500619 "EID", eid);
Tom Joseph75356c12021-06-20 03:52:40 -0700620 descriptorMap.erase(eid);
621 return;
622 }
623
624 pldm_get_firmware_parameters_resp fwParams{};
625 variable_field activeCompImageSetVerStr{};
626 variable_field pendingCompImageSetVerStr{};
627 variable_field compParamTable{};
628
629 auto rc = decode_get_firmware_parameters_resp(
630 response, respMsgLen, &fwParams, &activeCompImageSetVerStr,
631 &pendingCompImageSetVerStr, &compParamTable);
632 if (rc)
633 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600634 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800635 "Failed to decode get firmware parameters response for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500636 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700637 return;
638 }
639
640 if (fwParams.completion_code)
641 {
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500642 auto fw_param_cc = fwParams.completion_code;
Riya Dixit49cfb132023-03-02 04:26:53 -0600643 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800644 "Failed to get firmware parameters response for endpoint ID {EID}, completion code {CC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500645 "EID", eid, "CC", fw_param_cc);
Tom Joseph75356c12021-06-20 03:52:40 -0700646 return;
647 }
648
649 auto compParamPtr = compParamTable.ptr;
650 auto compParamTableLen = compParamTable.length;
651 pldm_component_parameter_entry compEntry{};
652 variable_field activeCompVerStr{};
653 variable_field pendingCompVerStr{};
654
655 ComponentInfo componentInfo{};
656 while (fwParams.comp_count-- && (compParamTableLen > 0))
657 {
658 auto rc = decode_get_firmware_parameters_resp_comp_entry(
659 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr,
660 &pendingCompVerStr);
661 if (rc)
662 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600663 error(
Unive Tien8b169dc2024-11-25 09:34:39 +0800664 "Failed to decode component parameter table entry for endpoint ID {EID}, response code {RC}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500665 "EID", eid, "RC", rc);
Tom Joseph75356c12021-06-20 03:52:40 -0700666 return;
667 }
668
669 auto compClassification = compEntry.comp_classification;
670 auto compIdentifier = compEntry.comp_identifier;
671 componentInfo.emplace(
672 std::make_pair(compClassification, compIdentifier),
673 compEntry.comp_classification_index);
674 compParamPtr += sizeof(pldm_component_parameter_entry) +
675 activeCompVerStr.length + pendingCompVerStr.length;
676 compParamTableLen -= sizeof(pldm_component_parameter_entry) +
677 activeCompVerStr.length + pendingCompVerStr.length;
678 }
Unive Tien7ad45b42025-08-18 06:04:53 +0000679
680 if (firmwareDeviceNameMap.contains(eid))
681 {
682 firmwareInventoryManager.createFirmwareEntry(
683 SoftwareIdentifier(eid, 0), firmwareDeviceNameMap.at(eid),
684 utils::toString(activeCompImageSetVerStr), descriptorMap[eid],
685 componentInfo);
686 }
687 else
688 {
689 error("Firmware device name not found for endpoint ID {EID}", "EID",
690 eid);
691 }
692
693 componentInfoMap.insert_or_assign(eid, std::move(componentInfo));
694}
695
696std::optional<SoftwareName> obtainDeviceNameFromConfigurations(
697 const Configurations& configurations, pldm::eid eid)
698{
699 for (const auto& [_, mctpInfo] : configurations)
700 {
701 if (std::get<pldm::eid>(mctpInfo) == eid)
702 {
703 auto nameOption = std::get<std::optional<std::string>>(mctpInfo);
704 if (nameOption)
705 {
706 return *nameOption;
707 }
708 break;
709 }
710 }
711 return std::nullopt;
712}
713
714std::optional<SoftwareName> obtainDeviceNameFromDescriptors(
715 const Descriptors& descriptors)
716{
717 for (const auto& [descriptorType, descriptorData] : descriptors)
718 {
719 if (descriptorType == PLDM_FWUP_VENDOR_DEFINED)
720 {
721 auto vendorInfo =
722 std::get<VendorDefinedDescriptorInfo>(descriptorData);
723 auto title = std::get<VendorDefinedDescriptorTitle>(vendorInfo);
724 if (title == "OpenBMC.Name")
725 {
726 auto deviceNameData =
727 std::get<VendorDefinedDescriptorData>(vendorInfo);
728 return SoftwareName{
729 reinterpret_cast<char*>(deviceNameData.data()),
730 deviceNameData.size()};
731 }
732 }
733 }
734 return std::nullopt;
Tom Joseph75356c12021-06-20 03:52:40 -0700735}
736
737} // namespace fw_update
738
Riya Dixit49cfb132023-03-02 04:26:53 -0600739} // namespace pldm