blob: c90b537b39a913ccf9fbdab74e41fea9b5280a2b [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"
Miguel Gomez21dad042020-06-26 20:54:48 +00005#include "msl_verify.hpp"
Saqib Khan5d532672017-08-09 10:44:50 -05006#include "serialize.hpp"
Gunnar Millsb0ce9962018-09-07 13:39:10 -05007
Lei YU25868182021-05-14 14:50:51 +08008#include <boost/asio/io_context.hpp>
Lei YU7d2fa142021-08-06 10:58:19 +08009#include <boost/asio/post.hpp>
Jayashankar Padatha0135602019-04-22 16:22:58 +053010#include <phosphor-logging/elog-errors.hpp>
11#include <phosphor-logging/elog.hpp>
Patrick Williamsc9bb6422021-08-27 06:18:35 -050012#include <phosphor-logging/lg2.hpp>
Adriana Kobylakaea48f22018-07-10 10:20:56 -050013#include <sdbusplus/exception.hpp>
Jayashankar Padatha0135602019-04-22 16:22:58 +053014#include <xyz/openbmc_project/Common/error.hpp>
Miguel Gomez21dad042020-06-26 20:54:48 +000015#include <xyz/openbmc_project/Software/Version/error.hpp>
Saqib Khanb9da6632017-09-13 09:48:37 -050016
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060017#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060018#include "image_verify.hpp"
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060019#endif
20
Lei YU25868182021-05-14 14:50:51 +080021extern boost::asio::io_context& getIOContext();
22
Saqib Khanb0774702017-05-23 16:02:41 -050023namespace phosphor
24{
25namespace software
26{
27namespace updater
28{
29
30namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
31
Patrick Williamsc9bb6422021-08-27 06:18:35 -050032PHOSPHOR_LOG2_USING;
Saqib Khanb9da6632017-09-13 09:48:37 -050033using namespace phosphor::logging;
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060034using InternalFailure =
35 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Jayashankar Padatha0135602019-04-22 16:22:58 +053036
37#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth9a9d7c22018-03-28 10:05:26 -050038namespace control = sdbusplus::xyz::openbmc_project::Control::server;
Jayanth Othayoth0e0c1272018-02-21 05:46:36 -060039#endif
40
Michael Tritzbed88af2017-07-19 16:00:06 -050041void Activation::subscribeToSystemdSignals()
42{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060043 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
44 SYSTEMD_INTERFACE, "Subscribe");
Adriana Kobylakaea48f22018-07-10 10:20:56 -050045 try
46 {
47 this->bus.call_noreply(method);
48 }
Patrick Williams4ce901c2021-09-02 09:34:45 -050049 catch (const sdbusplus::exception::exception& e)
Adriana Kobylakaea48f22018-07-10 10:20:56 -050050 {
51 if (e.name() != nullptr &&
52 strcmp("org.freedesktop.systemd1.AlreadySubscribed", e.name()) == 0)
53 {
54 // If an Activation attempt fails, the Unsubscribe method is not
55 // called. This may lead to an AlreadySubscribed error if the
56 // Activation is re-attempted.
57 }
58 else
59 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050060 error("Error subscribing to systemd: {ERROR}", "ERROR", e);
Adriana Kobylakaea48f22018-07-10 10:20:56 -050061 }
62 }
Michael Tritzbed88af2017-07-19 16:00:06 -050063
64 return;
65}
66
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050067void Activation::unsubscribeFromSystemdSignals()
68{
Adriana Kobylak2285fe02018-02-27 15:36:59 -060069 auto method = this->bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
70 SYSTEMD_INTERFACE, "Unsubscribe");
Jayashankar Padatha0135602019-04-22 16:22:58 +053071 try
72 {
73 this->bus.call_noreply(method);
74 }
Patrick Williams4ce901c2021-09-02 09:34:45 -050075 catch (const sdbusplus::exception::exception& e)
Jayashankar Padatha0135602019-04-22 16:22:58 +053076 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050077 error("Error unsubscribing from systemd signals: {ERROR}", "ERROR", e);
Jayashankar Padatha0135602019-04-22 16:22:58 +053078 }
Michael Tritzf2b5e0d2017-07-25 14:39:34 -050079
80 return;
81}
82
Adriana Kobylak2285fe02018-02-27 15:36:59 -060083auto Activation::activation(Activations value) -> Activations
Saqib Khanb0774702017-05-23 16:02:41 -050084{
Adriana Kobylak8bd84c82018-01-24 14:19:24 -060085 if ((value != softwareServer::Activation::Activations::Active) &&
86 (value != softwareServer::Activation::Activations::Activating))
Saqib Khan4c1aec02017-07-06 11:46:13 -050087 {
88 redundancyPriority.reset(nullptr);
89 }
90
Saqib Khanb0774702017-05-23 16:02:41 -050091 if (value == softwareServer::Activation::Activations::Activating)
92 {
Lei YU7ab55e22021-05-19 13:26:53 +080093#ifdef WANT_SIGNATURE_VERIFY
94 fs::path uploadDir(IMG_UPLOAD_DIR);
95 if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
96 {
97 onVerifyFailed();
98 // Stop the activation process, if fieldMode is enabled.
99 if (parent.control::FieldMode::fieldModeEnabled())
100 {
101 return softwareServer::Activation::activation(
102 softwareServer::Activation::Activations::Failed);
103 }
104 }
105#endif
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800106
107#ifdef HOST_BIOS_UPGRADE
108 auto purpose = parent.versions.find(versionId)->second->purpose();
109 if (purpose == VersionPurpose::Host)
110 {
111 if (!activationProgress)
112 {
113 activationProgress =
114 std::make_unique<ActivationProgress>(bus, path);
115 }
116
117 // Enable systemd signals
118 subscribeToSystemdSignals();
119
120 // Set initial progress
121 activationProgress->progress(20);
122
123 // Initiate image writing to flash
124 flashWriteHost();
125
126 return softwareServer::Activation::activation(value);
127 }
128#endif
129
Miguel Gomez21dad042020-06-26 20:54:48 +0000130 auto versionStr = parent.versions.find(versionId)->second->version();
131
132 if (!minimum_ship_level::verify(versionStr))
133 {
134 using namespace phosphor::logging;
135 using IncompatibleErr = sdbusplus::xyz::openbmc_project::Software::
136 Version::Error::Incompatible;
137 using Incompatible =
138 xyz::openbmc_project::Software::Version::Incompatible;
139
140 report<IncompatibleErr>(
141 prev_entry<Incompatible::MIN_VERSION>(),
142 prev_entry<Incompatible::ACTUAL_VERSION>(),
143 prev_entry<Incompatible::VERSION_PURPOSE>());
144 return softwareServer::Activation::activation(
145 softwareServer::Activation::Activations::Failed);
146 }
147
Adriana Kobylakb824b2f2020-05-14 14:57:53 -0500148 if (!activationProgress)
149 {
150 activationProgress =
151 std::make_unique<ActivationProgress>(bus, path);
152 }
153
154 if (!activationBlocksTransition)
155 {
156 activationBlocksTransition =
157 std::make_unique<ActivationBlocksTransition>(bus, path);
158 }
159
160 activationProgress->progress(10);
161
Adriana Kobylaka6963592018-09-07 14:13:29 -0500162 parent.freeSpace(*this);
Lei YUa7853ee2018-05-23 11:13:12 +0800163
Adriana Kobylakb824b2f2020-05-14 14:57:53 -0500164 // Enable systemd signals
165 Activation::subscribeToSystemdSignals();
166
Lei YUa7853ee2018-05-23 11:13:12 +0800167 flashWrite();
168
Adriana Kobylak70f5bc02020-05-13 14:08:14 -0500169#if defined UBIFS_LAYOUT || defined MMC_LAYOUT
Lei YUa7853ee2018-05-23 11:13:12 +0800170
Adriana Kobylakb824b2f2020-05-14 14:57:53 -0500171 return softwareServer::Activation::activation(value);
Lei YUa7853ee2018-05-23 11:13:12 +0800172
Adriana Kobylak70f5bc02020-05-13 14:08:14 -0500173#else // STATIC_LAYOUT
Lei YUa7853ee2018-05-23 11:13:12 +0800174
Adriana Kobylakb824b2f2020-05-14 14:57:53 -0500175 onFlashWriteSuccess();
Lei YUa7853ee2018-05-23 11:13:12 +0800176 return softwareServer::Activation::activation(
177 softwareServer::Activation::Activations::Active);
178#endif
Saqib Khanb0774702017-05-23 16:02:41 -0500179 }
180 else
181 {
182 activationBlocksTransition.reset(nullptr);
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500183 activationProgress.reset(nullptr);
Saqib Khanb0774702017-05-23 16:02:41 -0500184 }
185 return softwareServer::Activation::activation(value);
186}
187
Adriana Kobylakb824b2f2020-05-14 14:57:53 -0500188void Activation::onFlashWriteSuccess()
189{
190 activationProgress->progress(100);
191
192 activationBlocksTransition.reset(nullptr);
193 activationProgress.reset(nullptr);
194
195 rwVolumeCreated = false;
196 roVolumeCreated = false;
197 ubootEnvVarsUpdated = false;
198 Activation::unsubscribeFromSystemdSignals();
199
200 storePurpose(versionId, parent.versions.find(versionId)->second->purpose());
201
202 if (!redundancyPriority)
203 {
204 redundancyPriority =
205 std::make_unique<RedundancyPriority>(bus, path, *this, 0);
206 }
207
208 // Remove version object from image manager
209 Activation::deleteImageManagerObject();
210
211 // Create active association
212 parent.createActiveAssociation(path);
213
214 // Create updateable association as this
215 // can be re-programmed.
216 parent.createUpdateableAssociation(path);
217
218 if (Activation::checkApplyTimeImmediate() == true)
219 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500220 info("Image Active and ApplyTime is immediate; rebooting BMC.");
Adriana Kobylakb824b2f2020-05-14 14:57:53 -0500221 Activation::rebootBmc();
222 }
223 else
224 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500225 info("BMC image ready; need reboot to get activated.");
Adriana Kobylakb824b2f2020-05-14 14:57:53 -0500226 }
227
228 activation(softwareServer::Activation::Activations::Active);
229}
230
Saqib Khanee13e832017-10-23 12:53:11 -0500231void Activation::deleteImageManagerObject()
232{
Saqib Khanee13e832017-10-23 12:53:11 -0500233 // Call the Delete object for <versionID> inside image_manager
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600234 auto method = this->bus.new_method_call(VERSION_BUSNAME, path.c_str(),
235 "xyz.openbmc_project.Object.Delete",
236 "Delete");
Adriana Kobylak3b6a4cd2018-12-10 13:45:09 -0600237 try
238 {
239 bus.call_noreply(method);
240 }
Patrick Williams4ce901c2021-09-02 09:34:45 -0500241 catch (const sdbusplus::exception::exception& e)
Saqib Khanee13e832017-10-23 12:53:11 -0500242 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500243 error("Error deleting image ({PATH}) from image manager: {ERROR}",
244 "PATH", path, "ERROR", e);
Saqib Khanee13e832017-10-23 12:53:11 -0500245 return;
246 }
247}
248
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600249auto Activation::requestedActivation(RequestedActivations value)
250 -> RequestedActivations
Saqib Khanb0774702017-05-23 16:02:41 -0500251{
Michael Tritzbed88af2017-07-19 16:00:06 -0500252 rwVolumeCreated = false;
253 roVolumeCreated = false;
Adriana Kobylak166bdf32018-04-09 14:24:06 -0500254 ubootEnvVarsUpdated = false;
Michael Tritzbed88af2017-07-19 16:00:06 -0500255
Saqib Khanb0774702017-05-23 16:02:41 -0500256 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
257 (softwareServer::Activation::requestedActivation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600258 softwareServer::Activation::RequestedActivations::Active))
Saqib Khanb0774702017-05-23 16:02:41 -0500259 {
260 if ((softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600261 softwareServer::Activation::Activations::Ready) ||
Saqib Khanb0774702017-05-23 16:02:41 -0500262 (softwareServer::Activation::activation() ==
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600263 softwareServer::Activation::Activations::Failed))
Saqib Khanb0774702017-05-23 16:02:41 -0500264 {
265 Activation::activation(
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600266 softwareServer::Activation::Activations::Activating);
Saqib Khanb0774702017-05-23 16:02:41 -0500267 }
268 }
269 return softwareServer::Activation::requestedActivation(value);
270}
271
Saqib Khan4c1aec02017-07-06 11:46:13 -0500272uint8_t RedundancyPriority::priority(uint8_t value)
273{
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500274 // Set the priority value so that the freePriority() function can order
275 // the versions by priority.
276 auto newPriority = softwareServer::RedundancyPriority::priority(value);
Adriana Kobylakbbcb7be2018-07-17 15:47:34 -0500277 parent.parent.savePriority(parent.versionId, value);
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500278 parent.parent.freePriority(value, parent.versionId);
279 return newPriority;
Saqib Khan4c1aec02017-07-06 11:46:13 -0500280}
281
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500282uint8_t RedundancyPriority::sdbusPriority(uint8_t value)
Saqib Khanf0382c32017-10-24 13:36:22 -0500283{
Adriana Kobylakbbcb7be2018-07-17 15:47:34 -0500284 parent.parent.savePriority(parent.versionId, value);
Adriana Kobylakb77551c2017-10-27 12:46:23 -0500285 return softwareServer::RedundancyPriority::priority(value);
Saqib Khanf0382c32017-10-24 13:36:22 -0500286}
287
Michael Tritzbed88af2017-07-19 16:00:06 -0500288void Activation::unitStateChange(sdbusplus::message::message& msg)
289{
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500290 if (softwareServer::Activation::activation() !=
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600291 softwareServer::Activation::Activations::Activating)
Michael Tritz0edd4ad2017-07-26 14:27:42 -0500292 {
293 return;
294 }
295
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800296#ifdef HOST_BIOS_UPGRADE
297 auto purpose = parent.versions.find(versionId)->second->purpose();
298 if (purpose == VersionPurpose::Host)
299 {
300 onStateChangesBios(msg);
301 return;
302 }
303#endif
304
Adriana Kobylak3ce563a2018-06-06 16:41:15 -0500305 onStateChanges(msg);
Michael Tritzbed88af2017-07-19 16:00:06 -0500306
307 return;
308}
309
Lei YU90532252018-05-24 11:15:24 +0800310#ifdef WANT_SIGNATURE_VERIFY
311bool Activation::verifySignature(const fs::path& imageDir,
312 const fs::path& confDir)
313{
314 using Signature = phosphor::software::image::Signature;
315
316 Signature signature(imageDir, confDir);
317
318 return signature.verify();
319}
320
321void Activation::onVerifyFailed()
322{
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500323 error("Error occurred during image validation");
Lei YU90532252018-05-24 11:15:24 +0800324 report<InternalFailure>();
325}
326#endif
327
Saqib Khanf37cefc2017-09-12 08:44:41 -0500328void ActivationBlocksTransition::enableRebootGuard()
329{
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500330 info("BMC image activating - BMC reboots are disabled.");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500331
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600332 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
333 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500334 method.append("reboot-guard-enable.service", "replace");
335 bus.call_noreply(method);
336}
337
338void ActivationBlocksTransition::disableRebootGuard()
339{
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500340 info("BMC activation has ended - BMC reboots are re-enabled.");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500341
Adriana Kobylak2285fe02018-02-27 15:36:59 -0600342 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
343 SYSTEMD_INTERFACE, "StartUnit");
Saqib Khanf37cefc2017-09-12 08:44:41 -0500344 method.append("reboot-guard-disable.service", "replace");
345 bus.call_noreply(method);
346}
Michael Tritzbed88af2017-07-19 16:00:06 -0500347
Jayashankar Padatha0135602019-04-22 16:22:58 +0530348bool Activation::checkApplyTimeImmediate()
349{
350 auto service = utils::getService(bus, applyTimeObjPath, applyTimeIntf);
351 if (service.empty())
352 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500353 info("Error getting the service name for BMC image ApplyTime. "
354 "The BMC needs to be manually rebooted to complete the image "
355 "activation if needed immediately.");
Jayashankar Padatha0135602019-04-22 16:22:58 +0530356 }
357 else
358 {
359
360 auto method = bus.new_method_call(service.c_str(), applyTimeObjPath,
361 dbusPropIntf, "Get");
362 method.append(applyTimeIntf, applyTimeProp);
363
364 try
365 {
366 auto reply = bus.call(method);
367
Patrick Williams24048b52020-05-13 17:51:30 -0500368 std::variant<std::string> result;
Jayashankar Padatha0135602019-04-22 16:22:58 +0530369 reply.read(result);
Patrick Williamse883fb82020-05-13 11:38:55 -0500370 auto applyTime = std::get<std::string>(result);
Jayashankar Padatha0135602019-04-22 16:22:58 +0530371 if (applyTime == applyTimeImmediate)
372 {
373 return true;
374 }
375 }
Patrick Williams4ce901c2021-09-02 09:34:45 -0500376 catch (const sdbusplus::exception::exception& e)
Jayashankar Padatha0135602019-04-22 16:22:58 +0530377 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500378 error("Error in getting ApplyTime: {ERROR}", "ERROR", e);
Jayashankar Padatha0135602019-04-22 16:22:58 +0530379 }
380 }
381 return false;
382}
383
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800384#ifdef HOST_BIOS_UPGRADE
385void Activation::flashWriteHost()
386{
387 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
388 SYSTEMD_INTERFACE, "StartUnit");
389 auto biosServiceFile = "obmc-flash-host-bios@" + versionId + ".service";
390 method.append(biosServiceFile, "replace");
391 try
392 {
393 auto reply = bus.call(method);
394 }
Patrick Williams4ce901c2021-09-02 09:34:45 -0500395 catch (const sdbusplus::exception::exception& e)
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800396 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500397 error("Error in trying to upgrade Host Bios: {ERROR}", "ERROR", e);
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800398 report<InternalFailure>();
399 }
400}
401
402void Activation::onStateChangesBios(sdbusplus::message::message& msg)
403{
404 uint32_t newStateID{};
405 sdbusplus::message::object_path newStateObjPath;
406 std::string newStateUnit{};
407 std::string newStateResult{};
408
409 // Read the msg and populate each variable
410 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
411
412 auto biosServiceFile = "obmc-flash-host-bios@" + versionId + ".service";
413
414 if (newStateUnit == biosServiceFile)
415 {
416 // unsubscribe to systemd signals
417 unsubscribeFromSystemdSignals();
418
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800419 if (newStateResult == "done")
420 {
421 // Set activation progress to 100
422 activationProgress->progress(100);
423
424 // Set Activation value to active
425 activation(softwareServer::Activation::Activations::Active);
426
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500427 info("Bios upgrade completed successfully.");
Lei YU16aa28a2021-05-07 10:17:30 +0800428 parent.biosVersion->version(
429 parent.versions.find(versionId)->second->version());
Lei YU25868182021-05-14 14:50:51 +0800430
431 // Delete the uploaded activation
Lei YU7d2fa142021-08-06 10:58:19 +0800432 boost::asio::post(getIOContext(), [this]() {
433 this->parent.erase(this->versionId);
Lei YU25868182021-05-14 14:50:51 +0800434 });
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800435 }
436 else if (newStateResult == "failed")
437 {
438 // Set Activation value to Failed
439 activation(softwareServer::Activation::Activations::Failed);
440
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500441 error("Bios upgrade failed.");
Vijay Khemkae9f6c842020-01-14 14:32:39 -0800442 }
443 }
444
445 return;
446}
447
448#endif
449
Jayashankar Padatha0135602019-04-22 16:22:58 +0530450void Activation::rebootBmc()
451{
452 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
453 SYSTEMD_INTERFACE, "StartUnit");
454 method.append("force-reboot.service", "replace");
455 try
456 {
457 auto reply = bus.call(method);
458 }
Patrick Williams4ce901c2021-09-02 09:34:45 -0500459 catch (const sdbusplus::exception::exception& e)
Jayashankar Padatha0135602019-04-22 16:22:58 +0530460 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500461 alert("Error in trying to reboot the BMC. The BMC needs to be manually "
462 "rebooted to complete the image activation. {ERROR}",
463 "ERROR", e);
Jayashankar Padatha0135602019-04-22 16:22:58 +0530464 report<InternalFailure>();
465 }
466}
467
Saqib Khanb0774702017-05-23 16:02:41 -0500468} // namespace updater
469} // namespace software
470} // namespace phosphor