1 #pragma once
2 
3 #include "activation.hpp"
4 #include "item_updater_helper.hpp"
5 #include "org/openbmc/Associations/server.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/Common/FactoryReset/server.hpp>
11 #include <xyz/openbmc_project/Control/FieldMode/server.hpp>
12 
13 namespace phosphor
14 {
15 namespace software
16 {
17 namespace updater
18 {
19 
20 using ItemUpdaterInherit = sdbusplus::server::object::object<
21     sdbusplus::xyz::openbmc_project::Common::server::FactoryReset,
22     sdbusplus::xyz::openbmc_project::Control::server::FieldMode,
23     sdbusplus::org::openbmc::server::Associations,
24     sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll>;
25 
26 namespace MatchRules = sdbusplus::bus::match::rules;
27 using VersionClass = phosphor::software::manager::Version;
28 using AssociationList =
29     std::vector<std::tuple<std::string, std::string, std::string>>;
30 
31 /** @class ItemUpdater
32  *  @brief Manages the activation of the BMC version items.
33  */
34 class ItemUpdater : public ItemUpdaterInherit
35 {
36   public:
37     /*
38      * @brief Types of Activation status for image validation.
39      */
40     enum class ActivationStatus
41     {
42         ready,
43         invalid,
44         active
45     };
46 
47     /** @brief Constructs ItemUpdater
48      *
49      * @param[in] bus    - The D-Bus bus object
50      */
51     ItemUpdater(sdbusplus::bus::bus& bus, const std::string& path) :
52         ItemUpdaterInherit(bus, path.c_str(), false), bus(bus), helper(bus),
53         versionMatch(bus,
54                      MatchRules::interfacesAdded() +
55                          MatchRules::path("/xyz/openbmc_project/software"),
56                      std::bind(std::mem_fn(&ItemUpdater::createActivation),
57                                this, std::placeholders::_1))
58     {
59         setBMCInventoryPath();
60         processBMCImage();
61         restoreFieldModeStatus();
62         emit_object_added();
63     };
64 
65     /** @brief Save priority value to persistent storage (flash and optionally
66      *  a U-Boot environment variable)
67      *
68      *  @param[in] versionId - The Id of the version
69      *  @param[in] value - The priority value
70      *  @return None
71      */
72     void savePriority(const std::string& versionId, uint8_t value);
73 
74     /** @brief Sets the given priority free by incrementing
75      *  any existing priority with the same value by 1
76      *
77      *  @param[in] value - The priority that needs to be set free.
78      *  @param[in] versionId - The Id of the version for which we
79      *                         are trying to free up the priority.
80      *  @return None
81      */
82     void freePriority(uint8_t value, const std::string& versionId);
83 
84     /**
85      * @brief Create and populate the active BMC Version.
86      */
87     void processBMCImage();
88 
89     /**
90      * @brief Erase specified entry D-Bus object
91      *        if Action property is not set to Active
92      *
93      * @param[in] entryId - unique identifier of the entry
94      */
95     void erase(std::string entryId);
96 
97     /**
98      * @brief Deletes all versions except for the current one
99      */
100     void deleteAll();
101 
102     /** @brief Creates an active association to the
103      *  newly active software image
104      *
105      * @param[in]  path - The path to create the association to.
106      */
107     void createActiveAssociation(const std::string& path);
108 
109     /** @brief Removes an active association to the software image
110      *
111      * @param[in]  path - The path to remove the association from.
112      */
113     void removeActiveAssociation(const std::string& path);
114 
115     /** @brief Determine if the given priority is the lowest
116      *
117      *  @param[in] value - The priority that needs to be checked.
118      *
119      *  @return boolean corresponding to whether the given
120      *      priority is lowest.
121      */
122     bool isLowestPriority(uint8_t value);
123 
124     /**
125      * @brief Updates the U-Boot variables to point to the requested
126      *        versionId, so that the systems boots from this version on
127      *        the next reboot.
128      *
129      * @param[in] versionId - The version to point the system to boot from.
130      */
131     void updateUbootEnvVars(const std::string& versionId);
132 
133     /**
134      * @brief Updates the uboot variables to point to BMC version with lowest
135      *        priority, so that the system boots from this version on the
136      *        next boot.
137      */
138     void resetUbootEnvVars();
139 
140     /** @brief Brings the total number of active BMC versions to
141      *         ACTIVE_BMC_MAX_ALLOWED -1. This function is intended to be
142      *         run before activating a new BMC version. If this function
143      *         needs to delete any BMC version(s) it will delete the
144      *         version(s) with the highest priority, skipping the
145      *         functional BMC version.
146      *
147      * @param[in] caller - The Activation object that called this function.
148      */
149     void freeSpace(Activation& caller);
150 
151   private:
152     /** @brief Callback function for Software.Version match.
153      *  @details Creates an Activation D-Bus object.
154      *
155      * @param[in]  msg       - Data associated with subscribed signal
156      */
157     void createActivation(sdbusplus::message::message& msg);
158 
159     /**
160      * @brief Validates the presence of SquashFS image in the image dir.
161      *
162      * @param[in]  filePath  - The path to the image dir.
163      * @param[out] result    - ActivationStatus Enum.
164      *                         ready if validation was successful.
165      *                         invalid if validation fail.
166      *                         active if image is the current version.
167      *
168      */
169     ActivationStatus validateSquashFSImage(const std::string& filePath);
170 
171     /** @brief BMC factory reset - marks the read-write partition for
172      * recreation upon reboot. */
173     void reset() override;
174 
175     /**
176      * @brief Enables field mode, if value=true.
177      *
178      * @param[in]  value  - If true, enables field mode.
179      * @param[out] result - Returns the current state of field mode.
180      *
181      */
182     bool fieldModeEnabled(bool value) override;
183 
184     /** @brief Sets the BMC inventory item path under
185      *  /xyz/openbmc_project/inventory/system/chassis/. */
186     void setBMCInventoryPath();
187 
188     /** @brief The path to the BMC inventory item. */
189     std::string bmcInventoryPath;
190 
191     /** @brief Restores field mode status on reboot. */
192     void restoreFieldModeStatus();
193 
194     /** @brief Creates a functional association to the
195      *  "running" BMC software image
196      *
197      * @param[in]  path - The path to create the association to.
198      */
199     void createFunctionalAssociation(const std::string& path);
200 
201     /** @brief Persistent sdbusplus D-Bus bus connection. */
202     sdbusplus::bus::bus& bus;
203 
204     /** @brief The helper of image updater. */
205     Helper helper;
206 
207     /** @brief Persistent map of Activation D-Bus objects and their
208      * version id */
209     std::map<std::string, std::unique_ptr<Activation>> activations;
210 
211     /** @brief Persistent map of Version D-Bus objects and their
212      * version id */
213     std::map<std::string, std::unique_ptr<VersionClass>> versions;
214 
215     /** @brief sdbusplus signal match for Software.Version */
216     sdbusplus::bus::match_t versionMatch;
217 
218     /** @brief This entry's associations */
219     AssociationList assocs = {};
220 
221     /** @brief Clears read only partition for
222      * given Activation D-Bus object.
223      *
224      * @param[in]  versionId - The version id.
225      */
226     void removeReadOnlyPartition(std::string versionId);
227 
228     /** @brief Copies U-Boot from the currently booted BMC chip to the
229      *  alternate chip.
230      */
231     void mirrorUbootToAlt();
232 };
233 
234 } // namespace updater
235 } // namespace software
236 } // namespace phosphor
237