| #pragma once |
| |
| #include "update_manager.hpp" |
| |
| #include <xyz/openbmc_project/Software/ApplyTime/server.hpp> |
| #include <xyz/openbmc_project/Software/Update/server.hpp> |
| |
| #include <memory> |
| #include <optional> |
| #include <span> |
| #include <spanstream> |
| #include <variant> |
| |
| namespace pldm::fw_update |
| { |
| |
| namespace software = sdbusplus::xyz::openbmc_project::Software::server; |
| |
| using ItemUpdateIntf = sdbusplus::server::object_t< |
| sdbusplus::xyz::openbmc_project::Software::server::Update>; |
| using ApplyTimeIntf = |
| sdbusplus::xyz::openbmc_project::Software::server::ApplyTime; |
| |
| class ItemUpdateManager : public UpdateManagerBase, public ItemUpdateIntf |
| { |
| public: |
| ItemUpdateManager() = delete; |
| ItemUpdateManager(const ItemUpdateManager&) = delete; |
| ItemUpdateManager(ItemUpdateManager&&) = delete; |
| ItemUpdateManager& operator=(const ItemUpdateManager&) = delete; |
| ItemUpdateManager& operator=(ItemUpdateManager&&) = delete; |
| ~ItemUpdateManager() = default; |
| |
| /** |
| * @brief Constructor for ItemUpdateManager |
| * |
| * @param[in] eid The MCTP EID |
| * @param[in] event The event object |
| * @param[in] handler The request handler |
| * @param[in] instanceIdDb The instance ID database |
| * @param[in] objPath The D-Bus object path |
| * @param[in] generatedId The software hash identifier |
| * @param[in] descriptors The descriptors for the device |
| * @param[in] componentInfo The component information for the device |
| */ |
| explicit ItemUpdateManager( |
| mctp_eid_t eid, Event& event, |
| pldm::requester::Handler<pldm::requester::Request>& handler, |
| InstanceIdDb& instanceIdDb, const std::string& objPath, |
| const std::string& generatedId, const Descriptors& descriptors, |
| const ComponentInfo& componentInfo, |
| const ConditionPaths& conditionPathPair = ConditionPaths{}, |
| const std::string& conditionArg = std::string{}, |
| std::function<void()> taskCompletionCallback = nullptr) : |
| UpdateManagerBase(event, handler, instanceIdDb), |
| ItemUpdateIntf(pldm::utils::DBusHandler::getBus(), |
| std::format("{}_{}", objPath, generatedId).c_str()), |
| eid(eid), objPath(objPath), descriptors(descriptors), |
| componentInfo(componentInfo), preConditionPath(conditionPathPair.first), |
| postConditionPath(conditionPathPair.second), |
| baseConditionArg(conditionArg), conditionArg(conditionArg), |
| taskCompletionCallback(std::move(taskCompletionCallback)) |
| {} |
| |
| /** |
| * @brief Handle PLDM requests for the item-based update manager |
| * |
| * @param[in] eid - Remote MCTP Endpoint ID |
| * @param[in] command - PLDM command code |
| * @param[in] request - PLDM request message |
| * @param[in] reqMsgLen - PLDM request message length |
| * @return PLDM response message |
| */ |
| Response handleRequest(mctp_eid_t eid, uint8_t command, |
| const pldm_msg* request, size_t reqMsgLen); |
| |
| /** |
| * @brief Update the device completion status |
| * |
| * @param[in] eid - The MCTP EID of the device |
| * @param[in] status - The completion status (true for success, false for |
| * failure) |
| */ |
| void updateDeviceCompletion(mctp_eid_t eid, bool status) override; |
| |
| /** |
| * @brief Update the activation progress status |
| */ |
| void updateActivationProgress() override; |
| |
| /** |
| * @brief Activate the firmware update package |
| */ |
| void activatePackage() override; |
| |
| /** |
| * @brief Clear the activation information |
| */ |
| void resetActivationState() override; |
| |
| /** |
| * @brief Start the update process |
| * |
| * D-Bus method implementation for starting the update process |
| * |
| * @param[in] image The image file descriptor |
| * @param[in] applyTime The requested apply time (Immediate, OnReset, |
| * OnStart, etc.) This will be passed to post-condition services to allow |
| * conditional handling (e.g., skip reset if not |
| * immediate) |
| */ |
| virtual sdbusplus::object_path startUpdate( |
| sdbusplus::message::unix_fd image, |
| ApplyTimeIntf::RequestedApplyTimes applyTime = |
| ApplyTimeIntf::RequestedApplyTimes::Immediate) override; |
| |
| /** |
| * @brief Associate the firmware update package with the target device |
| * |
| * This function associates the firmware update package with the specified |
| * target device by matching the device ID records and descriptors. |
| * |
| * @param[in] fwDeviceIDRecords The firmware device ID records |
| * @param[in] descriptors The descriptors to match against |
| * |
| * @return The offset of the device ID record if found, std::nullopt |
| * otherwise. |
| */ |
| std::optional<DeviceIDRecordOffset> associatePkgToDevice( |
| const FirmwareDeviceIDRecords& fwDeviceIDRecords, |
| const Descriptors& descriptors); |
| |
| private: |
| mctp_eid_t eid; |
| std::string objPath; |
| std::string objPathWithSwId; |
| |
| /** |
| * @brief The descriptors to match against |
| */ |
| const Descriptors& descriptors; |
| |
| /** |
| * @brief The component information of the target device |
| */ |
| const ComponentInfo& componentInfo; |
| |
| /** |
| * @brief The package data for the firmware update |
| */ |
| std::unique_ptr<pldm::utils::MMapHandler> packageMap; |
| |
| /** |
| * @brief The package data stream for the firmware update |
| */ |
| std::unique_ptr<std::ispanstream> packageDataStream; |
| |
| /** |
| * @brief Process the firmware update package |
| * |
| * @return true on success, false on failure |
| */ |
| bool processPackage(); |
| |
| /** |
| * @brief Send the defer request of the firmware update package |
| * |
| * @param[in] fd - The firmware update package file descriptor |
| * @return The D-Bus object path of the firmware update package |
| */ |
| std::string processFd(int fd); |
| |
| void startFirmwareUpdate(); |
| |
| /** |
| * @brief Common completion path for an update attempt |
| * |
| * Reports the final activation state, releases the update resources and |
| * notifies the completion callback. This is the single completion path for |
| * both a finished firmware update and a failing pre/post update condition, |
| * so it tolerates being called before the firmware update flow started. |
| * |
| * @param[in] status - true when the update succeeded |
| */ |
| void completeUpdate(bool status); |
| |
| /** |
| * @brief Common teardown path for cleaning up update resources |
| * |
| * Resets deviceUpdater, packageDataStream, packageMap, dupFd and |
| * marks updateInProgress as false. Should be called from all cleanup |
| * paths to ensure consistent resource management. |
| */ |
| void teardownUpdate(); |
| |
| std::unique_ptr<Activation> inProgressActivation; |
| std::unique_ptr<ActivationProgress> activationProgress; |
| std::unique_ptr<PackageParser> parser; |
| std::unique_ptr<DeviceUpdater> deviceUpdater; |
| /** |
| * @brief Start time of the firmware update flow |
| * |
| * Only set once the update has been activated, so that a completion before |
| * that point does not report a bogus duration. |
| */ |
| std::optional<decltype(std::chrono::steady_clock::now())> startTime; |
| |
| /** |
| * @brief The defer handler for processing package |
| */ |
| std::unique_ptr<sdeventplus::source::Defer> deferHandler; |
| |
| /** |
| * @brief RAII wrapper for the duplicated package file descriptor |
| */ |
| std::unique_ptr<pldm::utils::CustomFD> dupFd; |
| |
| /** |
| * @brief Liveness token for callbacks that can outlive this manager |
| * |
| * A condition callback is owned by the SystemdInterface singleton, which |
| * lives as long as the daemon, while this manager is erased as soon as its |
| * MCTP endpoint goes away. Callbacks therefore capture a weak reference to |
| * this token and return early once it has expired, both while the StartUnit |
| * reply is still pending and after the callback has been registered for the |
| * JobRemoved signal. |
| */ |
| std::shared_ptr<std::monostate> aliveToken = |
| std::make_shared<std::monostate>(); |
| |
| std::string preConditionPath; |
| std::string postConditionPath; |
| |
| /** |
| * @brief Named arguments known before an update is requested |
| */ |
| std::string baseConditionArg; |
| |
| /** |
| * @brief All named arguments passed to a parameterized condition service |
| * |
| * The base arguments plus the fields only known once an update has been |
| * requested. Ignored for a condition service that is not parameterized. |
| */ |
| std::string conditionArg; |
| ApplyTimeIntf::RequestedApplyTimes applyTime = |
| ApplyTimeIntf::RequestedApplyTimes::Immediate; |
| |
| /** |
| * @brief Convert applyTime enum to string representation |
| * @return String representation of applyTime |
| */ |
| std::string applyTimeToString() const; |
| |
| std::function<void()> taskCompletionCallback; |
| |
| bool updateInProgress = false; |
| |
| /** @brief The last progress that was calculated. Used to avoid spamming |
| * dbus |
| * |
| */ |
| uint8_t lastProgress; |
| }; |
| |
| } // namespace pldm::fw_update |