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      */
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      */
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 
138     ~ActivationBlocksTransition() override
139     {
140         disableRebootGuard();
141     }
142 
143     ActivationBlocksTransition(const ActivationBlocksTransition&) = delete;
144     ActivationBlocksTransition&
145         operator=(const ActivationBlocksTransition&) = delete;
146     ActivationBlocksTransition(ActivationBlocksTransition&&) = delete;
147     ActivationBlocksTransition&
148         operator=(ActivationBlocksTransition&&) = delete;
149 
150   private:
151     sdbusplus::bus_t& bus;
152 
153     /** @brief Enables a Guard that blocks any BMC reboot commands */
154     void enableRebootGuard();
155 
156     /** @brief Disables any guard that was blocking the BMC reboot */
157     void disableRebootGuard();
158 };
159 
160 class ActivationProgress : public ActivationProgressInherit
161 {
162   public:
163     /** @brief Constructs ActivationProgress.
164      *
165      * @param[in] bus    - The Dbus bus object
166      * @param[in] path   - The Dbus object path
167      */
168     ActivationProgress(sdbusplus::bus_t& bus, const std::string& path) :
169         ActivationProgressInherit(bus, path.c_str(),
170                                   action::emit_interface_added)
171     {
172         progress(0);
173     }
174 };
175 
176 /** @class Activation
177  *  @brief OpenBMC activation software management implementation.
178  *  @details A concrete implementation for
179  *  xyz.openbmc_project.Software.Activation DBus API.
180  */
181 class Activation : public ActivationInherit, public Flash
182 {
183   public:
184     /** @brief Constructs Activation Software Manager
185      *
186      * @param[in] bus    - The Dbus bus object
187      * @param[in] path   - The Dbus object path
188      * @param[in] parent - Parent object.
189      * @param[in] versionId  - The software version id
190      * @param[in] activationStatus - The status of Activation
191      * @param[in] assocs - Association objects
192      */
193     Activation(sdbusplus::bus_t& bus, const std::string& path,
194                ItemUpdater& parent, std::string& versionId,
195                sdbusplus::server::xyz::openbmc_project::software::Activation::
196                    Activations activationStatus,
197                AssociationList& assocs) :
198         ActivationInherit(bus, path.c_str(),
199                           ActivationInherit::action::defer_emit),
200         bus(bus), path(path), parent(parent), versionId(versionId),
201         systemdSignals(
202             bus,
203             sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
204                 sdbusRule::path("/org/freedesktop/systemd1") +
205                 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
206             std::bind(std::mem_fn(&Activation::unitStateChange), this,
207                       std::placeholders::_1))
208     {
209         // Set Properties.
210         activation(activationStatus);
211         associations(assocs);
212 
213         // Emit deferred signal.
214         emit_object_added();
215     }
216 
217     /** @brief Overloaded Activation property setter function
218      *
219      * @param[in] value - One of Activation::Activations
220      *
221      * @return Success or exception thrown
222      */
223     Activations activation(Activations value) override;
224 
225     /** @brief Activation */
226     using ActivationInherit::activation;
227 
228     /** @brief Overloaded requestedActivation property setter function
229      *
230      * @param[in] value - One of Activation::RequestedActivations
231      *
232      * @return Success or exception thrown
233      */
234     RequestedActivations
235         requestedActivation(RequestedActivations value) override;
236 
237     /** @brief Overloaded write flash function */
238     void flashWrite() override;
239 
240     /**
241      * @brief Handle the success of the flashWrite() function
242      *
243      * @details Perform anything that is necessary to mark the activation
244      * successful after the image has been written to flash. Sets the Activation
245      * value to Active.
246      */
247     void onFlashWriteSuccess();
248 
249 #ifdef HOST_BIOS_UPGRADE
250     /* @brief write to Host flash function */
251     void flashWriteHost();
252 
253     /** @brief Function that acts on Bios upgrade service file state changes */
254     void onStateChangesBios(sdbusplus::message_t& /*msg*/);
255 #endif
256 
257     /** @brief Overloaded function that acts on service file state changes */
258     void onStateChanges(sdbusplus::message_t& /*msg*/) override;
259 
260     /** @brief Check if systemd state change is relevant to this object
261      *
262      * Instance specific interface to handle the detected systemd state
263      * change
264      *
265      * @param[in]  msg       - Data associated with subscribed signal
266      *
267      */
268     void unitStateChange(sdbusplus::message_t& msg);
269 
270     /**
271      * @brief subscribe to the systemd signals
272      *
273      * This object needs to capture when it's systemd targets complete
274      * so it can keep it's state updated
275      *
276      */
277     void subscribeToSystemdSignals();
278 
279     /**
280      * @brief unsubscribe from the systemd signals
281      *
282      * systemd signals are only of interest during the activation process.
283      * Once complete, we want to unsubscribe to avoid unnecessary calls of
284      * unitStateChange().
285      *
286      */
287     void unsubscribeFromSystemdSignals();
288 
289     /**
290      * @brief Deletes the version from Image Manager and the
291      *        untar image from image upload dir.
292      */
293     void deleteImageManagerObject();
294 
295     /**
296      * @brief Determine the configured image apply time value
297      *
298      * @return true if the image apply time value is immediate
299      **/
300     bool checkApplyTimeImmediate();
301 
302     /**
303      * @brief Reboot the BMC. Called when ApplyTime is immediate.
304      *
305      * @return none
306      **/
307     void rebootBmc();
308 
309     /** @brief Persistent sdbusplus DBus bus connection */
310     sdbusplus::bus_t& bus;
311 
312     /** @brief Persistent DBus object path */
313     std::string path;
314 
315     /** @brief Parent Object. */
316     ItemUpdater& parent;
317 
318     /** @brief Version id */
319     std::string versionId;
320 
321     /** @brief Persistent ActivationBlocksTransition dbus object */
322     std::unique_ptr<ActivationBlocksTransition> activationBlocksTransition;
323 
324     /** @brief Persistent RedundancyPriority dbus object */
325     std::unique_ptr<RedundancyPriority> redundancyPriority;
326 
327     /** @brief Persistent ActivationProgress dbus object */
328     std::unique_ptr<ActivationProgress> activationProgress;
329 
330     /** @brief Used to subscribe to dbus systemd signals **/
331     sdbusplus::bus::match_t systemdSignals;
332 
333     /** @brief Tracks whether the read-write volume has been created as
334      * part of the activation process. **/
335     bool rwVolumeCreated = false;
336 
337     /** @brief Tracks whether the read-only volume has been created as
338      * part of the activation process. **/
339     bool roVolumeCreated = false;
340 
341     /** @brief Tracks if the service that updates the U-Boot environment
342      *         variables has completed. **/
343     bool ubootEnvVarsUpdated = false;
344 
345 #ifdef WANT_SIGNATURE_VERIFY
346   private:
347     /** @brief Verify signature of the images.
348      *
349      * @param[in] imageDir - The path of images to verify
350      * @param[in] confDir - The path of configs for verification
351      *
352      * @return true if verification successful and false otherwise
353      */
354     static bool verifySignature(const fs::path& imageDir,
355                                 const fs::path& confDir);
356 
357     /** @brief Called when image verification fails. */
358     void onVerifyFailed();
359 #endif
360 };
361 
362 } // namespace updater
363 } // namespace software
364 } // namespace phosphor
365