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, ¶ms);
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