1 #pragma once 2 3 #include "config.h" 4 5 #include "activation.hpp" 6 #include "association_interface.hpp" 7 #include "types.hpp" 8 #include "utils.hpp" 9 #include "version.hpp" 10 11 #include <phosphor-logging/log.hpp> 12 #include <sdbusplus/server.hpp> 13 #include <xyz/openbmc_project/Association/Definitions/server.hpp> 14 #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp> 15 16 #include <filesystem> 17 18 class TestItemUpdater; 19 20 namespace phosphor 21 { 22 namespace software 23 { 24 namespace updater 25 { 26 27 class Version; 28 29 using ItemUpdaterInherit = sdbusplus::server::object_t< 30 sdbusplus::xyz::openbmc_project::Association::server::Definitions>; 31 32 namespace MatchRules = sdbusplus::bus::match::rules; 33 34 namespace fs = std::filesystem; 35 36 /** @class ItemUpdater 37 * @brief Manages the activation of the PSU version items. 38 */ 39 class ItemUpdater : 40 public ItemUpdaterInherit, 41 public AssociationInterface, 42 public ActivationListener 43 { 44 friend class ::TestItemUpdater; 45 46 public: 47 /** @brief Constructs ItemUpdater 48 * 49 * @param[in] bus - The D-Bus bus object 50 * @param[in] path - The D-Bus path 51 */ 52 ItemUpdater(sdbusplus::bus_t& bus, const std::string& path) : 53 ItemUpdaterInherit(bus, path.c_str()), bus(bus), 54 versionMatch( 55 bus, 56 MatchRules::interfacesAdded() + MatchRules::path(SOFTWARE_OBJPATH), 57 std::bind(std::mem_fn(&ItemUpdater::createActivation), this, 58 std::placeholders::_1)), 59 psuInterfaceMatch( 60 bus, 61 MatchRules::interfacesAdded() + 62 MatchRules::path("/xyz/openbmc_project/inventory") + 63 MatchRules::sender("xyz.openbmc_project.Inventory.Manager"), 64 std::bind(std::mem_fn(&ItemUpdater::onPSUInterfaceAdded), this, 65 std::placeholders::_1)) 66 { 67 processPSUImageAndSyncToLatest(); 68 } 69 70 /** @brief Deletes version 71 * 72 * @param[in] versionId - Id of the version to delete 73 */ 74 void erase(const std::string& versionId); 75 76 /** @brief Creates an active association to the 77 * newly active software image 78 * 79 * @param[in] path - The path to create the association to. 80 */ 81 void createActiveAssociation(const std::string& path) override; 82 83 /** @brief Add the functional association to the 84 * new "running" PSU images 85 * 86 * @param[in] path - The path to add the association to. 87 */ 88 void addFunctionalAssociation(const std::string& path) override; 89 90 /** @brief Add the updateable association to the 91 * "running" PSU software image 92 * 93 * @param[in] path - The path to create the association. 94 */ 95 void addUpdateableAssociation(const std::string& path) override; 96 97 /** @brief Removes the associations from the provided software image path 98 * 99 * @param[in] path - The path to remove the association from. 100 */ 101 void removeAssociation(const std::string& path) override; 102 103 /** @brief Notify a PSU is updated 104 * 105 * @param[in] versionId - The versionId of the activation 106 * @param[in] psuInventoryPath - The PSU inventory path that is updated 107 */ 108 void onUpdateDone(const std::string& versionId, 109 const std::string& psuInventoryPath) override; 110 111 private: 112 /** @brief Callback function for Software.Version match. 113 * @details Creates an Activation D-Bus object. 114 * 115 * @param[in] msg - Data associated with subscribed signal 116 */ 117 void createActivation(sdbusplus::message_t& msg); 118 119 using Properties = 120 std::map<std::string, utils::UtilsInterface::PropertyType>; 121 122 /** @brief Callback function for PSU inventory match. 123 * @details Update an Activation D-Bus object for PSU inventory. 124 * 125 * @param[in] msg - Data associated with subscribed signal 126 */ 127 void onPsuInventoryChangedMsg(sdbusplus::message_t& msg); 128 129 /** @brief Callback function for PSU inventory match. 130 * @details Update an Activation D-Bus object for PSU inventory. 131 * 132 * @param[in] psuPath - The PSU inventory path 133 * @param[in] properties - The updated properties 134 */ 135 void onPsuInventoryChanged(const std::string& psuPath, 136 const Properties& properties); 137 138 /** @brief Create Activation object */ 139 std::unique_ptr<Activation> createActivationObject( 140 const std::string& path, const std::string& versionId, 141 const std::string& extVersion, Activation::Status activationStatus, 142 const AssociationList& assocs, const std::string& filePath); 143 144 /** @brief Create Version object */ 145 std::unique_ptr<Version> createVersionObject( 146 const std::string& objPath, const std::string& versionId, 147 const std::string& versionString, 148 sdbusplus::xyz::openbmc_project::Software::server::Version:: 149 VersionPurpose versionPurpose); 150 151 /** @brief Create Activation and Version object for PSU inventory 152 * @details If the same version exists for multiple PSUs, just add 153 * related association, instead of creating new objects. 154 * */ 155 void createPsuObject(const std::string& psuInventoryPath, 156 const std::string& psuVersion); 157 158 /** @brief Remove Activation and Version object for PSU inventory 159 * @details If the same version exists for multiple PSUs, just remove 160 * related association. 161 * If the version has no association, the Activation and 162 * Version object will be removed 163 */ 164 void removePsuObject(const std::string& psuInventoryPath); 165 166 /** @brief Add PSU inventory path to the PSU status map 167 * @details Also adds a PropertiesChanged listener for the inventory path 168 * so we are notified when the Present property changes. 169 * Does nothing if the inventory path already exists in the map. 170 * 171 * @param[in] psuPath - The PSU inventory path 172 */ 173 void addPsuToStatusMap(const std::string& psuPath); 174 175 /** @brief Handle a change in presence for a PSU. 176 * 177 * @param[in] psuPath - The PSU inventory path 178 */ 179 void handlePSUPresenceChanged(const std::string& psuPath); 180 181 /** 182 * @brief Create and populate the active PSU Version. 183 */ 184 void processPSUImage(); 185 186 /** @brief Create PSU Version from stored images */ 187 void processStoredImage(); 188 189 /** @brief Scan a directory and create PSU Version from stored images */ 190 void scanDirectory(const fs::path& p); 191 192 /** @brief Get the versionId of the latest PSU version */ 193 std::optional<std::string> getLatestVersionId(); 194 195 /** @brief Update PSUs to the latest version */ 196 void syncToLatestImage(); 197 198 /** @brief Invoke the activation via DBus */ 199 static void invokeActivation(const std::unique_ptr<Activation>& activation); 200 201 /** @brief Callback function for interfaces added signal. 202 * 203 * This method is called when a new interface is added. It updates the 204 * internal status map and process the new PSU if it's present. 205 * 206 * @param[in] msg - Data associated with subscribed signal 207 */ 208 void onPSUInterfaceAdded(sdbusplus::message_t& msg); 209 210 /** 211 * @brief Handles the processing of PSU images. 212 * 213 * This function responsible for invoking the sequence of processing PSU 214 * images, processing stored images, and syncing to the latest firmware 215 * image. 216 */ 217 void processPSUImageAndSyncToLatest(); 218 219 /** @brief Retrieve FW version from IMG_DIR_BUILTIN 220 * 221 * This function retrieves the firmware version from the PSU model directory 222 * that is in the IMG_DIR_BUILTIN. It loops through the activations map to 223 * find matching path starts with IMG_DIR_BUILTIN, then gets the 224 * corresponding version ID, and then looks it up in the versions map to 225 * retrieve the associated version string. 226 */ 227 std::string getFWVersionFromBuiltinDir(); 228 229 /** @brief Persistent sdbusplus D-Bus bus connection. */ 230 sdbusplus::bus_t& bus; 231 232 /** @brief Persistent map of Activation D-Bus objects and their 233 * version id */ 234 std::map<std::string, std::unique_ptr<Activation>> activations; 235 236 /** @brief Persistent map of Version D-Bus objects and their 237 * version id */ 238 std::map<std::string, std::unique_ptr<Version>> versions; 239 240 /** @brief The reference map of PSU Inventory objects and the 241 * Activation*/ 242 std::map<std::string, const std::unique_ptr<Activation>&> 243 psuPathActivationMap; 244 245 /** @brief sdbusplus signal match for PSU Software*/ 246 sdbusplus::bus::match_t versionMatch; 247 248 /** @brief sdbusplus signal matches for PSU Inventory */ 249 std::vector<sdbusplus::bus::match_t> psuMatches; 250 251 /** @brief This entry's associations */ 252 AssociationList assocs; 253 254 /** @brief A collection of the version strings */ 255 std::set<std::string> versionStrings; 256 257 /** @brief A struct to hold the PSU present status and model */ 258 struct psuStatus 259 { 260 bool present; 261 std::string model; 262 }; 263 264 /** @brief The map of PSU inventory path and the psuStatus 265 * 266 * It is used to handle psu inventory changed event, that only create psu 267 * software object when a PSU is present and the model is retrieved */ 268 std::map<std::string, psuStatus> psuStatusMap; 269 270 /** @brief Signal match for PSU interfaces added. 271 * 272 * This match listens for D-Bus signals indicating new interface has been 273 * added. When such a signal received, it triggers the 274 * `onInterfacesAdded` method to handle the new PSU. 275 */ 276 sdbusplus::bus::match_t psuInterfaceMatch; 277 }; 278 279 } // namespace updater 280 } // namespace software 281 } // namespace phosphor 282