blob: e4d7b99f5768dc5ffe3dc3f6fa72bf9ed3294a05 [file] [log] [blame]
Lei YU01539e72019-07-31 10:57:38 +08001#pragma once
2
3#include "config.h"
4
5#include "activation.hpp"
Lei YU7f2a2152019-09-16 16:50:18 +08006#include "association_interface.hpp"
Lei YU91029442019-08-01 15:57:31 +08007#include "types.hpp"
Lei YU5e0dcb32019-08-02 18:04:34 +08008#include "utils.hpp"
Lei YU01539e72019-07-31 10:57:38 +08009#include "version.hpp"
10
Lei YU5e0dcb32019-08-02 18:04:34 +080011#include <phosphor-logging/log.hpp>
Lei YU01539e72019-07-31 10:57:38 +080012#include <sdbusplus/server.hpp>
Lei YU91029442019-08-01 15:57:31 +080013#include <xyz/openbmc_project/Association/Definitions/server.hpp>
Lei YU01539e72019-07-31 10:57:38 +080014#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
15
Patrick Williams5670b182023-05-10 07:50:50 -050016#include <filesystem>
Shawn McCarney487e2e12024-11-25 17:19:46 -060017#include <map>
18#include <string>
19#include <variant>
20#include <vector>
Patrick Williams5670b182023-05-10 07:50:50 -050021
Lei YUf77189f2019-08-07 14:26:30 +080022class TestItemUpdater;
23
Lei YU01539e72019-07-31 10:57:38 +080024namespace phosphor
25{
26namespace software
27{
28namespace updater
29{
30
31class Version;
32
Patrick Williams374fae52022-07-22 19:26:55 -050033using ItemUpdaterInherit = sdbusplus::server::object_t<
Lei YUa5c47bb2019-09-29 11:28:53 +080034 sdbusplus::xyz::openbmc_project::Association::server::Definitions>;
35
Lei YU01539e72019-07-31 10:57:38 +080036namespace MatchRules = sdbusplus::bus::match::rules;
37
Lei YU58c26e32019-09-27 17:52:06 +080038namespace fs = std::filesystem;
39
Lei YU01539e72019-07-31 10:57:38 +080040/** @class ItemUpdater
41 * @brief Manages the activation of the PSU version items.
42 */
Patrick Williams5670b182023-05-10 07:50:50 -050043class ItemUpdater :
44 public ItemUpdaterInherit,
45 public AssociationInterface,
46 public ActivationListener
Lei YU01539e72019-07-31 10:57:38 +080047{
Lei YUf77189f2019-08-07 14:26:30 +080048 friend class ::TestItemUpdater;
49
Lei YU01539e72019-07-31 10:57:38 +080050 public:
51 /** @brief Constructs ItemUpdater
52 *
53 * @param[in] bus - The D-Bus bus object
54 * @param[in] path - The D-Bus path
55 */
Patrick Williams374fae52022-07-22 19:26:55 -050056 ItemUpdater(sdbusplus::bus_t& bus, const std::string& path) :
Lei YU01539e72019-07-31 10:57:38 +080057 ItemUpdaterInherit(bus, path.c_str()), bus(bus),
Patrick Williamsbab5ed92024-08-16 15:20:54 -040058 versionMatch(
59 bus,
60 MatchRules::interfacesAdded() + MatchRules::path(SOFTWARE_OBJPATH),
Shawn McCarney487e2e12024-11-25 17:19:46 -060061 std::bind(std::mem_fn(&ItemUpdater::onVersionInterfacesAddedMsg),
62 this, std::placeholders::_1)),
Faisal Awada760053d2024-05-16 13:31:32 -050063 psuInterfaceMatch(
64 bus,
65 MatchRules::interfacesAdded() +
66 MatchRules::path("/xyz/openbmc_project/inventory") +
67 MatchRules::sender("xyz.openbmc_project.Inventory.Manager"),
Shawn McCarney487e2e12024-11-25 17:19:46 -060068 std::bind(std::mem_fn(&ItemUpdater::onPSUInterfacesAdded), this,
Faisal Awada760053d2024-05-16 13:31:32 -050069 std::placeholders::_1))
Lei YU01539e72019-07-31 10:57:38 +080070 {
Faisal Awada760053d2024-05-16 13:31:32 -050071 processPSUImageAndSyncToLatest();
Lei YU01539e72019-07-31 10:57:38 +080072 }
73
74 /** @brief Deletes version
75 *
76 * @param[in] versionId - Id of the version to delete
77 */
Lei YUa5c47bb2019-09-29 11:28:53 +080078 void erase(const std::string& versionId);
Lei YU01539e72019-07-31 10:57:38 +080079
Lei YU91029442019-08-01 15:57:31 +080080 /** @brief Creates an active association to the
81 * newly active software image
82 *
83 * @param[in] path - The path to create the association to.
84 */
Lei YU7f2a2152019-09-16 16:50:18 +080085 void createActiveAssociation(const std::string& path) override;
Lei YU91029442019-08-01 15:57:31 +080086
Lei YUad90ad52019-08-06 11:19:28 +080087 /** @brief Add the functional association to the
Lei YU91029442019-08-01 15:57:31 +080088 * new "running" PSU images
89 *
Lei YUad90ad52019-08-06 11:19:28 +080090 * @param[in] path - The path to add the association to.
Lei YU91029442019-08-01 15:57:31 +080091 */
Lei YU7f2a2152019-09-16 16:50:18 +080092 void addFunctionalAssociation(const std::string& path) override;
Lei YU91029442019-08-01 15:57:31 +080093
Lei YUa8b966f2020-03-18 10:32:24 +080094 /** @brief Add the updateable association to the
95 * "running" PSU software image
96 *
97 * @param[in] path - The path to create the association.
98 */
99 void addUpdateableAssociation(const std::string& path) override;
100
Lei YU91029442019-08-01 15:57:31 +0800101 /** @brief Removes the associations from the provided software image path
102 *
103 * @param[in] path - The path to remove the association from.
104 */
Lei YU7f2a2152019-09-16 16:50:18 +0800105 void removeAssociation(const std::string& path) override;
Lei YU91029442019-08-01 15:57:31 +0800106
Lei YUffb36532019-10-15 13:55:24 +0800107 /** @brief Notify a PSU is updated
108 *
109 * @param[in] versionId - The versionId of the activation
110 * @param[in] psuInventoryPath - The PSU inventory path that is updated
111 */
112 void onUpdateDone(const std::string& versionId,
113 const std::string& psuInventoryPath) override;
114
Lei YU7f2a2152019-09-16 16:50:18 +0800115 private:
Shawn McCarney487e2e12024-11-25 17:19:46 -0600116 using Properties =
117 std::map<std::string, utils::UtilsInterface::PropertyType>;
118 using InterfacesAddedMap =
119 std::map<std::string,
120 std::map<std::string, std::variant<bool, std::string>>>;
121
Lei YU01539e72019-07-31 10:57:38 +0800122 /** @brief Callback function for Software.Version match.
Lei YU01539e72019-07-31 10:57:38 +0800123 *
124 * @param[in] msg - Data associated with subscribed signal
125 */
Shawn McCarney487e2e12024-11-25 17:19:46 -0600126 void onVersionInterfacesAddedMsg(sdbusplus::message_t& msg);
Lei YU01539e72019-07-31 10:57:38 +0800127
Shawn McCarney487e2e12024-11-25 17:19:46 -0600128 /** @brief Called when new Software.Version interfaces are found
129 * @details Creates an Activation D-Bus object if appropriate
130 * Throws an exception if an error occurs.
131 *
132 * @param[in] path - D-Bus object path
133 * @param[in] interfaces - D-Bus interfaces that were added
134 */
135 void onVersionInterfacesAdded(const std::string& path,
136 const InterfacesAddedMap& interfaces);
Lei YUa2c2cd72019-08-09 15:54:10 +0800137
Lei YUad90ad52019-08-06 11:19:28 +0800138 /** @brief Callback function for PSU inventory match.
Lei YUad90ad52019-08-06 11:19:28 +0800139 *
140 * @param[in] msg - Data associated with subscribed signal
141 */
Patrick Williams374fae52022-07-22 19:26:55 -0500142 void onPsuInventoryChangedMsg(sdbusplus::message_t& msg);
Lei YUa2c2cd72019-08-09 15:54:10 +0800143
Shawn McCarney487e2e12024-11-25 17:19:46 -0600144 /** @brief Called when a PSU inventory object has changed
Lei YUa2c2cd72019-08-09 15:54:10 +0800145 * @details Update an Activation D-Bus object for PSU inventory.
Shawn McCarney487e2e12024-11-25 17:19:46 -0600146 * Throws an exception if an error occurs.
Lei YUa2c2cd72019-08-09 15:54:10 +0800147 *
148 * @param[in] psuPath - The PSU inventory path
149 * @param[in] properties - The updated properties
150 */
151 void onPsuInventoryChanged(const std::string& psuPath,
152 const Properties& properties);
Lei YUad90ad52019-08-06 11:19:28 +0800153
Lei YU01539e72019-07-31 10:57:38 +0800154 /** @brief Create Activation object */
155 std::unique_ptr<Activation> createActivationObject(
156 const std::string& path, const std::string& versionId,
Lei YU58c26e32019-09-27 17:52:06 +0800157 const std::string& extVersion, Activation::Status activationStatus,
Lei YU99301372019-09-29 16:27:12 +0800158 const AssociationList& assocs, const std::string& filePath);
Lei YU01539e72019-07-31 10:57:38 +0800159
160 /** @brief Create Version object */
Patrick Williamsbab5ed92024-08-16 15:20:54 -0400161 std::unique_ptr<Version> createVersionObject(
162 const std::string& objPath, const std::string& versionId,
163 const std::string& versionString,
164 sdbusplus::xyz::openbmc_project::Software::server::Version::
165 VersionPurpose versionPurpose);
Lei YU01539e72019-07-31 10:57:38 +0800166
Lei YUbd3b0072019-08-08 13:09:50 +0800167 /** @brief Create Activation and Version object for PSU inventory
168 * @details If the same version exists for multiple PSUs, just add
169 * related association, instead of creating new objects.
170 * */
Lei YUad90ad52019-08-06 11:19:28 +0800171 void createPsuObject(const std::string& psuInventoryPath,
172 const std::string& psuVersion);
173
Lei YUbd3b0072019-08-08 13:09:50 +0800174 /** @brief Remove Activation and Version object for PSU inventory
Manojkiran Eda33cf9f02024-06-17 14:40:44 +0530175 * @details If the same version exists for multiple PSUs, just remove
Lei YUbd3b0072019-08-08 13:09:50 +0800176 * related association.
177 * If the version has no association, the Activation and
178 * Version object will be removed
179 */
180 void removePsuObject(const std::string& psuInventoryPath);
181
Shawn McCarney73a6f0d2024-10-30 16:11:29 -0500182 /** @brief Add PSU inventory path to the PSU status map
Shawn McCarney783406e2024-11-17 21:49:37 -0600183 * @details Also adds a PropertiesChanged listener for the inventory path
184 * so we are notified when the Present property changes.
Shawn McCarney73a6f0d2024-10-30 16:11:29 -0500185 * Does nothing if the inventory path already exists in the map.
186 *
187 * @param[in] psuPath - The PSU inventory path
188 */
189 void addPsuToStatusMap(const std::string& psuPath);
190
Shawn McCarney783406e2024-11-17 21:49:37 -0600191 /** @brief Handle a change in presence for a PSU.
192 *
193 * @param[in] psuPath - The PSU inventory path
194 */
195 void handlePSUPresenceChanged(const std::string& psuPath);
196
Lei YUad90ad52019-08-06 11:19:28 +0800197 /**
198 * @brief Create and populate the active PSU Version.
199 */
200 void processPSUImage();
201
Lei YU58c26e32019-09-27 17:52:06 +0800202 /** @brief Create PSU Version from stored images */
203 void processStoredImage();
204
Shawn McCarney487e2e12024-11-25 17:19:46 -0600205 /** @brief Scan a directory and create PSU Version from stored images
206 * @details Throws an exception if an error occurs
207 *
208 * @param[in] dir Directory path to scan
209 */
210 void scanDirectory(const fs::path& dir);
211
212 /** @brief Find the PSU model subdirectory within the specified directory
213 * @details Throws an exception if an error occurs
214 *
215 * @param[in] dir Directory path to search
216 *
217 * @return Subdirectory path, or an empty path if none found
218 */
219 fs::path findModelDirectory(const fs::path& dir);
Lei YU58c26e32019-09-27 17:52:06 +0800220
Lei YU65207482019-10-11 16:39:36 +0800221 /** @brief Get the versionId of the latest PSU version */
222 std::optional<std::string> getLatestVersionId();
223
Lei YU63f9e712019-10-12 15:16:55 +0800224 /** @brief Update PSUs to the latest version */
225 void syncToLatestImage();
226
227 /** @brief Invoke the activation via DBus */
George Liu80c2daa2024-08-23 15:46:12 +0800228 static void invokeActivation(const std::unique_ptr<Activation>& activation);
Lei YU63f9e712019-10-12 15:16:55 +0800229
Faisal Awada760053d2024-05-16 13:31:32 -0500230 /** @brief Callback function for interfaces added signal.
231 *
Shawn McCarney487e2e12024-11-25 17:19:46 -0600232 * This method is called when new interfaces are added. It updates the
233 * internal status map and processes the new PSU if it's present.
Faisal Awada760053d2024-05-16 13:31:32 -0500234 *
235 * @param[in] msg - Data associated with subscribed signal
236 */
Shawn McCarney487e2e12024-11-25 17:19:46 -0600237 void onPSUInterfacesAdded(sdbusplus::message_t& msg);
Faisal Awada760053d2024-05-16 13:31:32 -0500238
239 /**
240 * @brief Handles the processing of PSU images.
241 *
242 * This function responsible for invoking the sequence of processing PSU
243 * images, processing stored images, and syncing to the latest firmware
244 * image.
245 */
246 void processPSUImageAndSyncToLatest();
247
Faisal Awadafb86e792024-09-11 10:51:17 -0500248 /** @brief Retrieve FW version from IMG_DIR_BUILTIN
249 *
250 * This function retrieves the firmware version from the PSU model directory
251 * that is in the IMG_DIR_BUILTIN. It loops through the activations map to
252 * find matching path starts with IMG_DIR_BUILTIN, then gets the
253 * corresponding version ID, and then looks it up in the versions map to
254 * retrieve the associated version string.
255 */
256 std::string getFWVersionFromBuiltinDir();
257
Lei YU01539e72019-07-31 10:57:38 +0800258 /** @brief Persistent sdbusplus D-Bus bus connection. */
Patrick Williams374fae52022-07-22 19:26:55 -0500259 sdbusplus::bus_t& bus;
Lei YU01539e72019-07-31 10:57:38 +0800260
261 /** @brief Persistent map of Activation D-Bus objects and their
262 * version id */
263 std::map<std::string, std::unique_ptr<Activation>> activations;
264
265 /** @brief Persistent map of Version D-Bus objects and their
266 * version id */
267 std::map<std::string, std::unique_ptr<Version>> versions;
268
Lei YUbd3b0072019-08-08 13:09:50 +0800269 /** @brief The reference map of PSU Inventory objects and the
270 * Activation*/
271 std::map<std::string, const std::unique_ptr<Activation>&>
272 psuPathActivationMap;
273
Lei YUad90ad52019-08-06 11:19:28 +0800274 /** @brief sdbusplus signal match for PSU Software*/
Lei YU01539e72019-07-31 10:57:38 +0800275 sdbusplus::bus::match_t versionMatch;
Lei YU91029442019-08-01 15:57:31 +0800276
Lei YUad90ad52019-08-06 11:19:28 +0800277 /** @brief sdbusplus signal matches for PSU Inventory */
278 std::vector<sdbusplus::bus::match_t> psuMatches;
279
Lei YU91029442019-08-01 15:57:31 +0800280 /** @brief This entry's associations */
281 AssociationList assocs;
Lei YU65207482019-10-11 16:39:36 +0800282
283 /** @brief A collection of the version strings */
284 std::set<std::string> versionStrings;
Lei YU1517f5f2019-10-14 16:44:42 +0800285
286 /** @brief A struct to hold the PSU present status and model */
287 struct psuStatus
288 {
289 bool present;
290 std::string model;
291 };
292
293 /** @brief The map of PSU inventory path and the psuStatus
294 *
295 * It is used to handle psu inventory changed event, that only create psu
296 * software object when a PSU is present and the model is retrieved */
297 std::map<std::string, psuStatus> psuStatusMap;
Faisal Awada760053d2024-05-16 13:31:32 -0500298
299 /** @brief Signal match for PSU interfaces added.
300 *
301 * This match listens for D-Bus signals indicating new interface has been
302 * added. When such a signal received, it triggers the
303 * `onInterfacesAdded` method to handle the new PSU.
304 */
305 sdbusplus::bus::match_t psuInterfaceMatch;
Lei YU01539e72019-07-31 10:57:38 +0800306};
307
308} // namespace updater
309} // namespace software
310} // namespace phosphor