blob: 421902afa2bf7317d29b9247deb82979638747b9 [file] [log] [blame]
Saqib Khanb0774702017-05-23 16:02:41 -05001#include "activation.hpp"
Saqib Khan4c1aec02017-07-06 11:46:13 -05002#include "item_updater.hpp"
Saqib Khan5d532672017-08-09 10:44:50 -05003#include "serialize.hpp"
Saqib Khanb9da6632017-09-13 09:48:37 -05004#include <phosphor-logging/log.hpp>
Adriana Kobylakaea48f22018-07-10 10:20:56 -05005#include <sdbusplus/exception.hpp>
Saqib Khanb9da6632017-09-13 09:48:37 -05006
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -06007#ifdef WANT_SIGNATURE_VERIFY
8#include <phosphor-logging/elog.hpp>
9#include <phosphor-logging/elog-errors.hpp>
10#include <xyz/openbmc_project/Common/error.hpp>
11#include "image_verify.hpp"
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060012#endif
13
Saqib Khanb0774702017-05-23 16:02:41 -050014namespace phosphor
15{
16namespace software
17{
18namespace updater
19{
20
21namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
22
Saqib Khanb9da6632017-09-13 09:48:37 -050023using namespace phosphor::logging;
Adriana Kobylakaea48f22018-07-10 10:20:56 -050024using sdbusplus::exception::SdBusError;
Saqib Khanb9da6632017-09-13 09:48:37 -050025
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060026#ifdef WANT_SIGNATURE_VERIFY
27using InternalFailure =
28 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -050029namespace control = sdbusplus::xyz::openbmc_project::Control::server;
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060030#endif
31
Michael Tritzbed88af2017-07-19 16:00:06 -050032void Activation::subscribeToSystemdSignals()
33{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060034 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
35 SYSTEMD_INTERFACE, "Subscribe");
Adriana Kobylakaea48f22018-07-10 10:20:56 -050036 try
37 {
38 this->bus.call_noreply(method);
39 }
40 catch (const SdBusError& e)
41 {
42 if (e.name() != nullptr &&
43 strcmp("org.freedesktop.systemd1.AlreadySubscribed", e.name()) == 0)
44 {
45 // If an Activation attempt fails, the Unsubscribe method is not
46 // called. This may lead to an AlreadySubscribed error if the
47 // Activation is re-attempted.
48 }
49 else
50 {
51 log<level::ERR>("Error subscribing to systemd",
52 entry("ERROR=%s", e.what()));
53 }
54 }
Michael Tritzbed88af2017-07-19 16:00:06 -050055
56 return;
57}
58
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050059void Activation::unsubscribeFromSystemdSignals()
60{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060061 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
62 SYSTEMD_INTERFACE, "Unsubscribe");
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050063 this->bus.call_noreply(method);
64
65 return;
66}
67
Adriana Kobylak2285fe02018-02-27 15:36:59 -060068auto Activation::activation(Activations value) -> Activations
Saqib Khanb0774702017-05-23 16:02:41 -050069{
Saqib Khan4c1aec02017-07-06 11:46:13 -050070
Adriana Kobylak8bd84c82018-01-24 14:19:24 -060071 if ((value != softwareServer::Activation::Activations::Active) &&
72 (value != softwareServer::Activation::Activations::Activating))
Saqib Khan4c1aec02017-07-06 11:46:13 -050073 {
74 redundancyPriority.reset(nullptr);
75 }
76
Saqib Khanb0774702017-05-23 16:02:41 -050077 if (value == softwareServer::Activation::Activations::Activating)
78 {
Lei YUa7853ee2018-05-23 11:13:12 +080079#ifdef UBIFS_LAYOUT
Michael Tritzbed88af2017-07-19 16:00:06 -050080 if (rwVolumeCreated == false && roVolumeCreated == false)
Saqib Khanb0774702017-05-23 16:02:41 -050081 {
Adriana Kobylakaea48f22018-07-10 10:20:56 -050082 // Enable systemd signals
83 Activation::subscribeToSystemdSignals();
84
Adriana Kobylak204e1e72018-01-24 16:00:05 -060085 parent.freeSpace();
86
Michael Tritz0edd4ad2017-07-26 14:27:42 -050087 if (!activationProgress)
88 {
Adriana Kobylak2285fe02018-02-27 15:36:59 -060089 activationProgress =
90 std::make_unique<ActivationProgress>(bus, path);
Michael Tritz0edd4ad2017-07-26 14:27:42 -050091 }
92
Michael Tritzbed88af2017-07-19 16:00:06 -050093 if (!activationBlocksTransition)
94 {
95 activationBlocksTransition =
Adriana Kobylak2285fe02018-02-27 15:36:59 -060096 std::make_unique<ActivationBlocksTransition>(bus, path);
Michael Tritzbed88af2017-07-19 16:00:06 -050097 }
Saqib Khan4c1aec02017-07-06 11:46:13 -050098
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060099#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600100 fs::path uploadDir(IMG_UPLOAD_DIR);
Lei YU90532252018-05-24 11:15:24 +0800101 if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600102 {
Lei YU90532252018-05-24 11:15:24 +0800103 onVerifyFailed();
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -0500104 // Stop the activation process, if fieldMode is enabled.
105 if (parent.control::FieldMode::fieldModeEnabled())
106 {
107 // Cleanup
108 activationBlocksTransition.reset(nullptr);
109 activationProgress.reset(nullptr);
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -0500110 return softwareServer::Activation::activation(
111 softwareServer::Activation::Activations::Failed);
112 }
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600113 }
114#endif
115
Adriana Kobylak9f89e2e2018-05-30 13:16:20 -0500116 flashWrite();
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500117
118 activationProgress->progress(10);
Michael Tritzbed88af2017-07-19 16:00:06 -0500119 }
120 else if (rwVolumeCreated == true && roVolumeCreated == true)
Saqib Khan4c1aec02017-07-06 11:46:13 -0500121 {
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500122 if (ubootEnvVarsUpdated == false)
Michael Tritzbed88af2017-07-19 16:00:06 -0500123 {
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500124 activationProgress->progress(90);
125
126 if (!redundancyPriority)
127 {
128 redundancyPriority = std::make_unique<RedundancyPriority>(
129 bus, path, *this, 0);
130 }
Michael Tritzbed88af2017-07-19 16:00:06 -0500131 }
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500132 else
133 {
134 activationProgress->progress(100);
Saqib Khan4c1aec02017-07-06 11:46:13 -0500135
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500136 activationBlocksTransition.reset(nullptr);
137 activationProgress.reset(nullptr);
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500138
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500139 rwVolumeCreated = false;
140 roVolumeCreated = false;
141 ubootEnvVarsUpdated = false;
142 Activation::unsubscribeFromSystemdSignals();
Michael Tritzf2b5e0d2017-07-25 14:39:34 -0500143
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500144 // Remove version object from image manager
145 Activation::deleteImageManagerObject();
Michael Tritzf2b5e0d2017-07-25 14:39:34 -0500146
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500147 // Create active association
148 parent.createActiveAssociation(path);
Saqib Khanee13e832017-10-23 12:53:11 -0500149
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500150 return softwareServer::Activation::activation(
151 softwareServer::Activation::Activations::Active);
152 }
Michael Tritzbed88af2017-07-19 16:00:06 -0500153 }
Lei YUa7853ee2018-05-23 11:13:12 +0800154#else // !UBIFS_LAYOUT
155
Lei YU90532252018-05-24 11:15:24 +0800156#ifdef WANT_SIGNATURE_VERIFY
157 fs::path uploadDir(IMG_UPLOAD_DIR);
158 if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
159 {
160 onVerifyFailed();
161 // Stop the activation process, if fieldMode is enabled.
162 if (parent.control::FieldMode::fieldModeEnabled())
163 {
164 return softwareServer::Activation::activation(
165 softwareServer::Activation::Activations::Failed);
166 }
167 }
168#endif
Lei YUa7853ee2018-05-23 11:13:12 +0800169 parent.freeSpace();
170
171 flashWrite();
172
173 if (!redundancyPriority)
174 {
175 redundancyPriority =
176 std::make_unique<RedundancyPriority>(bus, path, *this, 0);
177 }
178
179 // Remove version object from image manager
180 Activation::deleteImageManagerObject();
181
182 // Create active association
183 parent.createActiveAssociation(path);
184
185 log<level::INFO>("BMC image ready, need reboot to get activated.");
186 return softwareServer::Activation::activation(
187 softwareServer::Activation::Activations::Active);
188#endif
Saqib Khanb0774702017-05-23 16:02:41 -0500189 }
190 else
191 {
192 activationBlocksTransition.reset(nullptr);
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500193 activationProgress.reset(nullptr);
Saqib Khanb0774702017-05-23 16:02:41 -0500194 }
195 return softwareServer::Activation::activation(value);
196}
197
Saqib Khanee13e832017-10-23 12:53:11 -0500198void Activation::deleteImageManagerObject()
199{
Saqib Khanee13e832017-10-23 12:53:11 -0500200 // Call the Delete object for <versionID> inside image_manager
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600201 auto method = this->bus.new_method_call(VERSION_BUSNAME, path.c_str(),
202 "xyz.openbmc_project.Object.Delete",
203 "Delete");
Adriana Kobylak00bd9022018-01-24 13:55:58 -0600204 auto mapperResponseMsg = bus.call(method);
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600205 // Check that the bus call didn't result in an error
Saqib Khanee13e832017-10-23 12:53:11 -0500206 if (mapperResponseMsg.is_method_error())
207 {
208 log<level::ERR>("Error in Deleting image from image manager",
Adriana Kobylak596466b2018-02-13 14:48:53 -0600209 entry("VERSIONPATH=%s", path.c_str()));
Saqib Khanee13e832017-10-23 12:53:11 -0500210 return;
211 }
212}
213
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600214auto Activation::requestedActivation(RequestedActivations value)
215 -> RequestedActivations
Saqib Khanb0774702017-05-23 16:02:41 -0500216{
Michael Tritzbed88af2017-07-19 16:00:06 -0500217 rwVolumeCreated = false;
218 roVolumeCreated = false;
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500219 ubootEnvVarsUpdated = false;
Michael Tritzbed88af2017-07-19 16:00:06 -0500220
Saqib Khanb0774702017-05-23 16:02:41 -0500221 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
222 (softwareServer::Activation::requestedActivation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600223 softwareServer::Activation::RequestedActivations::Active))
Saqib Khanb0774702017-05-23 16:02:41 -0500224 {
225 if ((softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600226 softwareServer::Activation::Activations::Ready) ||
Saqib Khanb0774702017-05-23 16:02:41 -0500227 (softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600228 softwareServer::Activation::Activations::Failed))
Saqib Khanb0774702017-05-23 16:02:41 -0500229 {
230 Activation::activation(
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600231 softwareServer::Activation::Activations::Activating);
Saqib Khanb0774702017-05-23 16:02:41 -0500232 }
233 }
234 return softwareServer::Activation::requestedActivation(value);
235}
236
Saqib Khan4c1aec02017-07-06 11:46:13 -0500237uint8_t RedundancyPriority::priority(uint8_t value)
238{
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500239 // Set the priority value so that the freePriority() function can order
240 // the versions by priority.
241 auto newPriority = softwareServer::RedundancyPriority::priority(value);
Saqib Khan5d532672017-08-09 10:44:50 -0500242 storeToFile(parent.versionId, value);
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500243 parent.parent.freePriority(value, parent.versionId);
244 return newPriority;
Saqib Khan4c1aec02017-07-06 11:46:13 -0500245}
246
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500247uint8_t RedundancyPriority::sdbusPriority(uint8_t value)
Saqib Khanf0382c32017-10-24 13:36:22 -0500248{
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500249 storeToFile(parent.versionId, value);
250 return softwareServer::RedundancyPriority::priority(value);
Saqib Khanf0382c32017-10-24 13:36:22 -0500251}
252
Michael Tritzbed88af2017-07-19 16:00:06 -0500253void Activation::unitStateChange(sdbusplus::message::message& msg)
254{
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500255 if (softwareServer::Activation::activation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600256 softwareServer::Activation::Activations::Activating)
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500257 {
258 return;
259 }
260
Adriana Kobylak3ce563a2018-06-06 16:41:15 -0500261 onStateChanges(msg);
Michael Tritzbed88af2017-07-19 16:00:06 -0500262
263 return;
264}
265
Lei YU90532252018-05-24 11:15:24 +0800266#ifdef WANT_SIGNATURE_VERIFY
267bool Activation::verifySignature(const fs::path& imageDir,
268 const fs::path& confDir)
269{
270 using Signature = phosphor::software::image::Signature;
271
272 Signature signature(imageDir, confDir);
273
274 return signature.verify();
275}
276
277void Activation::onVerifyFailed()
278{
279 log<level::ERR>("Error occurred during image validation");
280 report<InternalFailure>();
281}
282#endif
283
Saqib Khanf37cefc2017-09-12 08:44:41 -0500284void ActivationBlocksTransition::enableRebootGuard()
285{
286 log<level::INFO>("BMC image activating - BMC reboots are disabled.");
287
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600288 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
289 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500290 method.append("reboot-guard-enable.service", "replace");
291 bus.call_noreply(method);
292}
293
294void ActivationBlocksTransition::disableRebootGuard()
295{
296 log<level::INFO>("BMC activation has ended - BMC reboots are re-enabled.");
297
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600298 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
299 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500300 method.append("reboot-guard-disable.service", "replace");
301 bus.call_noreply(method);
302}
Michael Tritzbed88af2017-07-19 16:00:06 -0500303
Saqib Khanb0774702017-05-23 16:02:41 -0500304} // namespace updater
305} // namespace software
306} // namespace phosphor