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( 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 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 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 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 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 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 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 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 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 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 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 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