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