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