xref: /openbmc/pldm/fw-update/device_updater.cpp (revision c453e164)
1 #include "device_updater.hpp"
2 
3 #include "activation.hpp"
4 #include "update_manager.hpp"
5 
6 #include <libpldm/firmware_update.h>
7 
8 #include <functional>
9 
10 namespace pldm
11 {
12 
13 namespace fw_update
14 {
15 
16 void DeviceUpdater::startFwUpdateFlow()
17 {
18     auto instanceId = updateManager->requester.getInstanceId(eid);
19     // NumberOfComponents
20     const auto& applicableComponents =
21         std::get<ApplicableComponents>(fwDeviceIDRecord);
22     // PackageDataLength
23     const auto& fwDevicePkgData =
24         std::get<FirmwareDevicePackageData>(fwDeviceIDRecord);
25     // ComponentImageSetVersionString
26     const auto& compImageSetVersion =
27         std::get<ComponentImageSetVersion>(fwDeviceIDRecord);
28     variable_field compImgSetVerStrInfo{};
29     compImgSetVerStrInfo.ptr =
30         reinterpret_cast<const uint8_t*>(compImageSetVersion.data());
31     compImgSetVerStrInfo.length =
32         static_cast<uint8_t>(compImageSetVersion.size());
33 
34     Request request(sizeof(pldm_msg_hdr) +
35                     sizeof(struct pldm_request_update_req) +
36                     compImgSetVerStrInfo.length);
37     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
38 
39     auto rc = encode_request_update_req(
40         instanceId, maxTransferSize, applicableComponents.size(),
41         PLDM_FWUP_MIN_OUTSTANDING_REQ, fwDevicePkgData.size(),
42         PLDM_STR_TYPE_ASCII, compImgSetVerStrInfo.length, &compImgSetVerStrInfo,
43         requestMsg,
44         sizeof(struct pldm_request_update_req) + compImgSetVerStrInfo.length);
45     if (rc)
46     {
47         updateManager->requester.markFree(eid, instanceId);
48         std::cerr << "encode_request_update_req failed, EID=" << unsigned(eid)
49                   << ", RC=" << rc << "\n";
50         // Handle error scenario
51     }
52 
53     rc = updateManager->handler.registerRequest(
54         eid, instanceId, PLDM_FWUP, PLDM_REQUEST_UPDATE, std::move(request),
55         std::move(std::bind_front(&DeviceUpdater::requestUpdate, this)));
56     if (rc)
57     {
58         std::cerr << "Failed to send RequestUpdate request, EID="
59                   << unsigned(eid) << ", RC=" << rc << "\n ";
60         // Handle error scenario
61     }
62 }
63 
64 void DeviceUpdater::requestUpdate(mctp_eid_t eid, const pldm_msg* response,
65                                   size_t respMsgLen)
66 {
67     if (response == nullptr || !respMsgLen)
68     {
69         // Handle error scenario
70         std::cerr << "No response received for RequestUpdate, EID="
71                   << unsigned(eid) << "\n";
72         return;
73     }
74 
75     uint8_t completionCode = 0;
76     uint16_t fdMetaDataLen = 0;
77     uint8_t fdWillSendPkgData = 0;
78 
79     auto rc = decode_request_update_resp(response, respMsgLen, &completionCode,
80                                          &fdMetaDataLen, &fdWillSendPkgData);
81     if (rc)
82     {
83         std::cerr << "Decoding RequestUpdate response failed, EID="
84                   << unsigned(eid) << ", RC=" << rc << "\n";
85         return;
86     }
87     if (completionCode)
88     {
89         std::cerr << "RequestUpdate response failed with error "
90                      "completion code, EID="
91                   << unsigned(eid) << ", CC=" << unsigned(completionCode)
92                   << "\n";
93         return;
94     }
95 
96     // Optional fields DeviceMetaData and GetPackageData not handled
97     pldmRequest = std::make_unique<sdeventplus::source::Defer>(
98         updateManager->event,
99         std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
100                   componentIndex));
101 }
102 
103 void DeviceUpdater::sendPassCompTableRequest(size_t offset)
104 {
105     pldmRequest.reset();
106 
107     auto instanceId = updateManager->requester.getInstanceId(eid);
108     // TransferFlag
109     const auto& applicableComponents =
110         std::get<ApplicableComponents>(fwDeviceIDRecord);
111     uint8_t transferFlag = 0;
112     if (applicableComponents.size() == 1)
113     {
114         transferFlag = PLDM_START_AND_END;
115     }
116     else if (offset == 0)
117     {
118         transferFlag = PLDM_START;
119     }
120     else if (offset == applicableComponents.size() - 1)
121     {
122         transferFlag = PLDM_END;
123     }
124     else
125     {
126         transferFlag = PLDM_MIDDLE;
127     }
128     const auto& comp = compImageInfos[applicableComponents[offset]];
129     // ComponentClassification
130     CompClassification compClassification = std::get<static_cast<size_t>(
131         ComponentImageInfoPos::CompClassificationPos)>(comp);
132     // ComponentIdentifier
133     CompIdentifier compIdentifier =
134         std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
135             comp);
136     // ComponentClassificationIndex
137     CompClassificationIndex compClassificationIndex{};
138     auto compKey = std::make_pair(compClassification, compIdentifier);
139     if (compInfo.contains(compKey))
140     {
141         auto search = compInfo.find(compKey);
142         compClassificationIndex = search->second;
143     }
144     else
145     {
146         // Handle error scenario
147     }
148     // ComponentComparisonStamp
149     CompComparisonStamp compComparisonStamp = std::get<static_cast<size_t>(
150         ComponentImageInfoPos::CompComparisonStampPos)>(comp);
151     // ComponentVersionString
152     const auto& compVersion =
153         std::get<static_cast<size_t>(ComponentImageInfoPos::CompVersionPos)>(
154             comp);
155     variable_field compVerStrInfo{};
156     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
157     compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
158 
159     Request request(sizeof(pldm_msg_hdr) +
160                     sizeof(struct pldm_pass_component_table_req) +
161                     compVerStrInfo.length);
162     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
163     auto rc = encode_pass_component_table_req(
164         instanceId, transferFlag, compClassification, compIdentifier,
165         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
166         compVerStrInfo.length, &compVerStrInfo, requestMsg,
167         sizeof(pldm_pass_component_table_req) + compVerStrInfo.length);
168     if (rc)
169     {
170         updateManager->requester.markFree(eid, instanceId);
171         std::cerr << "encode_pass_component_table_req failed, EID="
172                   << unsigned(eid) << ", RC=" << rc << "\n";
173         // Handle error scenario
174     }
175 
176     rc = updateManager->handler.registerRequest(
177         eid, instanceId, PLDM_FWUP, PLDM_PASS_COMPONENT_TABLE,
178         std::move(request),
179         std::move(std::bind_front(&DeviceUpdater::passCompTable, this)));
180     if (rc)
181     {
182         std::cerr << "Failed to send PassComponentTable request, EID="
183                   << unsigned(eid) << ", RC=" << rc << "\n ";
184         // Handle error scenario
185     }
186 }
187 
188 void DeviceUpdater::passCompTable(mctp_eid_t eid, const pldm_msg* response,
189                                   size_t respMsgLen)
190 {
191     if (response == nullptr || !respMsgLen)
192     {
193         // Handle error scenario
194         std::cerr << "No response received for PassComponentTable, EID="
195                   << unsigned(eid) << "\n";
196         return;
197     }
198 
199     uint8_t completionCode = 0;
200     uint8_t compResponse = 0;
201     uint8_t compResponseCode = 0;
202 
203     auto rc =
204         decode_pass_component_table_resp(response, respMsgLen, &completionCode,
205                                          &compResponse, &compResponseCode);
206     if (rc)
207     {
208         // Handle error scenario
209         std::cerr << "Decoding PassComponentTable response failed, EID="
210                   << unsigned(eid) << ", RC=" << rc << "\n";
211         return;
212     }
213     if (completionCode)
214     {
215         // Handle error scenario
216         std::cerr << "PassComponentTable response failed with error "
217                      "completion code, EID="
218                   << unsigned(eid) << ", CC=" << unsigned(completionCode)
219                   << "\n";
220         return;
221     }
222     // Handle ComponentResponseCode
223 
224     const auto& applicableComponents =
225         std::get<ApplicableComponents>(fwDeviceIDRecord);
226     if (componentIndex == applicableComponents.size() - 1)
227     {
228         componentIndex = 0;
229         pldmRequest = std::make_unique<sdeventplus::source::Defer>(
230             updateManager->event,
231             std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
232                       componentIndex));
233     }
234     else
235     {
236         componentIndex++;
237         pldmRequest = std::make_unique<sdeventplus::source::Defer>(
238             updateManager->event,
239             std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
240                       componentIndex));
241     }
242 }
243 
244 void DeviceUpdater::sendUpdateComponentRequest(size_t offset)
245 {
246     pldmRequest.reset();
247 
248     auto instanceId = updateManager->requester.getInstanceId(eid);
249     const auto& applicableComponents =
250         std::get<ApplicableComponents>(fwDeviceIDRecord);
251     const auto& comp = compImageInfos[applicableComponents[offset]];
252     // ComponentClassification
253     CompClassification compClassification = std::get<static_cast<size_t>(
254         ComponentImageInfoPos::CompClassificationPos)>(comp);
255     // ComponentIdentifier
256     CompIdentifier compIdentifier =
257         std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>(
258             comp);
259     // ComponentClassificationIndex
260     CompClassificationIndex compClassificationIndex{};
261     auto compKey = std::make_pair(compClassification, compIdentifier);
262     if (compInfo.contains(compKey))
263     {
264         auto search = compInfo.find(compKey);
265         compClassificationIndex = search->second;
266     }
267     else
268     {
269         // Handle error scenario
270     }
271 
272     // UpdateOptionFlags
273     bitfield32_t updateOptionFlags;
274     updateOptionFlags.bits.bit0 = std::get<3>(comp)[0];
275     // ComponentVersion
276     const auto& compVersion = std::get<7>(comp);
277     variable_field compVerStrInfo{};
278     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data());
279     compVerStrInfo.length = static_cast<uint8_t>(compVersion.size());
280 
281     Request request(sizeof(pldm_msg_hdr) +
282                     sizeof(struct pldm_update_component_req) +
283                     compVerStrInfo.length);
284     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
285 
286     auto rc = encode_update_component_req(
287         instanceId, compClassification, compIdentifier, compClassificationIndex,
288         std::get<static_cast<size_t>(
289             ComponentImageInfoPos::CompComparisonStampPos)>(comp),
290         std::get<static_cast<size_t>(ComponentImageInfoPos::CompSizePos)>(comp),
291         updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrInfo.length,
292         &compVerStrInfo, requestMsg,
293         sizeof(pldm_update_component_req) + compVerStrInfo.length);
294     if (rc)
295     {
296         updateManager->requester.markFree(eid, instanceId);
297         std::cerr << "encode_update_component_req failed, EID=" << unsigned(eid)
298                   << ", RC=" << rc << "\n";
299         // Handle error scenario
300     }
301 
302     rc = updateManager->handler.registerRequest(
303         eid, instanceId, PLDM_FWUP, PLDM_UPDATE_COMPONENT, std::move(request),
304         std::move(std::bind_front(&DeviceUpdater::updateComponent, this)));
305     if (rc)
306     {
307         std::cerr << "Failed to send UpdateComponent request, EID="
308                   << unsigned(eid) << ", RC=" << rc << "\n ";
309         // Handle error scenario
310     }
311 }
312 
313 void DeviceUpdater::updateComponent(mctp_eid_t eid, const pldm_msg* response,
314                                     size_t respMsgLen)
315 {
316     if (response == nullptr || !respMsgLen)
317     {
318         // Handle error scenario
319         std::cerr << "No response received for updateComponent, EID="
320                   << unsigned(eid) << "\n";
321         return;
322     }
323 
324     uint8_t completionCode = 0;
325     uint8_t compCompatibilityResp = 0;
326     uint8_t compCompatibilityRespCode = 0;
327     bitfield32_t updateOptionFlagsEnabled{};
328     uint16_t timeBeforeReqFWData = 0;
329 
330     auto rc = decode_update_component_resp(
331         response, respMsgLen, &completionCode, &compCompatibilityResp,
332         &compCompatibilityRespCode, &updateOptionFlagsEnabled,
333         &timeBeforeReqFWData);
334     if (rc)
335     {
336         std::cerr << "Decoding UpdateComponent response failed, EID="
337                   << unsigned(eid) << ", RC=" << rc << "\n";
338         return;
339     }
340     if (completionCode)
341     {
342         std::cerr << "UpdateComponent response failed with error "
343                      "completion code, EID="
344                   << unsigned(eid) << ", CC=" << unsigned(completionCode)
345                   << "\n";
346         return;
347     }
348 }
349 
350 Response DeviceUpdater::requestFwData(const pldm_msg* request,
351                                       size_t payloadLength)
352 {
353     uint8_t completionCode = PLDM_SUCCESS;
354     uint32_t offset = 0;
355     uint32_t length = 0;
356     Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
357     auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
358     auto rc = decode_request_firmware_data_req(request, payloadLength, &offset,
359                                                &length);
360     if (rc)
361     {
362         std::cerr << "Decoding RequestFirmwareData request failed, EID="
363                   << unsigned(eid) << ", RC=" << rc << "\n";
364         rc = encode_request_firmware_data_resp(
365             request->hdr.instance_id, PLDM_ERROR_INVALID_DATA, responseMsg,
366             sizeof(completionCode));
367         if (rc)
368         {
369             std::cerr << "Encoding RequestFirmwareData response failed, EID="
370                       << unsigned(eid) << ", RC=" << rc << "\n";
371         }
372         return response;
373     }
374 
375     const auto& applicableComponents =
376         std::get<ApplicableComponents>(fwDeviceIDRecord);
377     const auto& comp = compImageInfos[applicableComponents[componentIndex]];
378     auto compOffset = std::get<5>(comp);
379     auto compSize = std::get<6>(comp);
380     std::cerr << "offset = " << unsigned(offset)
381               << ", length = " << unsigned(length) << "\n";
382 
383     if (length < PLDM_FWUP_BASELINE_TRANSFER_SIZE || length > maxTransferSize)
384     {
385         rc = encode_request_firmware_data_resp(
386             request->hdr.instance_id, PLDM_FWUP_INVALID_TRANSFER_LENGTH,
387             responseMsg, sizeof(completionCode));
388         if (rc)
389         {
390             std::cerr << "Encoding RequestFirmwareData response failed, EID="
391                       << unsigned(eid) << ", RC=" << rc << "\n";
392         }
393         return response;
394     }
395 
396     if (offset + length > compSize + PLDM_FWUP_BASELINE_TRANSFER_SIZE)
397     {
398         rc = encode_request_firmware_data_resp(
399             request->hdr.instance_id, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg,
400             sizeof(completionCode));
401         if (rc)
402         {
403             std::cerr << "Encoding RequestFirmwareData response failed, EID="
404                       << unsigned(eid) << ", RC=" << rc << "\n";
405         }
406         return response;
407     }
408 
409     size_t padBytes = 0;
410     if (offset + length > compSize)
411     {
412         padBytes = offset + length - compSize;
413     }
414 
415     response.resize(sizeof(pldm_msg_hdr) + sizeof(completionCode) + length);
416     responseMsg = reinterpret_cast<pldm_msg*>(response.data());
417     package.seekg(compOffset + offset);
418     package.read(reinterpret_cast<char*>(response.data() +
419                                          sizeof(pldm_msg_hdr) +
420                                          sizeof(completionCode)),
421                  length - padBytes);
422     rc = encode_request_firmware_data_resp(request->hdr.instance_id,
423                                            completionCode, responseMsg,
424                                            sizeof(completionCode));
425     if (rc)
426     {
427         std::cerr << "Encoding RequestFirmwareData response failed, EID="
428                   << unsigned(eid) << ", RC=" << rc << "\n";
429         return response;
430     }
431 
432     return response;
433 }
434 
435 Response DeviceUpdater::transferComplete(const pldm_msg* request,
436                                          size_t payloadLength)
437 {
438     uint8_t completionCode = PLDM_SUCCESS;
439     Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
440     auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
441 
442     uint8_t transferResult = 0;
443     auto rc =
444         decode_transfer_complete_req(request, payloadLength, &transferResult);
445     if (rc)
446     {
447         std::cerr << "Decoding TransferComplete request failed, EID="
448                   << unsigned(eid) << ", RC=" << rc << "\n";
449         rc = encode_transfer_complete_resp(request->hdr.instance_id,
450                                            PLDM_ERROR_INVALID_DATA, responseMsg,
451                                            sizeof(completionCode));
452         if (rc)
453         {
454             std::cerr << "Encoding TransferComplete response failed, EID="
455                       << unsigned(eid) << ", RC=" << rc << "\n";
456         }
457         return response;
458     }
459 
460     const auto& applicableComponents =
461         std::get<ApplicableComponents>(fwDeviceIDRecord);
462     const auto& comp = compImageInfos[applicableComponents[componentIndex]];
463     const auto& compVersion = std::get<7>(comp);
464 
465     if (transferResult == PLDM_FWUP_TRANSFER_SUCCESS)
466     {
467         std::cout << "Component Transfer complete, EID=" << unsigned(eid)
468                   << ", COMPONENT_VERSION=" << compVersion << "\n";
469     }
470     else
471     {
472         std::cerr << "Transfer of the component failed, EID=" << unsigned(eid)
473                   << ", COMPONENT_VERSION=" << compVersion
474                   << ", TRANSFER_RESULT=" << unsigned(transferResult) << "\n";
475     }
476 
477     rc = encode_transfer_complete_resp(request->hdr.instance_id, completionCode,
478                                        responseMsg, sizeof(completionCode));
479     if (rc)
480     {
481         std::cerr << "Encoding TransferComplete response failed, EID="
482                   << unsigned(eid) << ", RC=" << rc << "\n";
483         return response;
484     }
485 
486     return response;
487 }
488 
489 Response DeviceUpdater::verifyComplete(const pldm_msg* request,
490                                        size_t payloadLength)
491 {
492     uint8_t completionCode = PLDM_SUCCESS;
493     Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
494     auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
495 
496     uint8_t verifyResult = 0;
497     auto rc = decode_verify_complete_req(request, payloadLength, &verifyResult);
498     if (rc)
499     {
500         std::cerr << "Decoding VerifyComplete request failed, EID="
501                   << unsigned(eid) << ", RC=" << rc << "\n";
502         rc = encode_verify_complete_resp(request->hdr.instance_id,
503                                          PLDM_ERROR_INVALID_DATA, responseMsg,
504                                          sizeof(completionCode));
505         if (rc)
506         {
507             std::cerr << "Encoding VerifyComplete response failed, EID="
508                       << unsigned(eid) << ", RC=" << rc << "\n";
509         }
510         return response;
511     }
512 
513     const auto& applicableComponents =
514         std::get<ApplicableComponents>(fwDeviceIDRecord);
515     const auto& comp = compImageInfos[applicableComponents[componentIndex]];
516     const auto& compVersion = std::get<7>(comp);
517 
518     if (verifyResult == PLDM_FWUP_VERIFY_SUCCESS)
519     {
520         std::cout << "Component verification complete, EID=" << unsigned(eid)
521                   << ", COMPONENT_VERSION=" << compVersion << "\n";
522     }
523     else
524     {
525         std::cerr << "Component verification failed, EID=" << unsigned(eid)
526                   << ", COMPONENT_VERSION=" << compVersion
527                   << ", VERIFY_RESULT=" << unsigned(verifyResult) << "\n";
528     }
529 
530     rc = encode_verify_complete_resp(request->hdr.instance_id, completionCode,
531                                      responseMsg, sizeof(completionCode));
532     if (rc)
533     {
534         std::cerr << "Encoding VerifyComplete response failed, EID="
535                   << unsigned(eid) << ", RC=" << rc << "\n";
536         return response;
537     }
538 
539     return response;
540 }
541 
542 Response DeviceUpdater::applyComplete(const pldm_msg* request,
543                                       size_t payloadLength)
544 {
545     uint8_t completionCode = PLDM_SUCCESS;
546     Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0);
547     auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
548 
549     uint8_t applyResult = 0;
550     bitfield16_t compActivationModification{};
551     auto rc = decode_apply_complete_req(request, payloadLength, &applyResult,
552                                         &compActivationModification);
553     if (rc)
554     {
555         std::cerr << "Decoding ApplyComplete request failed, EID="
556                   << unsigned(eid) << ", RC=" << rc << "\n";
557         rc = encode_apply_complete_resp(request->hdr.instance_id,
558                                         PLDM_ERROR_INVALID_DATA, responseMsg,
559                                         sizeof(completionCode));
560         if (rc)
561         {
562             std::cerr << "Encoding ApplyComplete response failed, EID="
563                       << unsigned(eid) << ", RC=" << rc << "\n";
564         }
565         return response;
566     }
567 
568     const auto& applicableComponents =
569         std::get<ApplicableComponents>(fwDeviceIDRecord);
570     const auto& comp = compImageInfos[applicableComponents[componentIndex]];
571     const auto& compVersion = std::get<7>(comp);
572 
573     if (applyResult == PLDM_FWUP_APPLY_SUCCESS ||
574         applyResult == PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD)
575     {
576         std::cout << "Component apply complete, EID=" << unsigned(eid)
577                   << ", COMPONENT_VERSION=" << compVersion << "\n";
578         updateManager->updateActivationProgress();
579     }
580     else
581     {
582         std::cerr << "Component apply failed, EID=" << unsigned(eid)
583                   << ", COMPONENT_VERSION=" << compVersion
584                   << ", APPLY_RESULT=" << unsigned(applyResult) << "\n";
585     }
586 
587     rc = encode_apply_complete_resp(request->hdr.instance_id, completionCode,
588                                     responseMsg, sizeof(completionCode));
589     if (rc)
590     {
591         std::cerr << "Encoding ApplyComplete response failed, EID="
592                   << unsigned(eid) << ", RC=" << rc << "\n";
593         return response;
594     }
595 
596     if (componentIndex == applicableComponents.size() - 1)
597     {
598         componentIndex = 0;
599         pldmRequest = std::make_unique<sdeventplus::source::Defer>(
600             updateManager->event,
601             std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this));
602     }
603     else
604     {
605         componentIndex++;
606         pldmRequest = std::make_unique<sdeventplus::source::Defer>(
607             updateManager->event,
608             std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
609                       componentIndex));
610     }
611 
612     return response;
613 }
614 
615 void DeviceUpdater::sendActivateFirmwareRequest()
616 {
617     pldmRequest.reset();
618     auto instanceId = updateManager->requester.getInstanceId(eid);
619     Request request(sizeof(pldm_msg_hdr) +
620                     sizeof(struct pldm_activate_firmware_req));
621     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
622 
623     auto rc = encode_activate_firmware_req(
624         instanceId, PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
625         sizeof(pldm_activate_firmware_req));
626     if (rc)
627     {
628         updateManager->requester.markFree(eid, instanceId);
629         std::cerr << "encode_activate_firmware_req failed, EID="
630                   << unsigned(eid) << ", RC=" << rc << "\n";
631     }
632 
633     rc = updateManager->handler.registerRequest(
634         eid, instanceId, PLDM_FWUP, PLDM_ACTIVATE_FIRMWARE, std::move(request),
635         std::move(std::bind_front(&DeviceUpdater::activateFirmware, this)));
636     if (rc)
637     {
638         std::cerr << "Failed to send ActivateFirmware request, EID="
639                   << unsigned(eid) << ", RC=" << rc << "\n ";
640     }
641 }
642 
643 void DeviceUpdater::activateFirmware(mctp_eid_t eid, const pldm_msg* response,
644                                      size_t respMsgLen)
645 {
646     if (response == nullptr || !respMsgLen)
647     {
648         // Handle error scenario
649         std::cerr << "No response received for ActivateFirmware, EID="
650                   << unsigned(eid) << "\n";
651         return;
652     }
653 
654     uint8_t completionCode = 0;
655     uint16_t estimatedTimeForActivation = 0;
656 
657     auto rc = decode_activate_firmware_resp(
658         response, respMsgLen, &completionCode, &estimatedTimeForActivation);
659     if (rc)
660     {
661         // Handle error scenario
662         std::cerr << "Decoding ActivateFirmware response failed, EID="
663                   << unsigned(eid) << ", RC=" << rc << "\n";
664         return;
665     }
666     if (completionCode)
667     {
668         // Handle error scenario
669         std::cerr << "ActivateFirmware response failed with error "
670                      "completion code, EID="
671                   << unsigned(eid) << ", CC=" << unsigned(completionCode)
672                   << "\n";
673         return;
674     }
675 
676     updateManager->updateDeviceCompletion(eid, true);
677 }
678 
679 } // namespace fw_update
680 
681 } // namespace pldm