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