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 
94         if (minimum_ship_level::enabled())
95         {
96             minimumVersionObject = std::make_unique<MinimumVersion>(bus, path);
97             minimumVersionObject->minimumVersion(
98                 minimum_ship_level::getMinimumVersion());
99         }
100 
101         emit_object_added();
102     };
103 
104     /** @brief Save priority value to persistent storage (flash and optionally
105      *  a U-Boot environment variable)
106      *
107      *  @param[in] versionId - The Id of the version
108      *  @param[in] value - The priority value
109      *  @return None
110      */
111     void savePriority(const std::string& versionId, uint8_t value);
112 
113     /** @brief Sets the given priority free by incrementing
114      *  any existing priority with the same value by 1
115      *
116      *  @param[in] value - The priority that needs to be set free.
117      *  @param[in] versionId - The Id of the version for which we
118      *                         are trying to free up the priority.
119      *  @return None
120      */
121     void freePriority(uint8_t value, const std::string& versionId);
122 
123     /**
124      * @brief Create and populate the active BMC Version.
125      */
126     void processBMCImage();
127 
128     /**
129      * @brief Erase specified entry D-Bus object
130      *        if Action property is not set to Active
131      *
132      * @param[in] entryId - unique identifier of the entry
133      */
134     void erase(std::string entryId);
135 
136     /**
137      * @brief Deletes all versions except for the current one
138      */
139     void deleteAll();
140 
141     /** @brief Creates an active association to the
142      *  newly active software image
143      *
144      * @param[in]  path - The path to create the association to.
145      */
146     void createActiveAssociation(const std::string& path);
147 
148     /** @brief Removes the associations from the provided software image path
149      *
150      * @param[in]  path - The path to remove the associations from.
151      */
152     void removeAssociations(const std::string& path);
153 
154     /** @brief Determine if the given priority is the lowest
155      *
156      *  @param[in] value - The priority that needs to be checked.
157      *
158      *  @return boolean corresponding to whether the given
159      *      priority is lowest.
160      */
161     bool isLowestPriority(uint8_t value);
162 
163     /**
164      * @brief Updates the U-Boot variables to point to the requested
165      *        versionId, so that the systems boots from this version on
166      *        the next reboot.
167      *
168      * @param[in] versionId - The version to point the system to boot from.
169      */
170     void updateUbootEnvVars(const std::string& versionId);
171 
172     /**
173      * @brief Updates the uboot variables to point to BMC version with lowest
174      *        priority, so that the system boots from this version on the
175      *        next boot.
176      */
177     void resetUbootEnvVars();
178 
179     /** @brief Brings the total number of active BMC versions to
180      *         ACTIVE_BMC_MAX_ALLOWED -1. This function is intended to be
181      *         run before activating a new BMC version. If this function
182      *         needs to delete any BMC version(s) it will delete the
183      *         version(s) with the highest priority, skipping the
184      *         functional BMC version.
185      *
186      * @param[in] caller - The Activation object that called this function.
187      */
188     void freeSpace(const Activation& caller);
189 
190     /** @brief Creates a updateable association to the
191      *  "running" BMC software image
192      *
193      * @param[in]  path - The path to create the association.
194      */
195     void createUpdateableAssociation(const std::string& path);
196 
197     /** @brief Persistent map of Version D-Bus objects and their
198      * version id */
199     std::map<std::string, std::unique_ptr<VersionClass>> versions;
200 
201     /** @brief Vector of needed BMC images in the tarball*/
202     std::vector<std::string> imageUpdateList;
203 
204     /** @breif The slot of running BMC image */
205     uint32_t runningImageSlot = 0;
206 
207   private:
208     /** @brief Callback function for Software.Version match.
209      *  @details Creates an Activation D-Bus object.
210      *
211      * @param[in]  msg       - Data associated with subscribed signal
212      */
213     void createActivation(sdbusplus::message_t& msg);
214 
215     /**
216      * @brief Validates the presence of SquashFS image in the image dir.
217      *
218      * @param[in]  filePath  - The path to the image dir.
219      * @param[out] result    - ActivationStatus Enum.
220      *                         ready if validation was successful.
221      *                         invalid if validation fail.
222      *                         active if image is the current version.
223      *
224      */
225     ActivationStatus validateSquashFSImage(const std::string& filePath);
226 
227     /** @brief BMC factory reset - marks the read-write partition for
228      * recreation upon reboot. */
229     void reset() override;
230 
231     /**
232      * @brief Enables field mode, if value=true.
233      *
234      * @param[in]  value  - If true, enables field mode.
235      * @param[out] result - Returns the current state of field mode.
236      *
237      */
238     bool fieldModeEnabled(bool value) override;
239 
240     /** @brief Sets the BMC inventory item path under
241      *  /xyz/openbmc_project/inventory/system/chassis/. */
242     void setBMCInventoryPath();
243 
244     /** @brief The path to the BMC inventory item. */
245     std::string bmcInventoryPath;
246 
247     /** @brief Restores field mode status on reboot. */
248     void restoreFieldModeStatus();
249 
250     /** @brief Creates a functional association to the
251      *  "running" BMC software image
252      *
253      * @param[in]  path - The path to create the association to.
254      */
255     void createFunctionalAssociation(const std::string& path);
256 
257     /** @brief Persistent sdbusplus D-Bus bus connection. */
258     sdbusplus::bus_t& bus;
259 
260     /** @brief The helper of image updater. */
261     Helper helper;
262 
263     /** @brief Persistent map of Activation D-Bus objects and their
264      * version id */
265     std::map<std::string, std::unique_ptr<Activation>> activations;
266 
267     /** @brief sdbusplus signal match for Software.Version */
268     sdbusplus::bus::match_t versionMatch;
269 
270     /** @brief This entry's associations */
271     AssociationList assocs = {};
272 
273     /** @brief Clears read only partition for
274      * given Activation D-Bus object.
275      *
276      * @param[in]  versionId - The version id.
277      */
278     void removeReadOnlyPartition(std::string versionId);
279 
280     /** @brief Copies U-Boot from the currently booted BMC chip to the
281      *  alternate chip.
282      */
283     void mirrorUbootToAlt();
284 
285     /** @brief Check the required image files
286      *
287      * @param[in] filePath - BMC tarball file path
288      * @param[in] imageList - Image filenames included in the BMC tarball
289      * @param[out] result - Boolean
290      *                      true if all image files are found in BMC tarball
291      *                      false if one of image files is missing
292      */
293     bool checkImage(const std::string& filePath,
294                     const std::vector<std::string>& imageList);
295 
296     /** @brief Persistent MinimumVersion D-Bus object */
297     std::unique_ptr<MinimumVersion> minimumVersionObject;
298 
299 #ifdef HOST_BIOS_UPGRADE
300     /** @brief Create the BIOS object without knowing the version.
301      *
302      *  The object is created only to provide the DBus access so that an
303      *  external service could set the correct BIOS version.
304      *  On BIOS code update, the version is updated accordingly.
305      */
306     void createBIOSObject();
307 
308     /** @brief Persistent Activation D-Bus object for BIOS */
309     std::unique_ptr<Activation> biosActivation;
310 
311   public:
312     /** @brief Persistent Version D-Bus object for BIOS */
313     std::unique_ptr<VersionClass> biosVersion;
314 #endif
315 
316     /** @brief Get the slot number of running image */
317     void getRunningSlot();
318 };
319 
320 } // namespace updater
321 } // namespace software
322 } // namespace phosphor
323