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