blob: 9a46a15b8bcb354649e049092bff25ef4e479167 [file] [log] [blame]
Tom Josephef90b0d2021-08-17 07:12:49 -07001#include "device_updater.hpp"
2
3#include "libpldm/firmware_update.h"
4
Tom Joseph4d8d5772021-08-17 07:35:05 -07005#include "activation.hpp"
6#include "update_manager.hpp"
7
Tom Josephef90b0d2021-08-17 07:12:49 -07008#include <functional>
9
10namespace pldm
11{
12
13namespace fw_update
14{
15
16void DeviceUpdater::startFwUpdateFlow()
17{
Tom Josephb7e083e2021-10-26 15:10:03 +053018 auto instanceId = updateManager->requester.getInstanceId(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -070019 // 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 {
Tom Josephb7e083e2021-10-26 15:10:03 +053047 updateManager->requester.markFree(eid, instanceId);
Tom Josephef90b0d2021-08-17 07:12:49 -070048 std::cerr << "encode_request_update_req failed, EID=" << unsigned(eid)
49 << ", RC=" << rc << "\n";
50 // Handle error scenario
51 }
52
Tom Josephb7e083e2021-10-26 15:10:03 +053053 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -070054 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
64void 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>(
Tom Josephb7e083e2021-10-26 15:10:03 +053098 updateManager->event,
99 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
100 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700101}
102
103void DeviceUpdater::sendPassCompTableRequest(size_t offset)
104{
105 pldmRequest.reset();
106
Tom Josephb7e083e2021-10-26 15:10:03 +0530107 auto instanceId = updateManager->requester.getInstanceId(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700108 // 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 {
Tom Josephb7e083e2021-10-26 15:10:03 +0530170 updateManager->requester.markFree(eid, instanceId);
Tom Josephef90b0d2021-08-17 07:12:49 -0700171 std::cerr << "encode_pass_component_table_req failed, EID="
172 << unsigned(eid) << ", RC=" << rc << "\n";
173 // Handle error scenario
174 }
175
Tom Josephb7e083e2021-10-26 15:10:03 +0530176 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700177 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
188void 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>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530230 updateManager->event,
231 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
232 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700233 }
234 else
235 {
236 componentIndex++;
237 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530238 updateManager->event,
239 std::bind(&DeviceUpdater::sendPassCompTableRequest, this,
240 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700241 }
242}
243
244void DeviceUpdater::sendUpdateComponentRequest(size_t offset)
245{
246 pldmRequest.reset();
247
Tom Josephb7e083e2021-10-26 15:10:03 +0530248 auto instanceId = updateManager->requester.getInstanceId(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700249 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 {
Tom Josephb7e083e2021-10-26 15:10:03 +0530296 updateManager->requester.markFree(eid, instanceId);
Tom Josephef90b0d2021-08-17 07:12:49 -0700297 std::cerr << "encode_update_component_req failed, EID=" << unsigned(eid)
298 << ", RC=" << rc << "\n";
299 // Handle error scenario
300 }
301
Tom Josephb7e083e2021-10-26 15:10:03 +0530302 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700303 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
313void 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
350Response 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
435Response 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
489Response 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
542Response 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";
Tom Joseph4d8d5772021-08-17 07:35:05 -0700578 updateManager->updateActivationProgress();
Tom Josephef90b0d2021-08-17 07:12:49 -0700579 }
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>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530600 updateManager->event,
Tom Josephef90b0d2021-08-17 07:12:49 -0700601 std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this));
602 }
603 else
604 {
605 componentIndex++;
606 pldmRequest = std::make_unique<sdeventplus::source::Defer>(
Tom Josephb7e083e2021-10-26 15:10:03 +0530607 updateManager->event,
608 std::bind(&DeviceUpdater::sendUpdateComponentRequest, this,
609 componentIndex));
Tom Josephef90b0d2021-08-17 07:12:49 -0700610 }
611
612 return response;
613}
614
615void DeviceUpdater::sendActivateFirmwareRequest()
616{
617 pldmRequest.reset();
Tom Josephb7e083e2021-10-26 15:10:03 +0530618 auto instanceId = updateManager->requester.getInstanceId(eid);
Tom Josephef90b0d2021-08-17 07:12:49 -0700619 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 {
Tom Josephb7e083e2021-10-26 15:10:03 +0530628 updateManager->requester.markFree(eid, instanceId);
Tom Josephef90b0d2021-08-17 07:12:49 -0700629 std::cerr << "encode_activate_firmware_req failed, EID="
630 << unsigned(eid) << ", RC=" << rc << "\n";
631 }
632
Tom Josephb7e083e2021-10-26 15:10:03 +0530633 rc = updateManager->handler.registerRequest(
Tom Josephef90b0d2021-08-17 07:12:49 -0700634 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
643void 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 }
Tom Joseph4d8d5772021-08-17 07:35:05 -0700675
676 updateManager->updateDeviceCompletion(eid, true);
Tom Josephef90b0d2021-08-17 07:12:49 -0700677}
678
679} // namespace fw_update
680
681} // namespace pldm