| #include "device_updater.hpp" |
| |
| #include "activation.hpp" |
| #include "update_manager.hpp" |
| |
| #include <libpldm/firmware_update.h> |
| |
| #include <phosphor-logging/lg2.hpp> |
| |
| #include <functional> |
| |
| PHOSPHOR_LOG2_USING; |
| |
| namespace pldm |
| { |
| |
| namespace fw_update |
| { |
| |
| void DeviceUpdater::startFwUpdateFlow() |
| { |
| auto instanceId = updateManager->instanceIdDb.next(eid); |
| // NumberOfComponents |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| // PackageDataLength |
| const auto& fwDevicePkgData = |
| std::get<FirmwareDevicePackageData>(fwDeviceIDRecord); |
| // ComponentImageSetVersionString |
| const auto& compImageSetVersion = |
| std::get<ComponentImageSetVersion>(fwDeviceIDRecord); |
| variable_field compImgSetVerStrInfo{}; |
| compImgSetVerStrInfo.ptr = |
| reinterpret_cast<const uint8_t*>(compImageSetVersion.data()); |
| compImgSetVerStrInfo.length = |
| static_cast<uint8_t>(compImageSetVersion.size()); |
| |
| Request request(sizeof(pldm_msg_hdr) + |
| sizeof(struct pldm_request_update_req) + |
| compImgSetVerStrInfo.length); |
| auto requestMsg = reinterpret_cast<pldm_msg*>(request.data()); |
| |
| auto rc = encode_request_update_req( |
| instanceId, maxTransferSize, applicableComponents.size(), |
| PLDM_FWUP_MIN_OUTSTANDING_REQ, fwDevicePkgData.size(), |
| PLDM_STR_TYPE_ASCII, compImgSetVerStrInfo.length, &compImgSetVerStrInfo, |
| requestMsg, |
| sizeof(struct pldm_request_update_req) + compImgSetVerStrInfo.length); |
| if (rc) |
| { |
| // Handle error scenario |
| updateManager->instanceIdDb.free(eid, instanceId); |
| error( |
| "Failed to encode request update request for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| |
| rc = updateManager->handler.registerRequest( |
| eid, instanceId, PLDM_FWUP, PLDM_REQUEST_UPDATE, std::move(request), |
| std::move(std::bind_front(&DeviceUpdater::requestUpdate, this))); |
| if (rc) |
| { |
| // Handle error scenario |
| error( |
| "Failed to send request update for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| } |
| |
| void DeviceUpdater::requestUpdate(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen) |
| { |
| if (response == nullptr || !respMsgLen) |
| { |
| // Handle error scenario |
| error("No response received for request update for endpoint ID '{EID}'", |
| "EID", eid); |
| return; |
| } |
| |
| uint8_t completionCode = 0; |
| uint16_t fdMetaDataLen = 0; |
| uint8_t fdWillSendPkgData = 0; |
| |
| auto rc = decode_request_update_resp(response, respMsgLen, &completionCode, |
| &fdMetaDataLen, &fdWillSendPkgData); |
| if (rc) |
| { |
| error( |
| "Failed to decode request update response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| return; |
| } |
| if (completionCode) |
| { |
| error( |
| "Failure in request update response for endpoint ID '{EID}', completion code '{CC}'", |
| "EID", eid, "CC", completionCode); |
| return; |
| } |
| |
| // Optional fields DeviceMetaData and GetPackageData not handled |
| pldmRequest = std::make_unique<sdeventplus::source::Defer>( |
| updateManager->event, |
| std::bind(&DeviceUpdater::sendPassCompTableRequest, this, |
| componentIndex)); |
| } |
| |
| void DeviceUpdater::sendPassCompTableRequest(size_t offset) |
| { |
| pldmRequest.reset(); |
| |
| auto instanceId = updateManager->instanceIdDb.next(eid); |
| // TransferFlag |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| uint8_t transferFlag = 0; |
| if (applicableComponents.size() == 1) |
| { |
| transferFlag = PLDM_START_AND_END; |
| } |
| else if (offset == 0) |
| { |
| transferFlag = PLDM_START; |
| } |
| else if (offset == applicableComponents.size() - 1) |
| { |
| transferFlag = PLDM_END; |
| } |
| else |
| { |
| transferFlag = PLDM_MIDDLE; |
| } |
| const auto& comp = compImageInfos[applicableComponents[offset]]; |
| // ComponentClassification |
| CompClassification compClassification = std::get<static_cast<size_t>( |
| ComponentImageInfoPos::CompClassificationPos)>(comp); |
| // ComponentIdentifier |
| CompIdentifier compIdentifier = |
| std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>( |
| comp); |
| // ComponentClassificationIndex |
| CompClassificationIndex compClassificationIndex{}; |
| auto compKey = std::make_pair(compClassification, compIdentifier); |
| if (compInfo.contains(compKey)) |
| { |
| auto search = compInfo.find(compKey); |
| compClassificationIndex = search->second; |
| } |
| else |
| { |
| // Handle error scenario |
| error( |
| "Failed to find component classification '{CLASSIFICATION}' and identifier '{IDENTIFIER}'", |
| "CLASSIFICATION", compClassification, "IDENTIFIER", compIdentifier); |
| } |
| // ComponentComparisonStamp |
| CompComparisonStamp compComparisonStamp = std::get<static_cast<size_t>( |
| ComponentImageInfoPos::CompComparisonStampPos)>(comp); |
| // ComponentVersionString |
| const auto& compVersion = |
| std::get<static_cast<size_t>(ComponentImageInfoPos::CompVersionPos)>( |
| comp); |
| variable_field compVerStrInfo{}; |
| compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data()); |
| compVerStrInfo.length = static_cast<uint8_t>(compVersion.size()); |
| |
| Request request(sizeof(pldm_msg_hdr) + |
| sizeof(struct pldm_pass_component_table_req) + |
| compVerStrInfo.length); |
| auto requestMsg = reinterpret_cast<pldm_msg*>(request.data()); |
| auto rc = encode_pass_component_table_req( |
| instanceId, transferFlag, compClassification, compIdentifier, |
| compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, |
| compVerStrInfo.length, &compVerStrInfo, requestMsg, |
| sizeof(pldm_pass_component_table_req) + compVerStrInfo.length); |
| if (rc) |
| { |
| // Handle error scenario |
| updateManager->instanceIdDb.free(eid, instanceId); |
| error( |
| "Failed to encode pass component table req for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| |
| rc = updateManager->handler.registerRequest( |
| eid, instanceId, PLDM_FWUP, PLDM_PASS_COMPONENT_TABLE, |
| std::move(request), |
| std::move(std::bind_front(&DeviceUpdater::passCompTable, this))); |
| if (rc) |
| { |
| // Handle error scenario |
| error( |
| "Failed to send pass component table request for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| } |
| |
| void DeviceUpdater::passCompTable(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen) |
| { |
| if (response == nullptr || !respMsgLen) |
| { |
| // Handle error scenario |
| error( |
| "No response received for pass component table for endpoint ID '{EID}'", |
| "EID", eid); |
| return; |
| } |
| |
| uint8_t completionCode = 0; |
| uint8_t compResponse = 0; |
| uint8_t compResponseCode = 0; |
| |
| auto rc = decode_pass_component_table_resp(response, respMsgLen, |
| &completionCode, &compResponse, |
| &compResponseCode); |
| if (rc) |
| { |
| // Handle error scenario |
| error( |
| "Failed to decode pass component table response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| return; |
| } |
| if (completionCode) |
| { |
| // Handle error scenario |
| error( |
| "Failed to pass component table response for endpoint ID '{EID}', completion code '{CC}'", |
| "EID", eid, "CC", completionCode); |
| return; |
| } |
| // Handle ComponentResponseCode |
| |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| if (componentIndex == applicableComponents.size() - 1) |
| { |
| componentIndex = 0; |
| pldmRequest = std::make_unique<sdeventplus::source::Defer>( |
| updateManager->event, |
| std::bind(&DeviceUpdater::sendUpdateComponentRequest, this, |
| componentIndex)); |
| } |
| else |
| { |
| componentIndex++; |
| pldmRequest = std::make_unique<sdeventplus::source::Defer>( |
| updateManager->event, |
| std::bind(&DeviceUpdater::sendPassCompTableRequest, this, |
| componentIndex)); |
| } |
| } |
| |
| void DeviceUpdater::sendUpdateComponentRequest(size_t offset) |
| { |
| pldmRequest.reset(); |
| |
| auto instanceId = updateManager->instanceIdDb.next(eid); |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| const auto& comp = compImageInfos[applicableComponents[offset]]; |
| // ComponentClassification |
| CompClassification compClassification = std::get<static_cast<size_t>( |
| ComponentImageInfoPos::CompClassificationPos)>(comp); |
| // ComponentIdentifier |
| CompIdentifier compIdentifier = |
| std::get<static_cast<size_t>(ComponentImageInfoPos::CompIdentifierPos)>( |
| comp); |
| // ComponentClassificationIndex |
| CompClassificationIndex compClassificationIndex{}; |
| auto compKey = std::make_pair(compClassification, compIdentifier); |
| if (compInfo.contains(compKey)) |
| { |
| auto search = compInfo.find(compKey); |
| compClassificationIndex = search->second; |
| } |
| else |
| { |
| // Handle error scenario |
| error( |
| "Failed to find component classification '{CLASSIFICATION}' and identifier '{IDENTIFIER}'", |
| "CLASSIFICATION", compClassification, "IDENTIFIER", compIdentifier); |
| } |
| |
| // UpdateOptionFlags |
| bitfield32_t updateOptionFlags; |
| updateOptionFlags.bits.bit0 = std::get<3>(comp)[0]; |
| // ComponentVersion |
| const auto& compVersion = std::get<7>(comp); |
| variable_field compVerStrInfo{}; |
| compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVersion.data()); |
| compVerStrInfo.length = static_cast<uint8_t>(compVersion.size()); |
| |
| Request request(sizeof(pldm_msg_hdr) + |
| sizeof(struct pldm_update_component_req) + |
| compVerStrInfo.length); |
| auto requestMsg = reinterpret_cast<pldm_msg*>(request.data()); |
| |
| auto rc = encode_update_component_req( |
| instanceId, compClassification, compIdentifier, compClassificationIndex, |
| std::get<static_cast<size_t>( |
| ComponentImageInfoPos::CompComparisonStampPos)>(comp), |
| std::get<static_cast<size_t>(ComponentImageInfoPos::CompSizePos)>(comp), |
| updateOptionFlags, PLDM_STR_TYPE_ASCII, compVerStrInfo.length, |
| &compVerStrInfo, requestMsg, |
| sizeof(pldm_update_component_req) + compVerStrInfo.length); |
| if (rc) |
| { |
| // Handle error scenario |
| updateManager->instanceIdDb.free(eid, instanceId); |
| error( |
| "Failed to encode update component req for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| |
| rc = updateManager->handler.registerRequest( |
| eid, instanceId, PLDM_FWUP, PLDM_UPDATE_COMPONENT, std::move(request), |
| std::move(std::bind_front(&DeviceUpdater::updateComponent, this))); |
| if (rc) |
| { |
| // Handle error scenario |
| error( |
| "Failed to send update request for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| } |
| |
| void DeviceUpdater::updateComponent(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen) |
| { |
| if (response == nullptr || !respMsgLen) |
| { |
| // Handle error scenario |
| error( |
| "No response received for update component with endpoint ID {EID}", |
| "EID", eid); |
| return; |
| } |
| |
| uint8_t completionCode = 0; |
| uint8_t compCompatibilityResp = 0; |
| uint8_t compCompatibilityRespCode = 0; |
| bitfield32_t updateOptionFlagsEnabled{}; |
| uint16_t timeBeforeReqFWData = 0; |
| |
| auto rc = decode_update_component_resp( |
| response, respMsgLen, &completionCode, &compCompatibilityResp, |
| &compCompatibilityRespCode, &updateOptionFlagsEnabled, |
| &timeBeforeReqFWData); |
| if (rc) |
| { |
| error( |
| "Failed to decode update request response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| return; |
| } |
| if (completionCode) |
| { |
| error( |
| "Failed to update request response for endpoint ID '{EID}', completion code '{CC}'", |
| "EID", eid, "CC", completionCode); |
| return; |
| } |
| } |
| |
| Response DeviceUpdater::requestFwData(const pldm_msg* request, |
| size_t payloadLength) |
| { |
| uint8_t completionCode = PLDM_SUCCESS; |
| uint32_t offset = 0; |
| uint32_t length = 0; |
| Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0); |
| auto responseMsg = reinterpret_cast<pldm_msg*>(response.data()); |
| auto rc = decode_request_firmware_data_req(request, payloadLength, &offset, |
| &length); |
| if (rc) |
| { |
| error( |
| "Failed to decode request firmware date request for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| rc = encode_request_firmware_data_resp( |
| request->hdr.instance_id, PLDM_ERROR_INVALID_DATA, responseMsg, |
| sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| return response; |
| } |
| |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| const auto& comp = compImageInfos[applicableComponents[componentIndex]]; |
| auto compOffset = std::get<5>(comp); |
| auto compSize = std::get<6>(comp); |
| info("Decoded fw request data at offset '{OFFSET}' and length '{LENGTH}' ", |
| "OFFSET", offset, "LENGTH", length); |
| if (length < PLDM_FWUP_BASELINE_TRANSFER_SIZE || length > maxTransferSize) |
| { |
| rc = encode_request_firmware_data_resp( |
| request->hdr.instance_id, PLDM_FWUP_INVALID_TRANSFER_LENGTH, |
| responseMsg, sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| return response; |
| } |
| |
| if (offset + length > compSize + PLDM_FWUP_BASELINE_TRANSFER_SIZE) |
| { |
| rc = encode_request_firmware_data_resp( |
| request->hdr.instance_id, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg, |
| sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| return response; |
| } |
| |
| size_t padBytes = 0; |
| if (offset + length > compSize) |
| { |
| padBytes = offset + length - compSize; |
| } |
| |
| response.resize(sizeof(pldm_msg_hdr) + sizeof(completionCode) + length); |
| responseMsg = reinterpret_cast<pldm_msg*>(response.data()); |
| package.seekg(compOffset + offset); |
| package.read(reinterpret_cast<char*>(response.data() + |
| sizeof(pldm_msg_hdr) + |
| sizeof(completionCode)), |
| length - padBytes); |
| rc = encode_request_firmware_data_resp(request->hdr.instance_id, |
| completionCode, responseMsg, |
| sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode request firmware date response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| return response; |
| } |
| |
| return response; |
| } |
| |
| Response DeviceUpdater::transferComplete(const pldm_msg* request, |
| size_t payloadLength) |
| { |
| uint8_t completionCode = PLDM_SUCCESS; |
| Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0); |
| auto responseMsg = reinterpret_cast<pldm_msg*>(response.data()); |
| |
| uint8_t transferResult = 0; |
| auto rc = decode_transfer_complete_req(request, payloadLength, |
| &transferResult); |
| if (rc) |
| { |
| error( |
| "Failed to decode TransferComplete request for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| rc = encode_transfer_complete_resp(request->hdr.instance_id, |
| PLDM_ERROR_INVALID_DATA, responseMsg, |
| sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode TransferComplete response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| return response; |
| } |
| |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| const auto& comp = compImageInfos[applicableComponents[componentIndex]]; |
| const auto& compVersion = std::get<7>(comp); |
| |
| if (transferResult == PLDM_FWUP_TRANSFER_SUCCESS) |
| { |
| info( |
| "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' transfer complete.", |
| "EID", eid, "COMPONENT_VERSION", compVersion); |
| } |
| else |
| { |
| error( |
| "Failure in transfer of the component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - {RESULT}", |
| "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT", |
| transferResult); |
| } |
| |
| rc = encode_transfer_complete_resp(request->hdr.instance_id, completionCode, |
| responseMsg, sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode transfer complete response of endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| return response; |
| } |
| |
| return response; |
| } |
| |
| Response DeviceUpdater::verifyComplete(const pldm_msg* request, |
| size_t payloadLength) |
| { |
| uint8_t completionCode = PLDM_SUCCESS; |
| Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0); |
| auto responseMsg = reinterpret_cast<pldm_msg*>(response.data()); |
| |
| uint8_t verifyResult = 0; |
| auto rc = decode_verify_complete_req(request, payloadLength, &verifyResult); |
| if (rc) |
| { |
| error( |
| "Failed to decode verify complete request of endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| rc = encode_verify_complete_resp(request->hdr.instance_id, |
| PLDM_ERROR_INVALID_DATA, responseMsg, |
| sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode verify complete response of endpoint ID '{EID}', response code '{RC}'.", |
| "EID", eid, "RC", rc); |
| } |
| return response; |
| } |
| |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| const auto& comp = compImageInfos[applicableComponents[componentIndex]]; |
| const auto& compVersion = std::get<7>(comp); |
| |
| if (verifyResult == PLDM_FWUP_VERIFY_SUCCESS) |
| { |
| info( |
| "Component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' verification complete.", |
| "EID", eid, "COMPONENT_VERSION", compVersion); |
| } |
| else |
| { |
| error( |
| "Failed to verify component endpoint ID '{EID}' and version '{COMPONENT_VERSION}' with transfer result - '{RESULT}'", |
| "EID", eid, "COMPONENT_VERSION", compVersion, "RESULT", |
| verifyResult); |
| } |
| |
| rc = encode_verify_complete_resp(request->hdr.instance_id, completionCode, |
| responseMsg, sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode verify complete response for endpoint ID '{EID}', response code - {RC}", |
| "EID", eid, "RC", rc); |
| return response; |
| } |
| |
| return response; |
| } |
| |
| Response DeviceUpdater::applyComplete(const pldm_msg* request, |
| size_t payloadLength) |
| { |
| uint8_t completionCode = PLDM_SUCCESS; |
| Response response(sizeof(pldm_msg_hdr) + sizeof(completionCode), 0); |
| auto responseMsg = reinterpret_cast<pldm_msg*>(response.data()); |
| |
| uint8_t applyResult = 0; |
| bitfield16_t compActivationModification{}; |
| auto rc = decode_apply_complete_req(request, payloadLength, &applyResult, |
| &compActivationModification); |
| if (rc) |
| { |
| error( |
| "Failed to decode apply complete request for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| rc = encode_apply_complete_resp(request->hdr.instance_id, |
| PLDM_ERROR_INVALID_DATA, responseMsg, |
| sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| return response; |
| } |
| |
| const auto& applicableComponents = |
| std::get<ApplicableComponents>(fwDeviceIDRecord); |
| const auto& comp = compImageInfos[applicableComponents[componentIndex]]; |
| const auto& compVersion = std::get<7>(comp); |
| |
| if (applyResult == PLDM_FWUP_APPLY_SUCCESS || |
| applyResult == PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) |
| { |
| info( |
| "Component endpoint ID '{EID}' with '{COMPONENT_VERSION}' apply complete.", |
| "EID", eid, "COMPONENT_VERSION", compVersion); |
| updateManager->updateActivationProgress(); |
| } |
| else |
| { |
| error( |
| "Failed to apply component endpoint ID '{EID}' and version '{COMPONENT_VERSION}', error - {ERROR}", |
| "EID", eid, "COMPONENT_VERSION", compVersion, "ERROR", applyResult); |
| } |
| |
| rc = encode_apply_complete_resp(request->hdr.instance_id, completionCode, |
| responseMsg, sizeof(completionCode)); |
| if (rc) |
| { |
| error( |
| "Failed to encode apply complete response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| return response; |
| } |
| |
| if (componentIndex == applicableComponents.size() - 1) |
| { |
| componentIndex = 0; |
| pldmRequest = std::make_unique<sdeventplus::source::Defer>( |
| updateManager->event, |
| std::bind(&DeviceUpdater::sendActivateFirmwareRequest, this)); |
| } |
| else |
| { |
| componentIndex++; |
| pldmRequest = std::make_unique<sdeventplus::source::Defer>( |
| updateManager->event, |
| std::bind(&DeviceUpdater::sendUpdateComponentRequest, this, |
| componentIndex)); |
| } |
| |
| return response; |
| } |
| |
| void DeviceUpdater::sendActivateFirmwareRequest() |
| { |
| pldmRequest.reset(); |
| auto instanceId = updateManager->instanceIdDb.next(eid); |
| Request request(sizeof(pldm_msg_hdr) + |
| sizeof(struct pldm_activate_firmware_req)); |
| auto requestMsg = reinterpret_cast<pldm_msg*>(request.data()); |
| |
| auto rc = encode_activate_firmware_req( |
| instanceId, PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg, |
| sizeof(pldm_activate_firmware_req)); |
| if (rc) |
| { |
| updateManager->instanceIdDb.free(eid, instanceId); |
| error( |
| "Failed to encode activate firmware req for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| |
| rc = updateManager->handler.registerRequest( |
| eid, instanceId, PLDM_FWUP, PLDM_ACTIVATE_FIRMWARE, std::move(request), |
| std::move(std::bind_front(&DeviceUpdater::activateFirmware, this))); |
| if (rc) |
| { |
| error( |
| "Failed to send activate firmware request for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| } |
| } |
| |
| void DeviceUpdater::activateFirmware(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen) |
| { |
| if (response == nullptr || !respMsgLen) |
| { |
| // Handle error scenario |
| error( |
| "No response received for activate firmware for endpoint ID '{EID}'", |
| "EID", eid); |
| return; |
| } |
| |
| uint8_t completionCode = 0; |
| uint16_t estimatedTimeForActivation = 0; |
| |
| auto rc = decode_activate_firmware_resp( |
| response, respMsgLen, &completionCode, &estimatedTimeForActivation); |
| if (rc) |
| { |
| // Handle error scenario |
| error( |
| "Failed to decode activate firmware response for endpoint ID '{EID}', response code '{RC}'", |
| "EID", eid, "RC", rc); |
| return; |
| } |
| if (completionCode) |
| { |
| // Handle error scenario |
| error( |
| "Failed to activate firmware response for endpoint ID '{EID}', completion code '{CC}'", |
| "EID", eid, "CC", completionCode); |
| return; |
| } |
| |
| updateManager->updateDeviceCompletion(eid, true); |
| } |
| |
| } // namespace fw_update |
| |
| } // namespace pldm |