101539e7eSLei YU #pragma once 201539e7eSLei YU 301539e7eSLei YU #include "config.h" 401539e7eSLei YU 501539e7eSLei YU #include "activation.hpp" 67f2a2152SLei YU #include "association_interface.hpp" 791029448SLei YU #include "types.hpp" 85e0dcb39SLei YU #include "utils.hpp" 901539e7eSLei YU #include "version.hpp" 1001539e7eSLei YU 115e0dcb39SLei YU #include <phosphor-logging/log.hpp> 1201539e7eSLei YU #include <sdbusplus/server.hpp> 1391029448SLei YU #include <xyz/openbmc_project/Association/Definitions/server.hpp> 1401539e7eSLei YU #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp> 1501539e7eSLei YU 165670b188SPatrick Williams #include <filesystem> 17*487e2e19SShawn McCarney #include <map> 18*487e2e19SShawn McCarney #include <string> 19*487e2e19SShawn McCarney #include <variant> 20*487e2e19SShawn McCarney #include <vector> 215670b188SPatrick Williams 22f77189f7SLei YU class TestItemUpdater; 23f77189f7SLei YU 2401539e7eSLei YU namespace phosphor 2501539e7eSLei YU { 2601539e7eSLei YU namespace software 2701539e7eSLei YU { 2801539e7eSLei YU namespace updater 2901539e7eSLei YU { 3001539e7eSLei YU 3101539e7eSLei YU class Version; 3201539e7eSLei YU 33374fae56SPatrick Williams using ItemUpdaterInherit = sdbusplus::server::object_t< 34a5c47bb3SLei YU sdbusplus::xyz::openbmc_project::Association::server::Definitions>; 35a5c47bb3SLei YU 3601539e7eSLei YU namespace MatchRules = sdbusplus::bus::match::rules; 3701539e7eSLei YU 3858c26e3fSLei YU namespace fs = std::filesystem; 3958c26e3fSLei YU 4001539e7eSLei YU /** @class ItemUpdater 4101539e7eSLei YU * @brief Manages the activation of the PSU version items. 4201539e7eSLei YU */ 435670b188SPatrick Williams class ItemUpdater : 445670b188SPatrick Williams public ItemUpdaterInherit, 45ffb36539SLei YU public AssociationInterface, 46ffb36539SLei YU public ActivationListener 4701539e7eSLei YU { 48f77189f7SLei YU friend class ::TestItemUpdater; 49f77189f7SLei YU 5001539e7eSLei YU public: 5101539e7eSLei YU /** @brief Constructs ItemUpdater 5201539e7eSLei YU * 5301539e7eSLei YU * @param[in] bus - The D-Bus bus object 5401539e7eSLei YU * @param[in] path - The D-Bus path 5501539e7eSLei YU */ ItemUpdater(sdbusplus::bus_t & bus,const std::string & path)56374fae56SPatrick Williams ItemUpdater(sdbusplus::bus_t& bus, const std::string& path) : 5701539e7eSLei YU ItemUpdaterInherit(bus, path.c_str()), bus(bus), 58bab5ed99SPatrick Williams versionMatch( 59bab5ed99SPatrick Williams bus, 60bab5ed99SPatrick Williams MatchRules::interfacesAdded() + MatchRules::path(SOFTWARE_OBJPATH), 61*487e2e19SShawn McCarney std::bind(std::mem_fn(&ItemUpdater::onVersionInterfacesAddedMsg), 62*487e2e19SShawn McCarney this, std::placeholders::_1)), 63760053d8SFaisal Awada psuInterfaceMatch( 64760053d8SFaisal Awada bus, 65760053d8SFaisal Awada MatchRules::interfacesAdded() + 66760053d8SFaisal Awada MatchRules::path("/xyz/openbmc_project/inventory") + 67760053d8SFaisal Awada MatchRules::sender("xyz.openbmc_project.Inventory.Manager"), 68*487e2e19SShawn McCarney std::bind(std::mem_fn(&ItemUpdater::onPSUInterfacesAdded), this, 69760053d8SFaisal Awada std::placeholders::_1)) 7001539e7eSLei YU { 71760053d8SFaisal Awada processPSUImageAndSyncToLatest(); 7201539e7eSLei YU } 7301539e7eSLei YU 7401539e7eSLei YU /** @brief Deletes version 7501539e7eSLei YU * 7601539e7eSLei YU * @param[in] versionId - Id of the version to delete 7701539e7eSLei YU */ 78a5c47bb3SLei YU void erase(const std::string& versionId); 7901539e7eSLei YU 8091029448SLei YU /** @brief Creates an active association to the 8191029448SLei YU * newly active software image 8291029448SLei YU * 8391029448SLei YU * @param[in] path - The path to create the association to. 8491029448SLei YU */ 857f2a2152SLei YU void createActiveAssociation(const std::string& path) override; 8691029448SLei YU 87ad90ad51SLei YU /** @brief Add the functional association to the 8891029448SLei YU * new "running" PSU images 8991029448SLei YU * 90ad90ad51SLei YU * @param[in] path - The path to add the association to. 9191029448SLei YU */ 927f2a2152SLei YU void addFunctionalAssociation(const std::string& path) override; 9391029448SLei YU 94a8b966f1SLei YU /** @brief Add the updateable association to the 95a8b966f1SLei YU * "running" PSU software image 96a8b966f1SLei YU * 97a8b966f1SLei YU * @param[in] path - The path to create the association. 98a8b966f1SLei YU */ 99a8b966f1SLei YU void addUpdateableAssociation(const std::string& path) override; 100a8b966f1SLei YU 10191029448SLei YU /** @brief Removes the associations from the provided software image path 10291029448SLei YU * 10391029448SLei YU * @param[in] path - The path to remove the association from. 10491029448SLei YU */ 1057f2a2152SLei YU void removeAssociation(const std::string& path) override; 10691029448SLei YU 107ffb36539SLei YU /** @brief Notify a PSU is updated 108ffb36539SLei YU * 109ffb36539SLei YU * @param[in] versionId - The versionId of the activation 110ffb36539SLei YU * @param[in] psuInventoryPath - The PSU inventory path that is updated 111ffb36539SLei YU */ 112ffb36539SLei YU void onUpdateDone(const std::string& versionId, 113ffb36539SLei YU const std::string& psuInventoryPath) override; 114ffb36539SLei YU 1157f2a2152SLei YU private: 116*487e2e19SShawn McCarney using Properties = 117*487e2e19SShawn McCarney std::map<std::string, utils::UtilsInterface::PropertyType>; 118*487e2e19SShawn McCarney using InterfacesAddedMap = 119*487e2e19SShawn McCarney std::map<std::string, 120*487e2e19SShawn McCarney std::map<std::string, std::variant<bool, std::string>>>; 121*487e2e19SShawn McCarney 12201539e7eSLei YU /** @brief Callback function for Software.Version match. 12301539e7eSLei YU * 12401539e7eSLei YU * @param[in] msg - Data associated with subscribed signal 12501539e7eSLei YU */ 126*487e2e19SShawn McCarney void onVersionInterfacesAddedMsg(sdbusplus::message_t& msg); 12701539e7eSLei YU 128*487e2e19SShawn McCarney /** @brief Called when new Software.Version interfaces are found 129*487e2e19SShawn McCarney * @details Creates an Activation D-Bus object if appropriate 130*487e2e19SShawn McCarney * Throws an exception if an error occurs. 131*487e2e19SShawn McCarney * 132*487e2e19SShawn McCarney * @param[in] path - D-Bus object path 133*487e2e19SShawn McCarney * @param[in] interfaces - D-Bus interfaces that were added 134*487e2e19SShawn McCarney */ 135*487e2e19SShawn McCarney void onVersionInterfacesAdded(const std::string& path, 136*487e2e19SShawn McCarney const InterfacesAddedMap& interfaces); 137a2c2cd72SLei YU 138ad90ad51SLei YU /** @brief Callback function for PSU inventory match. 139ad90ad51SLei YU * 140ad90ad51SLei YU * @param[in] msg - Data associated with subscribed signal 141ad90ad51SLei YU */ 142374fae56SPatrick Williams void onPsuInventoryChangedMsg(sdbusplus::message_t& msg); 143a2c2cd72SLei YU 144*487e2e19SShawn McCarney /** @brief Called when a PSU inventory object has changed 145a2c2cd72SLei YU * @details Update an Activation D-Bus object for PSU inventory. 146*487e2e19SShawn McCarney * Throws an exception if an error occurs. 147a2c2cd72SLei YU * 148a2c2cd72SLei YU * @param[in] psuPath - The PSU inventory path 149a2c2cd72SLei YU * @param[in] properties - The updated properties 150a2c2cd72SLei YU */ 151a2c2cd72SLei YU void onPsuInventoryChanged(const std::string& psuPath, 152a2c2cd72SLei YU const Properties& properties); 153ad90ad51SLei YU 15401539e7eSLei YU /** @brief Create Activation object */ 15501539e7eSLei YU std::unique_ptr<Activation> createActivationObject( 15601539e7eSLei YU const std::string& path, const std::string& versionId, 15758c26e3fSLei YU const std::string& extVersion, Activation::Status activationStatus, 1589930137bSLei YU const AssociationList& assocs, const std::string& filePath); 15901539e7eSLei YU 16001539e7eSLei YU /** @brief Create Version object */ 161bab5ed99SPatrick Williams std::unique_ptr<Version> createVersionObject( 162bab5ed99SPatrick Williams const std::string& objPath, const std::string& versionId, 16301539e7eSLei YU const std::string& versionString, 164bab5ed99SPatrick Williams sdbusplus::xyz::openbmc_project::Software::server::Version:: 165bab5ed99SPatrick Williams VersionPurpose versionPurpose); 16601539e7eSLei YU 167bd3b0076SLei YU /** @brief Create Activation and Version object for PSU inventory 168bd3b0076SLei YU * @details If the same version exists for multiple PSUs, just add 169bd3b0076SLei YU * related association, instead of creating new objects. 170bd3b0076SLei YU * */ 171ad90ad51SLei YU void createPsuObject(const std::string& psuInventoryPath, 172ad90ad51SLei YU const std::string& psuVersion); 173ad90ad51SLei YU 174bd3b0076SLei YU /** @brief Remove Activation and Version object for PSU inventory 17533cf9f08SManojkiran Eda * @details If the same version exists for multiple PSUs, just remove 176bd3b0076SLei YU * related association. 177bd3b0076SLei YU * If the version has no association, the Activation and 178bd3b0076SLei YU * Version object will be removed 179bd3b0076SLei YU */ 180bd3b0076SLei YU void removePsuObject(const std::string& psuInventoryPath); 181bd3b0076SLei YU 18273a6f0d8SShawn McCarney /** @brief Add PSU inventory path to the PSU status map 183783406e6SShawn McCarney * @details Also adds a PropertiesChanged listener for the inventory path 184783406e6SShawn McCarney * so we are notified when the Present property changes. 18573a6f0d8SShawn McCarney * Does nothing if the inventory path already exists in the map. 18673a6f0d8SShawn McCarney * 18773a6f0d8SShawn McCarney * @param[in] psuPath - The PSU inventory path 18873a6f0d8SShawn McCarney */ 18973a6f0d8SShawn McCarney void addPsuToStatusMap(const std::string& psuPath); 19073a6f0d8SShawn McCarney 191783406e6SShawn McCarney /** @brief Handle a change in presence for a PSU. 192783406e6SShawn McCarney * 193783406e6SShawn McCarney * @param[in] psuPath - The PSU inventory path 194783406e6SShawn McCarney */ 195783406e6SShawn McCarney void handlePSUPresenceChanged(const std::string& psuPath); 196783406e6SShawn McCarney 197ad90ad51SLei YU /** 198ad90ad51SLei YU * @brief Create and populate the active PSU Version. 199ad90ad51SLei YU */ 200ad90ad51SLei YU void processPSUImage(); 201ad90ad51SLei YU 20258c26e3fSLei YU /** @brief Create PSU Version from stored images */ 20358c26e3fSLei YU void processStoredImage(); 20458c26e3fSLei YU 205*487e2e19SShawn McCarney /** @brief Scan a directory and create PSU Version from stored images 206*487e2e19SShawn McCarney * @details Throws an exception if an error occurs 207*487e2e19SShawn McCarney * 208*487e2e19SShawn McCarney * @param[in] dir Directory path to scan 209*487e2e19SShawn McCarney */ 210*487e2e19SShawn McCarney void scanDirectory(const fs::path& dir); 211*487e2e19SShawn McCarney 212*487e2e19SShawn McCarney /** @brief Find the PSU model subdirectory within the specified directory 213*487e2e19SShawn McCarney * @details Throws an exception if an error occurs 214*487e2e19SShawn McCarney * 215*487e2e19SShawn McCarney * @param[in] dir Directory path to search 216*487e2e19SShawn McCarney * 217*487e2e19SShawn McCarney * @return Subdirectory path, or an empty path if none found 218*487e2e19SShawn McCarney */ 219*487e2e19SShawn McCarney fs::path findModelDirectory(const fs::path& dir); 22058c26e3fSLei YU 2216520748dSLei YU /** @brief Get the versionId of the latest PSU version */ 2226520748dSLei YU std::optional<std::string> getLatestVersionId(); 2236520748dSLei YU 22463f9e712SLei YU /** @brief Update PSUs to the latest version */ 22563f9e712SLei YU void syncToLatestImage(); 22663f9e712SLei YU 22763f9e712SLei YU /** @brief Invoke the activation via DBus */ 22880c2daaeSGeorge Liu static void invokeActivation(const std::unique_ptr<Activation>& activation); 22963f9e712SLei YU 230760053d8SFaisal Awada /** @brief Callback function for interfaces added signal. 231760053d8SFaisal Awada * 232*487e2e19SShawn McCarney * This method is called when new interfaces are added. It updates the 233*487e2e19SShawn McCarney * internal status map and processes the new PSU if it's present. 234760053d8SFaisal Awada * 235760053d8SFaisal Awada * @param[in] msg - Data associated with subscribed signal 236760053d8SFaisal Awada */ 237*487e2e19SShawn McCarney void onPSUInterfacesAdded(sdbusplus::message_t& msg); 238760053d8SFaisal Awada 239760053d8SFaisal Awada /** 240760053d8SFaisal Awada * @brief Handles the processing of PSU images. 241760053d8SFaisal Awada * 242760053d8SFaisal Awada * This function responsible for invoking the sequence of processing PSU 243760053d8SFaisal Awada * images, processing stored images, and syncing to the latest firmware 244760053d8SFaisal Awada * image. 245760053d8SFaisal Awada */ 246760053d8SFaisal Awada void processPSUImageAndSyncToLatest(); 247760053d8SFaisal Awada 248fb86e794SFaisal Awada /** @brief Retrieve FW version from IMG_DIR_BUILTIN 249fb86e794SFaisal Awada * 250fb86e794SFaisal Awada * This function retrieves the firmware version from the PSU model directory 251fb86e794SFaisal Awada * that is in the IMG_DIR_BUILTIN. It loops through the activations map to 252fb86e794SFaisal Awada * find matching path starts with IMG_DIR_BUILTIN, then gets the 253fb86e794SFaisal Awada * corresponding version ID, and then looks it up in the versions map to 254fb86e794SFaisal Awada * retrieve the associated version string. 255fb86e794SFaisal Awada */ 256fb86e794SFaisal Awada std::string getFWVersionFromBuiltinDir(); 257fb86e794SFaisal Awada 25801539e7eSLei YU /** @brief Persistent sdbusplus D-Bus bus connection. */ 259374fae56SPatrick Williams sdbusplus::bus_t& bus; 26001539e7eSLei YU 26101539e7eSLei YU /** @brief Persistent map of Activation D-Bus objects and their 26201539e7eSLei YU * version id */ 26301539e7eSLei YU std::map<std::string, std::unique_ptr<Activation>> activations; 26401539e7eSLei YU 26501539e7eSLei YU /** @brief Persistent map of Version D-Bus objects and their 26601539e7eSLei YU * version id */ 26701539e7eSLei YU std::map<std::string, std::unique_ptr<Version>> versions; 26801539e7eSLei YU 269bd3b0076SLei YU /** @brief The reference map of PSU Inventory objects and the 270bd3b0076SLei YU * Activation*/ 271bd3b0076SLei YU std::map<std::string, const std::unique_ptr<Activation>&> 272bd3b0076SLei YU psuPathActivationMap; 273bd3b0076SLei YU 274ad90ad51SLei YU /** @brief sdbusplus signal match for PSU Software*/ 27501539e7eSLei YU sdbusplus::bus::match_t versionMatch; 27691029448SLei YU 277ad90ad51SLei YU /** @brief sdbusplus signal matches for PSU Inventory */ 278ad90ad51SLei YU std::vector<sdbusplus::bus::match_t> psuMatches; 279ad90ad51SLei YU 28091029448SLei YU /** @brief This entry's associations */ 28191029448SLei YU AssociationList assocs; 2826520748dSLei YU 2836520748dSLei YU /** @brief A collection of the version strings */ 2846520748dSLei YU std::set<std::string> versionStrings; 2851517f5f6SLei YU 2861517f5f6SLei YU /** @brief A struct to hold the PSU present status and model */ 2871517f5f6SLei YU struct psuStatus 2881517f5f6SLei YU { 2891517f5f6SLei YU bool present; 2901517f5f6SLei YU std::string model; 2911517f5f6SLei YU }; 2921517f5f6SLei YU 2931517f5f6SLei YU /** @brief The map of PSU inventory path and the psuStatus 2941517f5f6SLei YU * 2951517f5f6SLei YU * It is used to handle psu inventory changed event, that only create psu 2961517f5f6SLei YU * software object when a PSU is present and the model is retrieved */ 2971517f5f6SLei YU std::map<std::string, psuStatus> psuStatusMap; 298760053d8SFaisal Awada 299760053d8SFaisal Awada /** @brief Signal match for PSU interfaces added. 300760053d8SFaisal Awada * 301760053d8SFaisal Awada * This match listens for D-Bus signals indicating new interface has been 302760053d8SFaisal Awada * added. When such a signal received, it triggers the 303760053d8SFaisal Awada * `onInterfacesAdded` method to handle the new PSU. 304760053d8SFaisal Awada */ 305760053d8SFaisal Awada sdbusplus::bus::match_t psuInterfaceMatch; 30601539e7eSLei YU }; 30701539e7eSLei YU 30801539e7eSLei YU } // namespace updater 30901539e7eSLei YU } // namespace software 31001539e7eSLei YU } // namespace phosphor 311