blob: 885847a680fec35581d8e317e1b3008705f3afec [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>
17
Lei YUf77189f2019-08-07 14:26:30 +080018class TestItemUpdater;
19
Lei YU01539e72019-07-31 10:57:38 +080020namespace phosphor
21{
22namespace software
23{
24namespace updater
25{
26
27class Version;
28
Patrick Williams374fae52022-07-22 19:26:55 -050029using ItemUpdaterInherit = sdbusplus::server::object_t<
Lei YUa5c47bb2019-09-29 11:28:53 +080030 sdbusplus::xyz::openbmc_project::Association::server::Definitions>;
31
Lei YU01539e72019-07-31 10:57:38 +080032namespace MatchRules = sdbusplus::bus::match::rules;
33
Lei YU58c26e32019-09-27 17:52:06 +080034namespace fs = std::filesystem;
35
Lei YU01539e72019-07-31 10:57:38 +080036/** @class ItemUpdater
37 * @brief Manages the activation of the PSU version items.
38 */
Patrick Williams5670b182023-05-10 07:50:50 -050039class ItemUpdater :
40 public ItemUpdaterInherit,
41 public AssociationInterface,
42 public ActivationListener
Lei YU01539e72019-07-31 10:57:38 +080043{
Lei YUf77189f2019-08-07 14:26:30 +080044 friend class ::TestItemUpdater;
45
Lei YU01539e72019-07-31 10:57:38 +080046 public:
47 /** @brief Constructs ItemUpdater
48 *
49 * @param[in] bus - The D-Bus bus object
50 * @param[in] path - The D-Bus path
51 */
Patrick Williams374fae52022-07-22 19:26:55 -050052 ItemUpdater(sdbusplus::bus_t& bus, const std::string& path) :
Lei YU01539e72019-07-31 10:57:38 +080053 ItemUpdaterInherit(bus, path.c_str()), bus(bus),
Patrick Williamsbab5ed92024-08-16 15:20:54 -040054 versionMatch(
55 bus,
56 MatchRules::interfacesAdded() + MatchRules::path(SOFTWARE_OBJPATH),
57 std::bind(std::mem_fn(&ItemUpdater::createActivation), this,
58 std::placeholders::_1)),
Faisal Awada760053d2024-05-16 13:31:32 -050059 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))
Lei YU01539e72019-07-31 10:57:38 +080066 {
Faisal Awada760053d2024-05-16 13:31:32 -050067 processPSUImageAndSyncToLatest();
Lei YU01539e72019-07-31 10:57:38 +080068 }
69
70 /** @brief Deletes version
71 *
72 * @param[in] versionId - Id of the version to delete
73 */
Lei YUa5c47bb2019-09-29 11:28:53 +080074 void erase(const std::string& versionId);
Lei YU01539e72019-07-31 10:57:38 +080075
Lei YU91029442019-08-01 15:57:31 +080076 /** @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 */
Lei YU7f2a2152019-09-16 16:50:18 +080081 void createActiveAssociation(const std::string& path) override;
Lei YU91029442019-08-01 15:57:31 +080082
Lei YUad90ad52019-08-06 11:19:28 +080083 /** @brief Add the functional association to the
Lei YU91029442019-08-01 15:57:31 +080084 * new "running" PSU images
85 *
Lei YUad90ad52019-08-06 11:19:28 +080086 * @param[in] path - The path to add the association to.
Lei YU91029442019-08-01 15:57:31 +080087 */
Lei YU7f2a2152019-09-16 16:50:18 +080088 void addFunctionalAssociation(const std::string& path) override;
Lei YU91029442019-08-01 15:57:31 +080089
Lei YUa8b966f2020-03-18 10:32:24 +080090 /** @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
Lei YU91029442019-08-01 15:57:31 +080097 /** @brief Removes the associations from the provided software image path
98 *
99 * @param[in] path - The path to remove the association from.
100 */
Lei YU7f2a2152019-09-16 16:50:18 +0800101 void removeAssociation(const std::string& path) override;
Lei YU91029442019-08-01 15:57:31 +0800102
Lei YUffb36532019-10-15 13:55:24 +0800103 /** @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
Lei YU7f2a2152019-09-16 16:50:18 +0800111 private:
Lei YU01539e72019-07-31 10:57:38 +0800112 /** @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 */
Patrick Williams374fae52022-07-22 19:26:55 -0500117 void createActivation(sdbusplus::message_t& msg);
Lei YU01539e72019-07-31 10:57:38 +0800118
Lei YUa2c2cd72019-08-09 15:54:10 +0800119 using Properties =
120 std::map<std::string, utils::UtilsInterface::PropertyType>;
121
Lei YUad90ad52019-08-06 11:19:28 +0800122 /** @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 */
Patrick Williams374fae52022-07-22 19:26:55 -0500127 void onPsuInventoryChangedMsg(sdbusplus::message_t& msg);
Lei YUa2c2cd72019-08-09 15:54:10 +0800128
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);
Lei YUad90ad52019-08-06 11:19:28 +0800137
Lei YU01539e72019-07-31 10:57:38 +0800138 /** @brief Create Activation object */
139 std::unique_ptr<Activation> createActivationObject(
140 const std::string& path, const std::string& versionId,
Lei YU58c26e32019-09-27 17:52:06 +0800141 const std::string& extVersion, Activation::Status activationStatus,
Lei YU99301372019-09-29 16:27:12 +0800142 const AssociationList& assocs, const std::string& filePath);
Lei YU01539e72019-07-31 10:57:38 +0800143
144 /** @brief Create Version object */
Patrick Williamsbab5ed92024-08-16 15:20:54 -0400145 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);
Lei YU01539e72019-07-31 10:57:38 +0800150
Lei YUbd3b0072019-08-08 13:09:50 +0800151 /** @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 * */
Lei YUad90ad52019-08-06 11:19:28 +0800155 void createPsuObject(const std::string& psuInventoryPath,
156 const std::string& psuVersion);
157
Lei YUbd3b0072019-08-08 13:09:50 +0800158 /** @brief Remove Activation and Version object for PSU inventory
Manojkiran Eda33cf9f02024-06-17 14:40:44 +0530159 * @details If the same version exists for multiple PSUs, just remove
Lei YUbd3b0072019-08-08 13:09:50 +0800160 * 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
Shawn McCarney73a6f0d2024-10-30 16:11:29 -0500166 /** @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
Lei YUad90ad52019-08-06 11:19:28 +0800175 /**
176 * @brief Create and populate the active PSU Version.
177 */
178 void processPSUImage();
179
Lei YU58c26e32019-09-27 17:52:06 +0800180 /** @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
Lei YU65207482019-10-11 16:39:36 +0800186 /** @brief Get the versionId of the latest PSU version */
187 std::optional<std::string> getLatestVersionId();
188
Lei YU63f9e712019-10-12 15:16:55 +0800189 /** @brief Update PSUs to the latest version */
190 void syncToLatestImage();
191
192 /** @brief Invoke the activation via DBus */
George Liu80c2daa2024-08-23 15:46:12 +0800193 static void invokeActivation(const std::unique_ptr<Activation>& activation);
Lei YU63f9e712019-10-12 15:16:55 +0800194
Faisal Awada760053d2024-05-16 13:31:32 -0500195 /** @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
Faisal Awadafb86e792024-09-11 10:51:17 -0500213 /** @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
Lei YU01539e72019-07-31 10:57:38 +0800223 /** @brief Persistent sdbusplus D-Bus bus connection. */
Patrick Williams374fae52022-07-22 19:26:55 -0500224 sdbusplus::bus_t& bus;
Lei YU01539e72019-07-31 10:57:38 +0800225
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
Lei YUbd3b0072019-08-08 13:09:50 +0800234 /** @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
Lei YUad90ad52019-08-06 11:19:28 +0800239 /** @brief sdbusplus signal match for PSU Software*/
Lei YU01539e72019-07-31 10:57:38 +0800240 sdbusplus::bus::match_t versionMatch;
Lei YU91029442019-08-01 15:57:31 +0800241
Lei YUad90ad52019-08-06 11:19:28 +0800242 /** @brief sdbusplus signal matches for PSU Inventory */
243 std::vector<sdbusplus::bus::match_t> psuMatches;
244
Lei YU91029442019-08-01 15:57:31 +0800245 /** @brief This entry's associations */
246 AssociationList assocs;
Lei YU65207482019-10-11 16:39:36 +0800247
248 /** @brief A collection of the version strings */
249 std::set<std::string> versionStrings;
Lei YU1517f5f2019-10-14 16:44:42 +0800250
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;
Faisal Awada760053d2024-05-16 13:31:32 -0500263
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;
Lei YU01539e72019-07-31 10:57:38 +0800271};
272
273} // namespace updater
274} // namespace software
275} // namespace phosphor