blob: a938b8b3f4f78991b4fd39c36a33bfd6ea2198bd [file] [log] [blame]
Saqib Khanb0774702017-05-23 16:02:41 -05001#include "activation.hpp"
Gunnar Millsb0ce9962018-09-07 13:39:10 -05002
Lei YU1be8d502018-06-20 11:48:36 +08003#include "images.hpp"
Saqib Khan4c1aec02017-07-06 11:46:13 -05004#include "item_updater.hpp"
Saqib Khan5d532672017-08-09 10:44:50 -05005#include "serialize.hpp"
Gunnar Millsb0ce9962018-09-07 13:39:10 -05006
Saqib Khanb9da6632017-09-13 09:48:37 -05007#include <phosphor-logging/log.hpp>
Adriana Kobylakaea48f22018-07-10 10:20:56 -05008#include <sdbusplus/exception.hpp>
Saqib Khanb9da6632017-09-13 09:48:37 -05009
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060010#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060011#include "image_verify.hpp"
Gunnar Millsb0ce9962018-09-07 13:39:10 -050012
13#include <phosphor-logging/elog-errors.hpp>
14#include <phosphor-logging/elog.hpp>
15#include <xyz/openbmc_project/Common/error.hpp>
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060016#endif
17
Saqib Khanb0774702017-05-23 16:02:41 -050018namespace phosphor
19{
20namespace software
21{
22namespace updater
23{
24
25namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
26
Saqib Khanb9da6632017-09-13 09:48:37 -050027using namespace phosphor::logging;
Adriana Kobylakaea48f22018-07-10 10:20:56 -050028using sdbusplus::exception::SdBusError;
Saqib Khanb9da6632017-09-13 09:48:37 -050029
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060030#ifdef WANT_SIGNATURE_VERIFY
31using InternalFailure =
32 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -050033namespace control = sdbusplus::xyz::openbmc_project::Control::server;
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060034#endif
35
Michael Tritzbed88af2017-07-19 16:00:06 -050036void Activation::subscribeToSystemdSignals()
37{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060038 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
39 SYSTEMD_INTERFACE, "Subscribe");
Adriana Kobylakaea48f22018-07-10 10:20:56 -050040 try
41 {
42 this->bus.call_noreply(method);
43 }
44 catch (const SdBusError& e)
45 {
46 if (e.name() != nullptr &&
47 strcmp("org.freedesktop.systemd1.AlreadySubscribed", e.name()) == 0)
48 {
49 // If an Activation attempt fails, the Unsubscribe method is not
50 // called. This may lead to an AlreadySubscribed error if the
51 // Activation is re-attempted.
52 }
53 else
54 {
55 log<level::ERR>("Error subscribing to systemd",
56 entry("ERROR=%s", e.what()));
57 }
58 }
Michael Tritzbed88af2017-07-19 16:00:06 -050059
60 return;
61}
62
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050063void Activation::unsubscribeFromSystemdSignals()
64{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060065 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
66 SYSTEMD_INTERFACE, "Unsubscribe");
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050067 this->bus.call_noreply(method);
68
69 return;
70}
71
Adriana Kobylak2285fe02018-02-27 15:36:59 -060072auto Activation::activation(Activations value) -> Activations
Saqib Khanb0774702017-05-23 16:02:41 -050073{
Saqib Khan4c1aec02017-07-06 11:46:13 -050074
Adriana Kobylak8bd84c82018-01-24 14:19:24 -060075 if ((value != softwareServer::Activation::Activations::Active) &&
76 (value != softwareServer::Activation::Activations::Activating))
Saqib Khan4c1aec02017-07-06 11:46:13 -050077 {
78 redundancyPriority.reset(nullptr);
79 }
80
Saqib Khanb0774702017-05-23 16:02:41 -050081 if (value == softwareServer::Activation::Activations::Activating)
82 {
Lei YUa7853ee2018-05-23 11:13:12 +080083#ifdef UBIFS_LAYOUT
Michael Tritzbed88af2017-07-19 16:00:06 -050084 if (rwVolumeCreated == false && roVolumeCreated == false)
Saqib Khanb0774702017-05-23 16:02:41 -050085 {
Adriana Kobylakaea48f22018-07-10 10:20:56 -050086 // Enable systemd signals
87 Activation::subscribeToSystemdSignals();
88
Adriana Kobylaka6963592018-09-07 14:13:29 -050089 parent.freeSpace(*this);
Adriana Kobylak204e1e72018-01-24 16:00:05 -060090
Michael Tritz0edd4ad2017-07-26 14:27:42 -050091 if (!activationProgress)
92 {
Adriana Kobylak2285fe02018-02-27 15:36:59 -060093 activationProgress =
94 std::make_unique<ActivationProgress>(bus, path);
Michael Tritz0edd4ad2017-07-26 14:27:42 -050095 }
96
Michael Tritzbed88af2017-07-19 16:00:06 -050097 if (!activationBlocksTransition)
98 {
99 activationBlocksTransition =
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600100 std::make_unique<ActivationBlocksTransition>(bus, path);
Michael Tritzbed88af2017-07-19 16:00:06 -0500101 }
Saqib Khan4c1aec02017-07-06 11:46:13 -0500102
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600103#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600104 fs::path uploadDir(IMG_UPLOAD_DIR);
Lei YU90532252018-05-24 11:15:24 +0800105 if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600106 {
Lei YU90532252018-05-24 11:15:24 +0800107 onVerifyFailed();
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -0500108 // Stop the activation process, if fieldMode is enabled.
109 if (parent.control::FieldMode::fieldModeEnabled())
110 {
111 // Cleanup
112 activationBlocksTransition.reset(nullptr);
113 activationProgress.reset(nullptr);
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -0500114 return softwareServer::Activation::activation(
115 softwareServer::Activation::Activations::Failed);
116 }
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600117 }
118#endif
119
Adriana Kobylak9f89e2e2018-05-30 13:16:20 -0500120 flashWrite();
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500121
122 activationProgress->progress(10);
Michael Tritzbed88af2017-07-19 16:00:06 -0500123 }
124 else if (rwVolumeCreated == true && roVolumeCreated == true)
Saqib Khan4c1aec02017-07-06 11:46:13 -0500125 {
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500126 if (ubootEnvVarsUpdated == false)
Michael Tritzbed88af2017-07-19 16:00:06 -0500127 {
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500128 activationProgress->progress(90);
129
130 if (!redundancyPriority)
131 {
132 redundancyPriority = std::make_unique<RedundancyPriority>(
133 bus, path, *this, 0);
134 }
Michael Tritzbed88af2017-07-19 16:00:06 -0500135 }
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500136 else
137 {
138 activationProgress->progress(100);
Saqib Khan4c1aec02017-07-06 11:46:13 -0500139
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500140 activationBlocksTransition.reset(nullptr);
141 activationProgress.reset(nullptr);
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500142
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500143 rwVolumeCreated = false;
144 roVolumeCreated = false;
145 ubootEnvVarsUpdated = false;
146 Activation::unsubscribeFromSystemdSignals();
Michael Tritzf2b5e0d2017-07-25 14:39:34 -0500147
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500148 // Remove version object from image manager
149 Activation::deleteImageManagerObject();
Michael Tritzf2b5e0d2017-07-25 14:39:34 -0500150
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500151 // Create active association
152 parent.createActiveAssociation(path);
Saqib Khanee13e832017-10-23 12:53:11 -0500153
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500154 return softwareServer::Activation::activation(
155 softwareServer::Activation::Activations::Active);
156 }
Michael Tritzbed88af2017-07-19 16:00:06 -0500157 }
Lei YUa7853ee2018-05-23 11:13:12 +0800158#else // !UBIFS_LAYOUT
159
Lei YU90532252018-05-24 11:15:24 +0800160#ifdef WANT_SIGNATURE_VERIFY
161 fs::path uploadDir(IMG_UPLOAD_DIR);
162 if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
163 {
164 onVerifyFailed();
165 // Stop the activation process, if fieldMode is enabled.
166 if (parent.control::FieldMode::fieldModeEnabled())
167 {
168 return softwareServer::Activation::activation(
169 softwareServer::Activation::Activations::Failed);
170 }
171 }
172#endif
Adriana Kobylaka6963592018-09-07 14:13:29 -0500173 parent.freeSpace(*this);
Lei YUa7853ee2018-05-23 11:13:12 +0800174
175 flashWrite();
176
177 if (!redundancyPriority)
178 {
179 redundancyPriority =
180 std::make_unique<RedundancyPriority>(bus, path, *this, 0);
181 }
182
183 // Remove version object from image manager
184 Activation::deleteImageManagerObject();
185
186 // Create active association
187 parent.createActiveAssociation(path);
188
189 log<level::INFO>("BMC image ready, need reboot to get activated.");
190 return softwareServer::Activation::activation(
191 softwareServer::Activation::Activations::Active);
192#endif
Saqib Khanb0774702017-05-23 16:02:41 -0500193 }
194 else
195 {
196 activationBlocksTransition.reset(nullptr);
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500197 activationProgress.reset(nullptr);
Saqib Khanb0774702017-05-23 16:02:41 -0500198 }
199 return softwareServer::Activation::activation(value);
200}
201
Saqib Khanee13e832017-10-23 12:53:11 -0500202void Activation::deleteImageManagerObject()
203{
Saqib Khanee13e832017-10-23 12:53:11 -0500204 // Call the Delete object for <versionID> inside image_manager
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600205 auto method = this->bus.new_method_call(VERSION_BUSNAME, path.c_str(),
206 "xyz.openbmc_project.Object.Delete",
207 "Delete");
Adriana Kobylak00bd9022018-01-24 13:55:58 -0600208 auto mapperResponseMsg = bus.call(method);
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600209 // Check that the bus call didn't result in an error
Saqib Khanee13e832017-10-23 12:53:11 -0500210 if (mapperResponseMsg.is_method_error())
211 {
212 log<level::ERR>("Error in Deleting image from image manager",
Adriana Kobylak596466b2018-02-13 14:48:53 -0600213 entry("VERSIONPATH=%s", path.c_str()));
Saqib Khanee13e832017-10-23 12:53:11 -0500214 return;
215 }
216}
217
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600218auto Activation::requestedActivation(RequestedActivations value)
219 -> RequestedActivations
Saqib Khanb0774702017-05-23 16:02:41 -0500220{
Michael Tritzbed88af2017-07-19 16:00:06 -0500221 rwVolumeCreated = false;
222 roVolumeCreated = false;
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500223 ubootEnvVarsUpdated = false;
Michael Tritzbed88af2017-07-19 16:00:06 -0500224
Saqib Khanb0774702017-05-23 16:02:41 -0500225 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
226 (softwareServer::Activation::requestedActivation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600227 softwareServer::Activation::RequestedActivations::Active))
Saqib Khanb0774702017-05-23 16:02:41 -0500228 {
229 if ((softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600230 softwareServer::Activation::Activations::Ready) ||
Saqib Khanb0774702017-05-23 16:02:41 -0500231 (softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600232 softwareServer::Activation::Activations::Failed))
Saqib Khanb0774702017-05-23 16:02:41 -0500233 {
234 Activation::activation(
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600235 softwareServer::Activation::Activations::Activating);
Saqib Khanb0774702017-05-23 16:02:41 -0500236 }
237 }
238 return softwareServer::Activation::requestedActivation(value);
239}
240
Saqib Khan4c1aec02017-07-06 11:46:13 -0500241uint8_t RedundancyPriority::priority(uint8_t value)
242{
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500243 // Set the priority value so that the freePriority() function can order
244 // the versions by priority.
245 auto newPriority = softwareServer::RedundancyPriority::priority(value);
Adriana Kobylakbbcb7be2018-07-17 15:47:34 -0500246 parent.parent.savePriority(parent.versionId, value);
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500247 parent.parent.freePriority(value, parent.versionId);
248 return newPriority;
Saqib Khan4c1aec02017-07-06 11:46:13 -0500249}
250
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500251uint8_t RedundancyPriority::sdbusPriority(uint8_t value)
Saqib Khanf0382c32017-10-24 13:36:22 -0500252{
Adriana Kobylakbbcb7be2018-07-17 15:47:34 -0500253 parent.parent.savePriority(parent.versionId, value);
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500254 return softwareServer::RedundancyPriority::priority(value);
Saqib Khanf0382c32017-10-24 13:36:22 -0500255}
256
Michael Tritzbed88af2017-07-19 16:00:06 -0500257void Activation::unitStateChange(sdbusplus::message::message& msg)
258{
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500259 if (softwareServer::Activation::activation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600260 softwareServer::Activation::Activations::Activating)
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500261 {
262 return;
263 }
264
Adriana Kobylak3ce563a2018-06-06 16:41:15 -0500265 onStateChanges(msg);
Michael Tritzbed88af2017-07-19 16:00:06 -0500266
267 return;
268}
269
Lei YU90532252018-05-24 11:15:24 +0800270#ifdef WANT_SIGNATURE_VERIFY
271bool Activation::verifySignature(const fs::path& imageDir,
272 const fs::path& confDir)
273{
274 using Signature = phosphor::software::image::Signature;
275
276 Signature signature(imageDir, confDir);
277
278 return signature.verify();
279}
280
281void Activation::onVerifyFailed()
282{
283 log<level::ERR>("Error occurred during image validation");
284 report<InternalFailure>();
285}
286#endif
287
Saqib Khanf37cefc2017-09-12 08:44:41 -0500288void ActivationBlocksTransition::enableRebootGuard()
289{
290 log<level::INFO>("BMC image activating - BMC reboots are disabled.");
291
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600292 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
293 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500294 method.append("reboot-guard-enable.service", "replace");
295 bus.call_noreply(method);
296}
297
298void ActivationBlocksTransition::disableRebootGuard()
299{
300 log<level::INFO>("BMC activation has ended - BMC reboots are re-enabled.");
301
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600302 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
303 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500304 method.append("reboot-guard-disable.service", "replace");
305 bus.call_noreply(method);
306}
Michael Tritzbed88af2017-07-19 16:00:06 -0500307
Saqib Khanb0774702017-05-23 16:02:41 -0500308} // namespace updater
309} // namespace software
310} // namespace phosphor