xref: /openbmc/phosphor-bmc-code-mgmt/item_updater.hpp (revision fc33ba86773d2f02cee1093bea3e5da405028220)
1 #pragma once
2 
3 #include "activation.hpp"
4 #include "item_updater_helper.hpp"
5 #include "msl_verify.hpp"
6 #include "version.hpp"
7 #include "xyz/openbmc_project/Collection/DeleteAll/server.hpp"
8 
9 #include <sdbusplus/server.hpp>
10 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
11 #include <xyz/openbmc_project/Common/FactoryReset/server.hpp>
12 #include <xyz/openbmc_project/Control/FieldMode/server.hpp>
13 #include <xyz/openbmc_project/Software/MinimumVersion/server.hpp>
14 
15 #include <string>
16 #include <vector>
17 
18 namespace phosphor
19 {
20 namespace software
21 {
22 namespace updater
23 {
24 
25 using ItemUpdaterInherit = sdbusplus::server::object_t<
26     sdbusplus::server::xyz::openbmc_project::common::FactoryReset,
27     sdbusplus::server::xyz::openbmc_project::control::FieldMode,
28     sdbusplus::server::xyz::openbmc_project::association::Definitions,
29     sdbusplus::server::xyz::openbmc_project::collection::DeleteAll>;
30 using MinimumVersionInherit = sdbusplus::server::object_t<
31     sdbusplus::server::xyz::openbmc_project::software::MinimumVersion>;
32 
33 namespace MatchRules = sdbusplus::bus::match::rules;
34 using VersionClass = phosphor::software::manager::Version;
35 using AssociationList =
36     std::vector<std::tuple<std::string, std::string, std::string>>;
37 
38 /** @class MinimumVersion
39  *  @brief OpenBMC MinimumVersion implementation.
40  *  @details A concrete implementation for
41  *  xyz.openbmc_project.Software.MinimumVersion DBus API.
42  */
43 class MinimumVersion : public MinimumVersionInherit
44 {
45   public:
46     /** @brief Constructs MinimumVersion
47      *
48      * @param[in] bus - The D-Bus bus object
49      * @param[in] path - The D-bus object path
50      */
51     MinimumVersion(sdbusplus::bus_t& bus, const std::string& path) :
52         MinimumVersionInherit(bus, path.c_str(), action::emit_interface_added)
53     {}
54 };
55 
56 /** @class ItemUpdater
57  *  @brief Manages the activation of the BMC version items.
58  */
59 class ItemUpdater : public ItemUpdaterInherit
60 {
61   public:
62     /*
63      * @brief Types of Activation status for image validation.
64      */
65     enum class ActivationStatus
66     {
67         ready,
68         invalid,
69         active
70     };
71 
72     /** @brief Constructs ItemUpdater
73      *
74      * @param[in] bus    - The D-Bus bus object
75      */
76     ItemUpdater(sdbusplus::bus_t& bus, const std::string& path) :
77         ItemUpdaterInherit(bus, path.c_str(),
78                            ItemUpdaterInherit::action::defer_emit),
79         bus(bus), helper(bus),
80         versionMatch(bus,
81                      MatchRules::interfacesAdded() +
82                          MatchRules::path("/xyz/openbmc_project/software"),
83                      std::bind(std::mem_fn(&ItemUpdater::createActivation),
84                                this, std::placeholders::_1))
85     {
86         getRunningSlot();
87         setBMCInventoryPath();
88         processBMCImage();
89         restoreFieldModeStatus();
90 #ifdef HOST_BIOS_UPGRADE
91         createBIOSObject();
92 #endif
93         emit_object_added();
94     };
95 
96     /** @brief Save priority value to persistent storage (flash and optionally
97      *  a U-Boot environment variable)
98      *
99      *  @param[in] versionId - The Id of the version
100      *  @param[in] value - The priority value
101      *  @return None
102      */
103     void savePriority(const std::string& versionId, uint8_t value);
104 
105     /** @brief Sets the given priority free by incrementing
106      *  any existing priority with the same value by 1
107      *
108      *  @param[in] value - The priority that needs to be set free.
109      *  @param[in] versionId - The Id of the version for which we
110      *                         are trying to free up the priority.
111      *  @return None
112      */
113     void freePriority(uint8_t value, const std::string& versionId);
114 
115     /**
116      * @brief Create and populate the active BMC Version.
117      */
118     void processBMCImage();
119 
120     /**
121      * @brief Erase specified entry D-Bus object
122      *        if Action property is not set to Active
123      *
124      * @param[in] entryId - unique identifier of the entry
125      */
126     void erase(std::string entryId);
127 
128     /**
129      * @brief Deletes all versions except for the current one
130      */
131     void deleteAll() override;
132 
133     /** @brief Creates an active association to the
134      *  newly active software image
135      *
136      * @param[in]  path - The path to create the association to.
137      */
138     void createActiveAssociation(const std::string& path);
139 
140     /** @brief Removes the associations from the provided software image path
141      *
142      * @param[in]  path - The path to remove the associations from.
143      */
144     void removeAssociations(const std::string& path);
145 
146     /** @brief Determine if the given priority is the lowest
147      *
148      *  @param[in] value - The priority that needs to be checked.
149      *
150      *  @return boolean corresponding to whether the given
151      *      priority is lowest.
152      */
153     bool isLowestPriority(uint8_t value);
154 
155     /**
156      * @brief Updates the U-Boot variables to point to the requested
157      *        versionId, so that the systems boots from this version on
158      *        the next reboot.
159      *
160      * @param[in] versionId - The version to point the system to boot from.
161      */
162     void updateUbootEnvVars(const std::string& versionId);
163 
164     /**
165      * @brief Updates the uboot variables to point to BMC version with lowest
166      *        priority, so that the system boots from this version on the
167      *        next boot.
168      */
169     void resetUbootEnvVars();
170 
171     /** @brief Brings the total number of active BMC versions to
172      *         ACTIVE_BMC_MAX_ALLOWED -1. This function is intended to be
173      *         run before activating a new BMC version. If this function
174      *         needs to delete any BMC version(s) it will delete the
175      *         version(s) with the highest priority, skipping the
176      *         functional BMC version.
177      *
178      * @param[in] caller - The Activation object that called this function.
179      */
180     void freeSpace(const Activation& caller);
181 
182     /** @brief Creates a updateable association to the
183      *  "running" BMC software image
184      *
185      * @param[in]  path - The path to create the association.
186      */
187     void createUpdateableAssociation(const std::string& path);
188 
189     /** @brief Persistent map of Version D-Bus objects and their
190      * version id */
191     std::map<std::string, std::unique_ptr<VersionClass>> versions;
192 
193     /** @brief Vector of needed BMC images in the tarball*/
194     std::vector<std::string> imageUpdateList;
195 
196     /** @brief The slot of running BMC image */
197     uint32_t runningImageSlot = 0;
198 
199   private:
200     /** @brief Callback function for Software.Version match.
201      *  @details Creates an Activation D-Bus object.
202      *
203      * @param[in]  msg       - Data associated with subscribed signal
204      */
205     void createActivation(sdbusplus::message_t& msg);
206 
207     /**
208      * @brief Validates the presence of SquashFS image in the image dir.
209      *
210      * @param[in]  filePath  - The path to the image dir.
211      * @param[out] result    - ActivationStatus Enum.
212      *                         ready if validation was successful.
213      *                         invalid if validation fail.
214      *                         active if image is the current version.
215      *
216      */
217     ActivationStatus validateSquashFSImage(const std::string& filePath);
218 
219     /** @brief BMC factory reset - marks the read-write partition for
220      * recreation upon reboot. */
221     void reset() override;
222 
223     /**
224      * @brief Enables field mode, if value=true.
225      *
226      * @param[in]  value  - If true, enables field mode.
227      * @param[out] result - Returns the current state of field mode.
228      *
229      */
230     bool fieldModeEnabled(bool value) override;
231 
232     /** @brief Sets the BMC inventory item path under
233      *  /xyz/openbmc_project/inventory/system/chassis/. */
234     void setBMCInventoryPath();
235 
236     /** @brief The path to the BMC inventory item. */
237     std::string bmcInventoryPath;
238 
239     /** @brief Restores field mode status on reboot. */
240     void restoreFieldModeStatus();
241 
242     /** @brief Creates a functional association to the
243      *  "running" BMC software image
244      *
245      * @param[in]  path - The path to create the association to.
246      */
247     void createFunctionalAssociation(const std::string& path);
248 
249     /** @brief Persistent sdbusplus D-Bus bus connection. */
250     sdbusplus::bus_t& bus;
251 
252     /** @brief The helper of image updater. */
253     Helper helper;
254 
255     /** @brief Persistent map of Activation D-Bus objects and their
256      * version id */
257     std::map<std::string, std::unique_ptr<Activation>> activations;
258 
259     /** @brief sdbusplus signal match for Software.Version */
260     sdbusplus::bus::match_t versionMatch;
261 
262     /** @brief This entry's associations */
263     AssociationList assocs;
264 
265     /** @brief Clears read only partition for
266      * given Activation D-Bus object.
267      *
268      * @param[in]  versionId - The version id.
269      */
270     void removeReadOnlyPartition(const std::string& versionId);
271 
272     /** @brief Copies U-Boot from the currently booted BMC chip to the
273      *  alternate chip.
274      */
275     void mirrorUbootToAlt();
276 
277     /** @brief Check the required image files
278      *
279      * @param[in] filePath - BMC tarball file path
280      * @param[in] imageList - Image filenames included in the BMC tarball
281      * @param[out] result - Boolean
282      *                      true if all image files are found in BMC tarball
283      *                      false if one of image files is missing
284      */
285     static bool checkImage(const std::string& filePath,
286                            const std::vector<std::string>& imageList);
287 
288     /** @brief Persistent MinimumVersion D-Bus object */
289     std::unique_ptr<MinimumVersion> minimumVersionObject;
290 
291 #ifdef HOST_BIOS_UPGRADE
292     /** @brief Create the BIOS object without knowing the version.
293      *
294      *  The object is created only to provide the DBus access so that an
295      *  external service could set the correct BIOS version.
296      *  On BIOS code update, the version is updated accordingly.
297      */
298     void createBIOSObject();
299 
300     /** @brief Persistent Activation D-Bus object for BIOS */
301     std::unique_ptr<Activation> biosActivation;
302 
303   public:
304     /** @brief Persistent Version D-Bus object for BIOS */
305     std::unique_ptr<VersionClass> biosVersion;
306 #endif
307 
308     /** @brief Get the slot number of running image */
309     void getRunningSlot();
310 };
311 
312 } // namespace updater
313 } // namespace software
314 } // namespace phosphor
315