| #pragma once |
| |
| #include "common/types.hpp" |
| |
| #include <libpldm/base.h> |
| #include <linux/mctp.h> |
| |
| #include <sdbusplus/timer.hpp> |
| #include <sdeventplus/event.hpp> |
| #include <sdeventplus/source/event.hpp> |
| |
| namespace pldm |
| { |
| |
| namespace fw_update |
| { |
| |
| /** @brief Type alias for component update status tracking |
| * Maps component index to its update completion status (true indicates |
| * successful completion, false indicates cancellation) |
| */ |
| using ComponentUpdateStatusMap = std::map<size_t, bool>; |
| |
| class UpdateManagerBase; |
| |
| /** @class UpdateProgress |
| * |
| * Attempts to provide accurate reporting of firmware update progress |
| * Called at the various phases of firmware update. |
| * A single UpdateProgress object represents a component of a pldm package |
| */ |
| class UpdateProgress |
| { |
| public: |
| /** @brief an enum to define the different states of progress |
| * |
| */ |
| enum class state |
| { |
| Update, |
| Verify, |
| Apply, |
| }; |
| |
| /** @brief Construct an UpdateProgress object given to the total component |
| * size |
| * |
| * @param[in] totalSize the size in bytes of a component for a given device |
| * @param[in] eid the eid of the device this class tracks progress for |
| */ |
| UpdateProgress(uint32_t totalSize, mctp_eid_t eid); |
| ~UpdateProgress() = default; |
| UpdateProgress& operator=(UpdateProgress&&) = default; |
| UpdateProgress& operator=(const UpdateProgress&) = delete; |
| UpdateProgress(UpdateProgress&&) = default; |
| UpdateProgress(const UpdateProgress&) = delete; |
| |
| /** @brief Called when switching between phases of firmware update |
| * |
| * @param[in] newState the state that we are entering. See |
| * UpdateProgress::state |
| * @return true on success, false on failure |
| */ |
| void updateState(state newState); |
| |
| /** @brief called when servicing RequestFirmwareData commands |
| * |
| * @param[in] amountUpdate the length of firmware transmitted, in bytes |
| * @return true on success, false on failure |
| */ |
| void reportFwUpdate(uint32_t amountUpdated); |
| |
| /** @brief get the progress as a percentage of this component |
| * |
| * @return the progress of this component as an int in [0-100] |
| */ |
| uint8_t getProgress() const; |
| |
| /** @brief get the total size of the firmware component in bytes |
| * |
| * @return the total number of bytes for the component |
| */ |
| uint32_t getTotalSize() const; |
| |
| private: |
| /** |
| * @brief progress of firmware update in percentage [0-100] |
| */ |
| uint8_t progress; |
| |
| /** |
| * @brief the eid of the device this object tracks |
| */ |
| mctp_eid_t eid; |
| /** |
| * @brief the total size in bytes of this component |
| */ |
| uint32_t totalSize; |
| /** |
| * @brief the total number of bytes sent |
| */ |
| uint32_t totalUpdated; |
| /** |
| * @brief the current state of update for this component |
| */ |
| state currentState; |
| }; |
| |
| /** @class DeviceUpdater |
| * |
| * DeviceUpdater orchestrates the firmware update of the firmware device and |
| * updates the UpdateManager about the status once it is complete. |
| */ |
| class DeviceUpdater |
| { |
| public: |
| DeviceUpdater() = delete; |
| DeviceUpdater(const DeviceUpdater&) = delete; |
| DeviceUpdater(DeviceUpdater&&) = default; |
| DeviceUpdater& operator=(const DeviceUpdater&) = delete; |
| DeviceUpdater& operator=(DeviceUpdater&&) = delete; |
| ~DeviceUpdater() = default; |
| |
| /** @brief Constructor |
| * |
| * @param[in] eid - Endpoint ID of the firmware device |
| * @param[in] package - File stream for firmware update package |
| * @param[in] fwDeviceIDRecord - FirmwareDeviceIDRecord in the fw update |
| * package that matches this firmware device |
| * @param[in] compImageInfos - Component image information for all the |
| * components in the fw update package |
| * @param[in] compInfo - Component info for the components in this FD |
| * derived from GetFirmwareParameters response |
| * @param[in] maxTransferSize - Maximum size in bytes of the variable |
| * payload allowed to be requested by the FD |
| * @param[in] updateManager - To update the status of fw update of the |
| * device |
| */ |
| explicit DeviceUpdater(mctp_eid_t eid, std::istream& package, |
| const FirmwareDeviceIDRecord& fwDeviceIDRecord, |
| const ComponentImageInfos& compImageInfos, |
| const ComponentInfo& compInfo, |
| uint32_t maxTransferSize, |
| UpdateManagerBase* updateManager); |
| |
| /** @brief Get the progress of updating this device as percentage |
| * |
| * Goes through each component for this device and calculates |
| * the percentage we are through the update process |
| * |
| * @return The percentage as an int [0-100], 0 is no progress, 100 is done. |
| */ |
| uint8_t getProgress() const; |
| |
| /** @brief Start the firmware update flow for the FD |
| * |
| * To start the update flow RequestUpdate command is sent to the FD. |
| * |
| */ |
| void startFwUpdateFlow(); |
| |
| /** @brief Handler for RequestUpdate command response |
| * |
| * The response of the RequestUpdate is processed and if the response |
| * is success, send PassComponentTable request to FD. |
| * |
| * @param[in] eid - Remote MCTP endpoint |
| * @param[in] response - PLDM response message |
| * @param[in] respMsgLen - Response message length |
| */ |
| void requestUpdate(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen); |
| |
| /** @brief Handler for PassComponentTable command response |
| * |
| * The response of the PassComponentTable is processed. If the response |
| * indicates component can be updated, continue with either a) or b). |
| * |
| * a. Send PassComponentTable request for the next component if |
| * applicable |
| * b. UpdateComponent command to request updating a specific |
| * firmware component |
| * |
| * If the response indicates component may be updateable, continue |
| * based on the policy in DeviceUpdateOptionFlags. |
| * |
| * @param[in] eid - Remote MCTP endpoint |
| * @param[in] response - PLDM response message |
| * @param[in] respMsgLen - Response message length |
| */ |
| void passCompTable(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen); |
| |
| /** @brief Handler for UpdateComponent command response |
| * |
| * The response of the UpdateComponent is processed and will wait for |
| * FD to request the firmware data. |
| * |
| * @param[in] eid - Remote MCTP endpoint |
| * @param[in] response - PLDM response message |
| * @param[in] respMsgLen - Response message length |
| */ |
| void updateComponent(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen); |
| |
| /** @brief Handler for RequestFirmwareData request |
| * |
| * @param[in] request - Request message |
| * @param[in] payload_length - Request message payload length |
| * @return Response - PLDM Response message |
| */ |
| Response requestFwData(const pldm_msg* request, size_t payloadLength); |
| |
| /** @brief Handler for TransferComplete request |
| * |
| * @param[in] request - Request message |
| * @param[in] payload_length - Request message payload length |
| * @return Response - PLDM Response message |
| */ |
| Response transferComplete(const pldm_msg* request, size_t payloadLength); |
| |
| /** @brief Handler for VerifyComplete request |
| * |
| * @param[in] request - Request message |
| * @param[in] payload_length - Request message payload length |
| * @return Response - PLDM Response message |
| */ |
| Response verifyComplete(const pldm_msg* request, size_t payloadLength); |
| |
| /** @brief Handler for ApplyComplete request |
| * |
| * @param[in] request - Request message |
| * @param[in] payload_length - Request message payload length |
| * @return Response - PLDM Response message |
| */ |
| Response applyComplete(const pldm_msg* request, size_t payloadLength); |
| |
| /** @brief Handler for ActivateFirmware command response |
| * |
| * The response of the ActivateFirmware is processed and will update the |
| * UpdateManager with the completion of the firmware update. |
| * |
| * @param[in] eid - Remote MCTP endpoint |
| * @param[in] response - PLDM response message |
| * @param[in] respMsgLen - Response message length |
| */ |
| void activateFirmware(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen); |
| /** |
| * @brief Handler for CancelUpdateComponent command response |
| * |
| * @param[in] eid - Remote MCTP endpoint |
| * @param[in] response - PLDM Response message |
| * @param[in] respMsgLen - Response message length |
| */ |
| void cancelUpdateComponent(mctp_eid_t eid, const pldm_msg* response, |
| size_t respMsgLen); |
| |
| private: |
| /** @brief Send PassComponentTable command request |
| * |
| * @param[in] compOffset - component offset in compImageInfos |
| */ |
| void sendPassCompTableRequest(size_t offset); |
| |
| /** @brief Send UpdateComponent command request |
| * |
| * @param[in] compOffset - component offset in compImageInfos |
| */ |
| void sendUpdateComponentRequest(size_t offset); |
| |
| /** @brief Send ActivateFirmware command request */ |
| void sendActivateFirmwareRequest(); |
| |
| /** |
| * @brief Send cancel update component request |
| */ |
| void sendCancelUpdateComponentRequest(); |
| |
| /** |
| * @brief Create a timer to handle RequestFirmwareData timeout (UA_T2) |
| */ |
| void createRequestFwDataTimer(); |
| |
| /** @brief Endpoint ID of the firmware device */ |
| mctp_eid_t eid; |
| |
| /** @brief File stream for firmware update package */ |
| std::istream& package; |
| |
| /** @brief FirmwareDeviceIDRecord in the fw update package that matches this |
| * firmware device |
| */ |
| const FirmwareDeviceIDRecord& fwDeviceIDRecord; |
| |
| /** @brief Component image information for all the components in the fw |
| * update package |
| */ |
| const ComponentImageInfos& compImageInfos; |
| |
| /** @brief Component info for the components in this FD derived from |
| * GetFirmwareParameters response |
| */ |
| const ComponentInfo& compInfo; |
| |
| /** @brief Maximum size in bytes of the variable payload to be requested by |
| * the FD via RequestFirmwareData command |
| */ |
| uint32_t maxTransferSize; |
| |
| /** @brief To update the status of fw update of the FD */ |
| UpdateManagerBase* updateManager; |
| |
| /** @brief Component index is used to track the current component being |
| * updated if multiple components are applicable for the FD. |
| * It is also used to keep track of the next component in |
| * PassComponentTable |
| */ |
| size_t componentIndex = 0; |
| |
| /** @brief To send a PLDM request after the current command handling */ |
| std::unique_ptr<sdeventplus::source::Defer> pldmRequest; |
| |
| /** |
| * @brief Map to hold component update status. True - success, False - |
| * cancelled |
| */ |
| ComponentUpdateStatusMap componentUpdateStatus; |
| |
| /** |
| * @brief Timeout in seconds for the UA to cancel the component update if no |
| * command is received from the FD during component image transfer stage |
| * |
| */ |
| static constexpr int updateTimeoutSeconds = 60; |
| |
| /** |
| * @brief Timer to handle RequestFirmwareData timeout(UA_T2) |
| * |
| */ |
| std::unique_ptr<sdbusplus::Timer> reqFwDataTimer; |
| /** |
| * @brief a list of UpdateProgress objects, one for each firmware component |
| * applicable to this device |
| */ |
| std::vector<UpdateProgress> progress; |
| /** |
| * @brief Whether this device has gone through application. Needed because |
| * UpdateProgress handles each component but application happens at |
| * the device level |
| */ |
| bool activationComplete; |
| }; |
| |
| } // namespace fw_update |
| |
| } // namespace pldm |