blob: 863ea563c38dd8d41efd1b505c22667f96cebb4c [file] [log] [blame]
Saqib Khanb0774702017-05-23 16:02:41 -05001#include "activation.hpp"
Lei YU1be8d502018-06-20 11:48:36 +08002#include "images.hpp"
Saqib Khan4c1aec02017-07-06 11:46:13 -05003#include "item_updater.hpp"
Saqib Khan5d532672017-08-09 10:44:50 -05004#include "serialize.hpp"
Saqib Khanb9da6632017-09-13 09:48:37 -05005#include <phosphor-logging/log.hpp>
Adriana Kobylakaea48f22018-07-10 10:20:56 -05006#include <sdbusplus/exception.hpp>
Saqib Khanb9da6632017-09-13 09:48:37 -05007
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -06008#ifdef WANT_SIGNATURE_VERIFY
9#include <phosphor-logging/elog.hpp>
10#include <phosphor-logging/elog-errors.hpp>
11#include <xyz/openbmc_project/Common/error.hpp>
12#include "image_verify.hpp"
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060013#endif
14
Saqib Khanb0774702017-05-23 16:02:41 -050015namespace phosphor
16{
17namespace software
18{
19namespace updater
20{
21
22namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
23
Saqib Khanb9da6632017-09-13 09:48:37 -050024using namespace phosphor::logging;
Adriana Kobylakaea48f22018-07-10 10:20:56 -050025using sdbusplus::exception::SdBusError;
Saqib Khanb9da6632017-09-13 09:48:37 -050026
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060027#ifdef WANT_SIGNATURE_VERIFY
28using InternalFailure =
29 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -050030namespace control = sdbusplus::xyz::openbmc_project::Control::server;
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060031#endif
32
Michael Tritzbed88af2017-07-19 16:00:06 -050033void Activation::subscribeToSystemdSignals()
34{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060035 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
36 SYSTEMD_INTERFACE, "Subscribe");
Adriana Kobylakaea48f22018-07-10 10:20:56 -050037 try
38 {
39 this->bus.call_noreply(method);
40 }
41 catch (const SdBusError& e)
42 {
43 if (e.name() != nullptr &&
44 strcmp("org.freedesktop.systemd1.AlreadySubscribed", e.name()) == 0)
45 {
46 // If an Activation attempt fails, the Unsubscribe method is not
47 // called. This may lead to an AlreadySubscribed error if the
48 // Activation is re-attempted.
49 }
50 else
51 {
52 log<level::ERR>("Error subscribing to systemd",
53 entry("ERROR=%s", e.what()));
54 }
55 }
Michael Tritzbed88af2017-07-19 16:00:06 -050056
57 return;
58}
59
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050060void Activation::unsubscribeFromSystemdSignals()
61{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060062 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
63 SYSTEMD_INTERFACE, "Unsubscribe");
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050064 this->bus.call_noreply(method);
65
66 return;
67}
68
Adriana Kobylak2285fe02018-02-27 15:36:59 -060069auto Activation::activation(Activations value) -> Activations
Saqib Khanb0774702017-05-23 16:02:41 -050070{
Saqib Khan4c1aec02017-07-06 11:46:13 -050071
Adriana Kobylak8bd84c82018-01-24 14:19:24 -060072 if ((value != softwareServer::Activation::Activations::Active) &&
73 (value != softwareServer::Activation::Activations::Activating))
Saqib Khan4c1aec02017-07-06 11:46:13 -050074 {
75 redundancyPriority.reset(nullptr);
76 }
77
Saqib Khanb0774702017-05-23 16:02:41 -050078 if (value == softwareServer::Activation::Activations::Activating)
79 {
Lei YUa7853ee2018-05-23 11:13:12 +080080#ifdef UBIFS_LAYOUT
Michael Tritzbed88af2017-07-19 16:00:06 -050081 if (rwVolumeCreated == false && roVolumeCreated == false)
Saqib Khanb0774702017-05-23 16:02:41 -050082 {
Adriana Kobylakaea48f22018-07-10 10:20:56 -050083 // Enable systemd signals
84 Activation::subscribeToSystemdSignals();
85
Adriana Kobylak204e1e72018-01-24 16:00:05 -060086 parent.freeSpace();
87
Michael Tritz0edd4ad2017-07-26 14:27:42 -050088 if (!activationProgress)
89 {
Adriana Kobylak2285fe02018-02-27 15:36:59 -060090 activationProgress =
91 std::make_unique<ActivationProgress>(bus, path);
Michael Tritz0edd4ad2017-07-26 14:27:42 -050092 }
93
Michael Tritzbed88af2017-07-19 16:00:06 -050094 if (!activationBlocksTransition)
95 {
96 activationBlocksTransition =
Adriana Kobylak2285fe02018-02-27 15:36:59 -060097 std::make_unique<ActivationBlocksTransition>(bus, path);
Michael Tritzbed88af2017-07-19 16:00:06 -050098 }
Saqib Khan4c1aec02017-07-06 11:46:13 -050099
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600100#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600101 fs::path uploadDir(IMG_UPLOAD_DIR);
Lei YU90532252018-05-24 11:15:24 +0800102 if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600103 {
Lei YU90532252018-05-24 11:15:24 +0800104 onVerifyFailed();
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -0500105 // Stop the activation process, if fieldMode is enabled.
106 if (parent.control::FieldMode::fieldModeEnabled())
107 {
108 // Cleanup
109 activationBlocksTransition.reset(nullptr);
110 activationProgress.reset(nullptr);
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -0500111 return softwareServer::Activation::activation(
112 softwareServer::Activation::Activations::Failed);
113 }
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -0600114 }
115#endif
116
Adriana Kobylak9f89e2e2018-05-30 13:16:20 -0500117 flashWrite();
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500118
119 activationProgress->progress(10);
Michael Tritzbed88af2017-07-19 16:00:06 -0500120 }
121 else if (rwVolumeCreated == true && roVolumeCreated == true)
Saqib Khan4c1aec02017-07-06 11:46:13 -0500122 {
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500123 if (ubootEnvVarsUpdated == false)
Michael Tritzbed88af2017-07-19 16:00:06 -0500124 {
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500125 activationProgress->progress(90);
126
127 if (!redundancyPriority)
128 {
129 redundancyPriority = std::make_unique<RedundancyPriority>(
130 bus, path, *this, 0);
131 }
Michael Tritzbed88af2017-07-19 16:00:06 -0500132 }
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500133 else
134 {
135 activationProgress->progress(100);
Saqib Khan4c1aec02017-07-06 11:46:13 -0500136
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500137 activationBlocksTransition.reset(nullptr);
138 activationProgress.reset(nullptr);
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500139
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500140 rwVolumeCreated = false;
141 roVolumeCreated = false;
142 ubootEnvVarsUpdated = false;
143 Activation::unsubscribeFromSystemdSignals();
Michael Tritzf2b5e0d2017-07-25 14:39:34 -0500144
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500145 // Remove version object from image manager
146 Activation::deleteImageManagerObject();
Michael Tritzf2b5e0d2017-07-25 14:39:34 -0500147
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500148 // Create active association
149 parent.createActiveAssociation(path);
Saqib Khanee13e832017-10-23 12:53:11 -0500150
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500151 return softwareServer::Activation::activation(
152 softwareServer::Activation::Activations::Active);
153 }
Michael Tritzbed88af2017-07-19 16:00:06 -0500154 }
Lei YUa7853ee2018-05-23 11:13:12 +0800155#else // !UBIFS_LAYOUT
156
Lei YU90532252018-05-24 11:15:24 +0800157#ifdef WANT_SIGNATURE_VERIFY
158 fs::path uploadDir(IMG_UPLOAD_DIR);
159 if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
160 {
161 onVerifyFailed();
162 // Stop the activation process, if fieldMode is enabled.
163 if (parent.control::FieldMode::fieldModeEnabled())
164 {
165 return softwareServer::Activation::activation(
166 softwareServer::Activation::Activations::Failed);
167 }
168 }
169#endif
Lei YUa7853ee2018-05-23 11:13:12 +0800170 parent.freeSpace();
171
172 flashWrite();
173
174 if (!redundancyPriority)
175 {
176 redundancyPriority =
177 std::make_unique<RedundancyPriority>(bus, path, *this, 0);
178 }
179
180 // Remove version object from image manager
181 Activation::deleteImageManagerObject();
182
183 // Create active association
184 parent.createActiveAssociation(path);
185
186 log<level::INFO>("BMC image ready, need reboot to get activated.");
187 return softwareServer::Activation::activation(
188 softwareServer::Activation::Activations::Active);
189#endif
Saqib Khanb0774702017-05-23 16:02:41 -0500190 }
191 else
192 {
193 activationBlocksTransition.reset(nullptr);
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500194 activationProgress.reset(nullptr);
Saqib Khanb0774702017-05-23 16:02:41 -0500195 }
196 return softwareServer::Activation::activation(value);
197}
198
Saqib Khanee13e832017-10-23 12:53:11 -0500199void Activation::deleteImageManagerObject()
200{
Saqib Khanee13e832017-10-23 12:53:11 -0500201 // Call the Delete object for <versionID> inside image_manager
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600202 auto method = this->bus.new_method_call(VERSION_BUSNAME, path.c_str(),
203 "xyz.openbmc_project.Object.Delete",
204 "Delete");
Adriana Kobylak00bd9022018-01-24 13:55:58 -0600205 auto mapperResponseMsg = bus.call(method);
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600206 // Check that the bus call didn't result in an error
Saqib Khanee13e832017-10-23 12:53:11 -0500207 if (mapperResponseMsg.is_method_error())
208 {
209 log<level::ERR>("Error in Deleting image from image manager",
Adriana Kobylak596466b2018-02-13 14:48:53 -0600210 entry("VERSIONPATH=%s", path.c_str()));
Saqib Khanee13e832017-10-23 12:53:11 -0500211 return;
212 }
213}
214
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600215auto Activation::requestedActivation(RequestedActivations value)
216 -> RequestedActivations
Saqib Khanb0774702017-05-23 16:02:41 -0500217{
Michael Tritzbed88af2017-07-19 16:00:06 -0500218 rwVolumeCreated = false;
219 roVolumeCreated = false;
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500220 ubootEnvVarsUpdated = false;
Michael Tritzbed88af2017-07-19 16:00:06 -0500221
Saqib Khanb0774702017-05-23 16:02:41 -0500222 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
223 (softwareServer::Activation::requestedActivation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600224 softwareServer::Activation::RequestedActivations::Active))
Saqib Khanb0774702017-05-23 16:02:41 -0500225 {
226 if ((softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600227 softwareServer::Activation::Activations::Ready) ||
Saqib Khanb0774702017-05-23 16:02:41 -0500228 (softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600229 softwareServer::Activation::Activations::Failed))
Saqib Khanb0774702017-05-23 16:02:41 -0500230 {
231 Activation::activation(
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600232 softwareServer::Activation::Activations::Activating);
Saqib Khanb0774702017-05-23 16:02:41 -0500233 }
234 }
235 return softwareServer::Activation::requestedActivation(value);
236}
237
Saqib Khan4c1aec02017-07-06 11:46:13 -0500238uint8_t RedundancyPriority::priority(uint8_t value)
239{
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500240 // Set the priority value so that the freePriority() function can order
241 // the versions by priority.
242 auto newPriority = softwareServer::RedundancyPriority::priority(value);
Saqib Khan5d532672017-08-09 10:44:50 -0500243 storeToFile(parent.versionId, value);
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500244 parent.parent.freePriority(value, parent.versionId);
245 return newPriority;
Saqib Khan4c1aec02017-07-06 11:46:13 -0500246}
247
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500248uint8_t RedundancyPriority::sdbusPriority(uint8_t value)
Saqib Khanf0382c32017-10-24 13:36:22 -0500249{
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500250 storeToFile(parent.versionId, value);
251 return softwareServer::RedundancyPriority::priority(value);
Saqib Khanf0382c32017-10-24 13:36:22 -0500252}
253
Michael Tritzbed88af2017-07-19 16:00:06 -0500254void Activation::unitStateChange(sdbusplus::message::message& msg)
255{
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500256 if (softwareServer::Activation::activation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600257 softwareServer::Activation::Activations::Activating)
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500258 {
259 return;
260 }
261
Adriana Kobylak3ce563a2018-06-06 16:41:15 -0500262 onStateChanges(msg);
Michael Tritzbed88af2017-07-19 16:00:06 -0500263
264 return;
265}
266
Lei YU90532252018-05-24 11:15:24 +0800267#ifdef WANT_SIGNATURE_VERIFY
268bool Activation::verifySignature(const fs::path& imageDir,
269 const fs::path& confDir)
270{
271 using Signature = phosphor::software::image::Signature;
272
273 Signature signature(imageDir, confDir);
274
275 return signature.verify();
276}
277
278void Activation::onVerifyFailed()
279{
280 log<level::ERR>("Error occurred during image validation");
281 report<InternalFailure>();
282}
283#endif
284
Saqib Khanf37cefc2017-09-12 08:44:41 -0500285void ActivationBlocksTransition::enableRebootGuard()
286{
287 log<level::INFO>("BMC image activating - BMC reboots are disabled.");
288
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600289 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
290 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500291 method.append("reboot-guard-enable.service", "replace");
292 bus.call_noreply(method);
293}
294
295void ActivationBlocksTransition::disableRebootGuard()
296{
297 log<level::INFO>("BMC activation has ended - BMC reboots are re-enabled.");
298
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600299 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
300 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500301 method.append("reboot-guard-disable.service", "replace");
302 bus.call_noreply(method);
303}
Michael Tritzbed88af2017-07-19 16:00:06 -0500304
Saqib Khanb0774702017-05-23 16:02:41 -0500305} // namespace updater
306} // namespace software
307} // namespace phosphor