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 PropertiesChanged listeners for the inventory path so 168 * we are notified when the present or model properties change. 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 /** 176 * @brief Create and populate the active PSU Version. 177 */ 178 void processPSUImage(); 179 180 /** @brief Create PSU Version from stored images */ 181 void processStoredImage(); 182 183 /** @brief Scan a directory and create PSU Version from stored images */ 184 void scanDirectory(const fs::path& p); 185 186 /** @brief Get the versionId of the latest PSU version */ 187 std::optional<std::string> getLatestVersionId(); 188 189 /** @brief Update PSUs to the latest version */ 190 void syncToLatestImage(); 191 192 /** @brief Invoke the activation via DBus */ 193 static void invokeActivation(const std::unique_ptr<Activation>& activation); 194 195 /** @brief Callback function for interfaces added signal. 196 * 197 * This method is called when a new interface is added. It updates the 198 * internal status map and process the new PSU if it's present. 199 * 200 * @param[in] msg - Data associated with subscribed signal 201 */ 202 void onPSUInterfaceAdded(sdbusplus::message_t& msg); 203 204 /** 205 * @brief Handles the processing of PSU images. 206 * 207 * This function responsible for invoking the sequence of processing PSU 208 * images, processing stored images, and syncing to the latest firmware 209 * image. 210 */ 211 void processPSUImageAndSyncToLatest(); 212 213 /** @brief Retrieve FW version from IMG_DIR_BUILTIN 214 * 215 * This function retrieves the firmware version from the PSU model directory 216 * that is in the IMG_DIR_BUILTIN. It loops through the activations map to 217 * find matching path starts with IMG_DIR_BUILTIN, then gets the 218 * corresponding version ID, and then looks it up in the versions map to 219 * retrieve the associated version string. 220 */ 221 std::string getFWVersionFromBuiltinDir(); 222 223 /** @brief Persistent sdbusplus D-Bus bus connection. */ 224 sdbusplus::bus_t& bus; 225 226 /** @brief Persistent map of Activation D-Bus objects and their 227 * version id */ 228 std::map<std::string, std::unique_ptr<Activation>> activations; 229 230 /** @brief Persistent map of Version D-Bus objects and their 231 * version id */ 232 std::map<std::string, std::unique_ptr<Version>> versions; 233 234 /** @brief The reference map of PSU Inventory objects and the 235 * Activation*/ 236 std::map<std::string, const std::unique_ptr<Activation>&> 237 psuPathActivationMap; 238 239 /** @brief sdbusplus signal match for PSU Software*/ 240 sdbusplus::bus::match_t versionMatch; 241 242 /** @brief sdbusplus signal matches for PSU Inventory */ 243 std::vector<sdbusplus::bus::match_t> psuMatches; 244 245 /** @brief This entry's associations */ 246 AssociationList assocs; 247 248 /** @brief A collection of the version strings */ 249 std::set<std::string> versionStrings; 250 251 /** @brief A struct to hold the PSU present status and model */ 252 struct psuStatus 253 { 254 bool present; 255 std::string model; 256 }; 257 258 /** @brief The map of PSU inventory path and the psuStatus 259 * 260 * It is used to handle psu inventory changed event, that only create psu 261 * software object when a PSU is present and the model is retrieved */ 262 std::map<std::string, psuStatus> psuStatusMap; 263 264 /** @brief Signal match for PSU interfaces added. 265 * 266 * This match listens for D-Bus signals indicating new interface has been 267 * added. When such a signal received, it triggers the 268 * `onInterfacesAdded` method to handle the new PSU. 269 */ 270 sdbusplus::bus::match_t psuInterfaceMatch; 271 }; 272 273 } // namespace updater 274 } // namespace software 275 } // namespace phosphor 276