1 #pragma once
2 
3 #include "config.h"
4 
5 #include "flash.hpp"
6 #include "utils.hpp"
7 #include "xyz/openbmc_project/Software/ActivationProgress/server.hpp"
8 #include "xyz/openbmc_project/Software/RedundancyPriority/server.hpp"
9 
10 #include <sdbusplus/server.hpp>
11 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
12 #include <xyz/openbmc_project/Software/Activation/server.hpp>
13 #include <xyz/openbmc_project/Software/ActivationBlocksTransition/server.hpp>
14 
15 #ifdef WANT_SIGNATURE_VERIFY
16 #include <filesystem>
17 #endif
18 
19 namespace phosphor
20 {
21 namespace software
22 {
23 namespace updater
24 {
25 
26 #ifdef WANT_SIGNATURE_VERIFY
27 namespace fs = std::filesystem;
28 #endif
29 
30 using AssociationList =
31     std::vector<std::tuple<std::string, std::string, std::string>>;
32 using ActivationInherit = sdbusplus::server::object_t<
33     sdbusplus::server::xyz::openbmc_project::software::Activation,
34     sdbusplus::server::xyz::openbmc_project::association::Definitions>;
35 using ActivationBlocksTransitionInherit =
36     sdbusplus::server::object_t<sdbusplus::server::xyz::openbmc_project::
37                                     software::ActivationBlocksTransition>;
38 using RedundancyPriorityInherit = sdbusplus::server::object_t<
39     sdbusplus::server::xyz::openbmc_project::software::RedundancyPriority>;
40 using ActivationProgressInherit = sdbusplus::server::object_t<
41     sdbusplus::server::xyz::openbmc_project::software::ActivationProgress>;
42 
43 constexpr auto applyTimeImmediate =
44     "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.Immediate";
45 constexpr auto applyTimeIntf = "xyz.openbmc_project.Software.ApplyTime";
46 constexpr auto dbusPropIntf = "org.freedesktop.DBus.Properties";
47 constexpr auto applyTimeObjPath = "/xyz/openbmc_project/software/apply_time";
48 constexpr auto applyTimeProp = "RequestedApplyTime";
49 
50 namespace sdbusRule = sdbusplus::bus::match::rules;
51 
52 class ItemUpdater;
53 class Activation;
54 class RedundancyPriority;
55 
56 /** @class RedundancyPriority
57  *  @brief OpenBMC RedundancyPriority implementation
58  *  @details A concrete implementation for
59  *  xyz.openbmc_project.Software.RedundancyPriority DBus API.
60  */
61 class RedundancyPriority : public RedundancyPriorityInherit
62 {
63   public:
64     /** @brief Constructs RedundancyPriority.
65      *
66      *  @param[in] bus    - The Dbus bus object
67      *  @param[in] path   - The Dbus object path
68      *  @param[in] parent - Parent object.
69      *  @param[in] value  - The redundancyPriority value
70      *  @param[in] freePriority  - Call freePriorioty, default to true
71      */
RedundancyPriority(sdbusplus::bus_t & bus,const std::string & path,Activation & parent,uint8_t value,bool freePriority=true)72     RedundancyPriority(sdbusplus::bus_t& bus, const std::string& path,
73                        Activation& parent, uint8_t value,
74                        bool freePriority = true) :
75         RedundancyPriorityInherit(bus, path.c_str(),
76                                   action::emit_interface_added),
77         parent(parent)
78     {
79         // Set Property
80         if (freePriority)
81         {
82             priority(value);
83         }
84         else
85         {
86             sdbusPriority(value);
87         }
88     }
89 
90     /** @brief Overridden Priority property set function, calls freePriority
91      *         to bump the duplicated priority values.
92      *
93      *  @param[in] value - uint8_t
94      *
95      *  @return Success or exception thrown
96      */
97     uint8_t priority(uint8_t value) override;
98 
99     /** @brief Non-Overriden Priority property set function
100      *
101      *  @param[in] value - uint8_t
102      *
103      *  @return Success or exception thrown
104      */
105     uint8_t sdbusPriority(uint8_t value);
106 
107     /** @brief Priority property get function
108      *
109      *  @returns uint8_t - The Priority value
110      */
111     using RedundancyPriorityInherit::priority;
112 
113     /** @brief Parent Object. */
114     Activation& parent;
115 };
116 
117 /** @class ActivationBlocksTransition
118  *  @brief OpenBMC ActivationBlocksTransition implementation.
119  *  @details A concrete implementation for
120  *  xyz.openbmc_project.Software.ActivationBlocksTransition DBus API.
121  */
122 class ActivationBlocksTransition : public ActivationBlocksTransitionInherit
123 {
124   public:
125     /** @brief Constructs ActivationBlocksTransition.
126      *
127      *  @param[in] bus    - The Dbus bus object
128      *  @param[in] path   - The Dbus object path
129      */
ActivationBlocksTransition(sdbusplus::bus_t & bus,const std::string & path)130     ActivationBlocksTransition(sdbusplus::bus_t& bus, const std::string& path) :
131         ActivationBlocksTransitionInherit(bus, path.c_str(),
132                                           action::emit_interface_added),
133         bus(bus)
134     {
135         enableRebootGuard();
136     }
137 
~ActivationBlocksTransition()138     ~ActivationBlocksTransition()
139     {
140         disableRebootGuard();
141     }
142 
143   private:
144     sdbusplus::bus_t& bus;
145 
146     /** @brief Enables a Guard that blocks any BMC reboot commands */
147     void enableRebootGuard();
148 
149     /** @brief Disables any guard that was blocking the BMC reboot */
150     void disableRebootGuard();
151 };
152 
153 class ActivationProgress : public ActivationProgressInherit
154 {
155   public:
156     /** @brief Constructs ActivationProgress.
157      *
158      * @param[in] bus    - The Dbus bus object
159      * @param[in] path   - The Dbus object path
160      */
ActivationProgress(sdbusplus::bus_t & bus,const std::string & path)161     ActivationProgress(sdbusplus::bus_t& bus, const std::string& path) :
162         ActivationProgressInherit(bus, path.c_str(),
163                                   action::emit_interface_added)
164     {
165         progress(0);
166     }
167 };
168 
169 /** @class Activation
170  *  @brief OpenBMC activation software management implementation.
171  *  @details A concrete implementation for
172  *  xyz.openbmc_project.Software.Activation DBus API.
173  */
174 class Activation : public ActivationInherit, public Flash
175 {
176   public:
177     /** @brief Constructs Activation Software Manager
178      *
179      * @param[in] bus    - The Dbus bus object
180      * @param[in] path   - The Dbus object path
181      * @param[in] parent - Parent object.
182      * @param[in] versionId  - The software version id
183      * @param[in] activationStatus - The status of Activation
184      * @param[in] assocs - Association objects
185      */
Activation(sdbusplus::bus_t & bus,const std::string & path,ItemUpdater & parent,std::string & versionId,sdbusplus::server::xyz::openbmc_project::software::Activation::Activations activationStatus,AssociationList & assocs)186     Activation(sdbusplus::bus_t& bus, const std::string& path,
187                ItemUpdater& parent, std::string& versionId,
188                sdbusplus::server::xyz::openbmc_project::software::Activation::
189                    Activations activationStatus,
190                AssociationList& assocs) :
191         ActivationInherit(bus, path.c_str(),
192                           ActivationInherit::action::defer_emit),
193         bus(bus), path(path), parent(parent), versionId(versionId),
194         systemdSignals(
195             bus,
196             sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
197                 sdbusRule::path("/org/freedesktop/systemd1") +
198                 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
199             std::bind(std::mem_fn(&Activation::unitStateChange), this,
200                       std::placeholders::_1))
201     {
202         // Set Properties.
203         activation(activationStatus);
204         associations(assocs);
205 
206         // Emit deferred signal.
207         emit_object_added();
208     }
209 
210     /** @brief Overloaded Activation property setter function
211      *
212      * @param[in] value - One of Activation::Activations
213      *
214      * @return Success or exception thrown
215      */
216     Activations activation(Activations value) override;
217 
218     /** @brief Activation */
219     using ActivationInherit::activation;
220 
221     /** @brief Overloaded requestedActivation property setter function
222      *
223      * @param[in] value - One of Activation::RequestedActivations
224      *
225      * @return Success or exception thrown
226      */
227     RequestedActivations
228         requestedActivation(RequestedActivations value) override;
229 
230     /** @brief Overloaded write flash function */
231     void flashWrite() override;
232 
233     /**
234      * @brief Handle the success of the flashWrite() function
235      *
236      * @details Perform anything that is necessary to mark the activation
237      * successful after the image has been written to flash. Sets the Activation
238      * value to Active.
239      */
240     void onFlashWriteSuccess();
241 
242 #ifdef HOST_BIOS_UPGRADE
243     /* @brief write to Host flash function */
244     void flashWriteHost();
245 
246     /** @brief Function that acts on Bios upgrade service file state changes */
247     void onStateChangesBios(sdbusplus::message_t&);
248 #endif
249 
250     /** @brief Overloaded function that acts on service file state changes */
251     void onStateChanges(sdbusplus::message_t&) override;
252 
253     /** @brief Check if systemd state change is relevant to this object
254      *
255      * Instance specific interface to handle the detected systemd state
256      * change
257      *
258      * @param[in]  msg       - Data associated with subscribed signal
259      *
260      */
261     void unitStateChange(sdbusplus::message_t& msg);
262 
263     /**
264      * @brief subscribe to the systemd signals
265      *
266      * This object needs to capture when it's systemd targets complete
267      * so it can keep it's state updated
268      *
269      */
270     void subscribeToSystemdSignals();
271 
272     /**
273      * @brief unsubscribe from the systemd signals
274      *
275      * systemd signals are only of interest during the activation process.
276      * Once complete, we want to unsubscribe to avoid unnecessary calls of
277      * unitStateChange().
278      *
279      */
280     void unsubscribeFromSystemdSignals();
281 
282     /**
283      * @brief Deletes the version from Image Manager and the
284      *        untar image from image upload dir.
285      */
286     void deleteImageManagerObject();
287 
288     /**
289      * @brief Determine the configured image apply time value
290      *
291      * @return true if the image apply time value is immediate
292      **/
293     bool checkApplyTimeImmediate();
294 
295     /**
296      * @brief Reboot the BMC. Called when ApplyTime is immediate.
297      *
298      * @return none
299      **/
300     void rebootBmc();
301 
302     /** @brief Persistent sdbusplus DBus bus connection */
303     sdbusplus::bus_t& bus;
304 
305     /** @brief Persistent DBus object path */
306     std::string path;
307 
308     /** @brief Parent Object. */
309     ItemUpdater& parent;
310 
311     /** @brief Version id */
312     std::string versionId;
313 
314     /** @brief Persistent ActivationBlocksTransition dbus object */
315     std::unique_ptr<ActivationBlocksTransition> activationBlocksTransition;
316 
317     /** @brief Persistent RedundancyPriority dbus object */
318     std::unique_ptr<RedundancyPriority> redundancyPriority;
319 
320     /** @brief Persistent ActivationProgress dbus object */
321     std::unique_ptr<ActivationProgress> activationProgress;
322 
323     /** @brief Used to subscribe to dbus systemd signals **/
324     sdbusplus::bus::match_t systemdSignals;
325 
326     /** @brief Tracks whether the read-write volume has been created as
327      * part of the activation process. **/
328     bool rwVolumeCreated = false;
329 
330     /** @brief Tracks whether the read-only volume has been created as
331      * part of the activation process. **/
332     bool roVolumeCreated = false;
333 
334     /** @brief Tracks if the service that updates the U-Boot environment
335      *         variables has completed. **/
336     bool ubootEnvVarsUpdated = false;
337 
338 #ifdef WANT_SIGNATURE_VERIFY
339   private:
340     /** @brief Verify signature of the images.
341      *
342      * @param[in] imageDir - The path of images to verify
343      * @param[in] confDir - The path of configs for verification
344      *
345      * @return true if verification successful and false otherwise
346      */
347     bool verifySignature(const fs::path& imageDir, const fs::path& confDir);
348 
349     /** @brief Called when image verification fails. */
350     void onVerifyFailed();
351 #endif
352 };
353 
354 } // namespace updater
355 } // namespace software
356 } // namespace phosphor
357