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