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