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