xref: /openbmc/pldm/fw-update/inventory_manager.cpp (revision 7ad45b401134e3b3a05a75200dbba00afd5aee46)
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 MctpInfos & mctpInfos)18 void InventoryManager::discoverFDs(const MctpInfos& mctpInfos)
19 {
20     for (const auto& mctpInfo : mctpInfos)
21     {
22         auto eid = std::get<pldm::eid>(mctpInfo);
23         try
24         {
25             sendQueryDeviceIdentifiersRequest(eid);
26         }
27         catch (const std::exception& e)
28         {
29             error(
30                 "Failed to discover file descriptors for endpoint ID {EID} with {ERROR}",
31                 "EID", eid, "ERROR", e);
32         }
33     }
34 }
35 
removeFDs(const MctpInfos & mctpInfos)36 void 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 
sendQueryDeviceIdentifiersRequest(mctp_eid_t eid)49 void InventoryManager::sendQueryDeviceIdentifiersRequest(mctp_eid_t eid)
50 {
51     auto instanceId = instanceIdDb.next(eid);
52     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),
70         [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
71             this->queryDeviceIdentifiers(eid, response, respMsgLen);
72         });
73     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");
80     }
81 }
82 
queryDeviceIdentifiers(mctp_eid_t eid,const pldm_msg * response,size_t respMsgLen)83 void InventoryManager::queryDeviceIdentifiers(
84     mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
85 {
86     if (response == nullptr || !respMsgLen)
87     {
88         error(
89             "No response received for query device identifiers for endpoint ID {EID}",
90             "EID", eid);
91         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     {
104         error(
105             "Failed to decode query device identifiers response for endpoint ID {EID} and descriptor count {DESCRIPTOR_COUNT}, response code {RC}",
106             "EID", eid, "DESCRIPTOR_COUNT", descriptorCount, "RC", rc);
107         return;
108     }
109 
110     if (completionCode)
111     {
112         error(
113             "Failed to query device identifiers response for endpoint ID {EID}, completion code {CC}",
114             "EID", eid, "CC", completionCode);
115         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         {
129             error(
130                 "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID {EID}, response code {RC}",
131                 "TYPE", descriptorType, "LENGTH", deviceIdentifiersLen, "EID",
132                 eid, "RC", rc);
133             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             {
154                 error(
155                     "Failed to decode vendor-defined descriptor value for endpoint ID {EID}, response code {RC}",
156                     "EID", eid, "RC", rc);
157                 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 
178     obtainFirmwareDeviceName(eid, descriptors);
179     descriptorMap.insert_or_assign(eid, std::move(descriptors));
180 
181     // Send GetFirmwareParameters request
182     sendGetFirmwareParametersRequest(eid);
183 }
184 
sendQueryDownstreamDevicesRequest(mctp_eid_t eid)185 void InventoryManager::sendQueryDownstreamDevicesRequest(mctp_eid_t eid)
186 {
187     Request requestMsg(sizeof(pldm_msg_hdr));
188     auto instanceId = instanceIdDb.next(eid);
189     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),
204         [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
205             this->queryDownstreamDevices(eid, response, respMsgLen);
206         });
207     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 
queryDownstreamDevices(mctp_eid_t eid,const pldm_msg * response,size_t respMsgLen)215 void 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 
sendQueryDownstreamIdentifiersRequest(mctp_eid_t eid,uint32_t dataTransferHandle,enum transfer_op_flag transferOperationFlag)291 void InventoryManager::sendQueryDownstreamIdentifiersRequest(
292     mctp_eid_t eid, uint32_t dataTransferHandle,
293     enum transfer_op_flag transferOperationFlag)
294 {
295     auto instanceId = instanceIdDb.next(eid);
296     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),
318         [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
319             this->queryDownstreamIdentifiers(eid, response, respMsgLen);
320         });
321     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 
queryDownstreamIdentifiers(mctp_eid_t eid,const pldm_msg * response,size_t respMsgLen)329 void 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 
sendGetDownstreamFirmwareParametersRequest(mctp_eid_t eid,uint32_t dataTransferHandle,enum transfer_op_flag transferOperationFlag)465 void 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);
471     auto instanceId = instanceIdDb.next(eid);
472     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),
491         [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
492             this->getDownstreamFirmwareParameters(eid, response, respMsgLen);
493         });
494     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 
getDownstreamFirmwareParameters(mctp_eid_t eid,const pldm_msg * response,size_t respMsgLen)502 void 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 
obtainFirmwareDeviceName(pldm::eid eid,const Descriptors & descriptors)562 void 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 
sendGetFirmwareParametersRequest(mctp_eid_t eid)581 void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid)
582 {
583     auto instanceId = instanceIdDb.next(eid);
584     Request requestMsg(
585         sizeof(pldm_msg_hdr) + PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES);
586     auto request = new (requestMsg.data()) pldm_msg;
587     auto rc = encode_get_firmware_parameters_req(
588         instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request);
589     if (rc)
590     {
591         instanceIdDb.free(eid, instanceId);
592         error(
593             "Failed to encode get firmware parameters req for endpoint ID {EID}, response code {RC}",
594             "EID", eid, "RC", rc);
595         return;
596     }
597 
598     rc = handler.registerRequest(
599         eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS,
600         std::move(requestMsg),
601         [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) {
602             this->getFirmwareParameters(eid, response, respMsgLen);
603         });
604     if (rc)
605     {
606         error(
607             "Failed to send get firmware parameters request for endpoint ID {EID}, response code {RC}",
608             "EID", eid, "RC", rc);
609     }
610 }
611 
getFirmwareParameters(mctp_eid_t eid,const pldm_msg * response,size_t respMsgLen)612 void InventoryManager::getFirmwareParameters(
613     mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen)
614 {
615     if (response == nullptr || !respMsgLen)
616     {
617         error(
618             "No response received for get firmware parameters for endpoint ID {EID}",
619             "EID", eid);
620         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     {
634         error(
635             "Failed to decode get firmware parameters response for endpoint ID {EID}, response code {RC}",
636             "EID", eid, "RC", rc);
637         return;
638     }
639 
640     if (fwParams.completion_code)
641     {
642         auto fw_param_cc = fwParams.completion_code;
643         error(
644             "Failed to get firmware parameters response for endpoint ID {EID}, completion code {CC}",
645             "EID", eid, "CC", fw_param_cc);
646         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         {
663             error(
664                 "Failed to decode component parameter table entry for endpoint ID {EID}, response code {RC}",
665                 "EID", eid, "RC", rc);
666             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     }
679 
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 
obtainDeviceNameFromConfigurations(const Configurations & configurations,pldm::eid eid)696 std::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 
obtainDeviceNameFromDescriptors(const Descriptors & descriptors)714 std::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;
735 }
736 
737 } // namespace fw_update
738 
739 } // namespace pldm
740