blob: ce20dcbd28e330b5cf3106559f3f5477173fde93 [file] [log] [blame]
Adriana Kobylak55f9e832017-05-14 16:13:00 -05001#include <experimental/filesystem>
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -05002#include "activation.hpp"
Adriana Kobylak692b5552017-04-17 14:02:58 -05003#include "config.h"
Saqib Khan81bac882017-06-08 12:17:01 -05004#include "item_updater.hpp"
Michael Tritz60bc20f2017-07-29 23:32:21 -05005#include "serialize.hpp"
Saqib Khan7f80e0b2017-10-22 11:29:07 -05006#include <phosphor-logging/log.hpp>
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -05007
Jayanth Othayoth4016e522018-03-20 09:39:06 -05008#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"
13#include "config.h"
14#endif
15
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050016namespace openpower
17{
18namespace software
19{
20namespace updater
21{
22
Adriana Kobylak55f9e832017-05-14 16:13:00 -050023namespace fs = std::experimental::filesystem;
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050024namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
25
Saqib Khan7f80e0b2017-10-22 11:29:07 -050026using namespace phosphor::logging;
27
Jayanth Othayoth4016e522018-03-20 09:39:06 -050028#ifdef WANT_SIGNATURE_VERIFY
29using InternalFailure =
30 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
31#endif
32
Adriana Kobylak70dcb632018-02-27 15:46:52 -060033constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
34constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
Michael Tritz9d25b602017-06-14 14:41:43 -050035
36void Activation::subscribeToSystemdSignals()
37{
Adriana Kobylak70dcb632018-02-27 15:46:52 -060038 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
39 SYSTEMD_INTERFACE, "Subscribe");
Michael Tritz9d25b602017-06-14 14:41:43 -050040 this->bus.call_noreply(method);
41
42 return;
43}
44
Michael Tritz1cb127f2017-07-26 15:40:38 -050045void Activation::unsubscribeFromSystemdSignals()
46{
Adriana Kobylak70dcb632018-02-27 15:46:52 -060047 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
48 SYSTEMD_INTERFACE, "Unsubscribe");
Michael Tritz1cb127f2017-07-26 15:40:38 -050049 this->bus.call_noreply(method);
50
51 return;
52}
53
Michael Tritz1cb127f2017-07-26 15:40:38 -050054void Activation::startActivation()
55{
56 // Since the squashfs image has not yet been loaded to pnor and the
57 // RW volumes have not yet been created, we need to start the
58 // service files for each of those actions.
59
60 if (!activationProgress)
61 {
Adriana Kobylak70dcb632018-02-27 15:46:52 -060062 activationProgress = std::make_unique<ActivationProgress>(bus, path);
Michael Tritz1cb127f2017-07-26 15:40:38 -050063 }
64
65 if (!activationBlocksTransition)
66 {
67 activationBlocksTransition =
Adriana Kobylak70dcb632018-02-27 15:46:52 -060068 std::make_unique<ActivationBlocksTransition>(bus, path);
Michael Tritz1cb127f2017-07-26 15:40:38 -050069 }
70
Michael Tritz1cb127f2017-07-26 15:40:38 -050071 constexpr auto ubimountService = "obmc-flash-bios-ubimount@";
Adriana Kobylak70dcb632018-02-27 15:46:52 -060072 auto ubimountServiceFile =
73 std::string(ubimountService) + versionId + ".service";
74 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
75 SYSTEMD_INTERFACE, "StartUnit");
Michael Tritz1cb127f2017-07-26 15:40:38 -050076 method.append(ubimountServiceFile, "replace");
77 bus.call_noreply(method);
78
79 activationProgress->progress(10);
80}
81
82void Activation::finishActivation()
83{
84 activationProgress->progress(90);
Michael Tritz1cb127f2017-07-26 15:40:38 -050085
86 // Set Redundancy Priority before setting to Active
87 if (!redundancyPriority)
88 {
Adriana Kobylak70dcb632018-02-27 15:46:52 -060089 redundancyPriority =
90 std::make_unique<RedundancyPriority>(bus, path, *this, 0);
Michael Tritz1cb127f2017-07-26 15:40:38 -050091 }
92
93 activationProgress->progress(100);
94
95 activationBlocksTransition.reset(nullptr);
96 activationProgress.reset(nullptr);
97
Saqib Khan1e0aa5c2017-08-31 11:04:17 -050098 ubiVolumesCreated = false;
Michael Tritz1cb127f2017-07-26 15:40:38 -050099 Activation::unsubscribeFromSystemdSignals();
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500100 // Remove version object from image manager
101 Activation::deleteImageManagerObject();
Gunnar Mills9741cd12017-08-28 15:09:00 -0500102 // Create active association
103 parent.createActiveAssociation(path);
Michael Tritz1cb127f2017-07-26 15:40:38 -0500104}
105
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600106auto Activation::activation(Activations value) -> Activations
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500107{
Saqib Khan942df8a2017-06-01 14:09:27 -0500108
109 if (value != softwareServer::Activation::Activations::Active)
110 {
111 redundancyPriority.reset(nullptr);
112 }
113
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500114 if (value == softwareServer::Activation::Activations::Activating)
115 {
Saqib Khan2cbfa032017-08-17 14:52:37 -0500116 parent.freeSpace();
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500117 softwareServer::Activation::activation(value);
118
Saqib Khan1e0aa5c2017-08-31 11:04:17 -0500119 if (ubiVolumesCreated == false)
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500120 {
Jayanth Othayoth4016e522018-03-20 09:39:06 -0500121
122#ifdef WANT_SIGNATURE_VERIFY
123 using Signature = openpower::software::image::Signature;
124
125 fs::path imagePath(IMG_DIR);
126
127 Signature signature(imagePath / versionId, SIGNED_IMAGE_CONF_PATH);
128
129 // Validate the signed image.
130 if (!signature.verify())
131 {
132 log<level::ERR>("Error occurred during image validation");
133 report<InternalFailure>();
134
135 return softwareServer::Activation::activation(
136 softwareServer::Activation::Activations::Failed);
137 }
138#endif
139
Michael Tritz1cb127f2017-07-26 15:40:38 -0500140 Activation::startActivation();
Michael Tritz9d25b602017-06-14 14:41:43 -0500141 return softwareServer::Activation::activation(value);
142 }
Saqib Khan1e0aa5c2017-08-31 11:04:17 -0500143 else if (ubiVolumesCreated == true)
Michael Tritz9d25b602017-06-14 14:41:43 -0500144 {
145 // Only when the squashfs image is finished loading AND the RW
Michael Tritz1cb127f2017-07-26 15:40:38 -0500146 // volumes have been created do we proceed with activation. To
147 // verify that this happened, we check for the mount dirs PNOR_PRSV
148 // and PNOR_RW_PREFIX_<versionid>, as well as the image dir R0.
Michael Tritz9d25b602017-06-14 14:41:43 -0500149
Michael Tritz9d25b602017-06-14 14:41:43 -0500150 if ((fs::is_directory(PNOR_PRSV)) &&
151 (fs::is_directory(PNOR_RW_PREFIX + versionId)) &&
152 (fs::is_directory(PNOR_RO_PREFIX + versionId)))
153 {
Michael Tritz1cb127f2017-07-26 15:40:38 -0500154 Activation::finishActivation();
Michael Tritz9d25b602017-06-14 14:41:43 -0500155 return softwareServer::Activation::activation(
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600156 softwareServer::Activation::Activations::Active);
Michael Tritz9d25b602017-06-14 14:41:43 -0500157 }
158 else
159 {
Saqib Khancb9df4e2017-06-26 11:06:07 -0500160 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500161 activationProgress.reset(nullptr);
Michael Tritz9d25b602017-06-14 14:41:43 -0500162 return softwareServer::Activation::activation(
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600163 softwareServer::Activation::Activations::Failed);
Michael Tritz9d25b602017-06-14 14:41:43 -0500164 }
Adriana Kobylak55f9e832017-05-14 16:13:00 -0500165 }
Adriana Kobylak692b5552017-04-17 14:02:58 -0500166 }
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500167 else
168 {
169 activationBlocksTransition.reset(nullptr);
Michael Tritz1793b642017-06-28 18:35:58 -0500170 activationProgress.reset(nullptr);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500171 }
Michael Tritz1cb127f2017-07-26 15:40:38 -0500172
173 return softwareServer::Activation::activation(value);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500174}
175
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600176auto Activation::requestedActivation(RequestedActivations value)
177 -> RequestedActivations
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500178{
Saqib Khan1e0aa5c2017-08-31 11:04:17 -0500179 ubiVolumesCreated = false;
Michael Tritz9d25b602017-06-14 14:41:43 -0500180
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500181 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
182 (softwareServer::Activation::requestedActivation() !=
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600183 softwareServer::Activation::RequestedActivations::Active))
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500184 {
185 if ((softwareServer::Activation::activation() ==
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600186 softwareServer::Activation::Activations::Ready) ||
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500187 (softwareServer::Activation::activation() ==
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600188 softwareServer::Activation::Activations::Failed))
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500189 {
190 Activation::activation(
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600191 softwareServer::Activation::Activations::Activating);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -0500192 }
193 }
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -0500194 return softwareServer::Activation::requestedActivation(value);
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500195}
196
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500197void Activation::deleteImageManagerObject()
198{
199 // Get the Delete object for <versionID> inside image_manager
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600200 auto method = this->bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
201 MAPPER_INTERFACE, "GetObject");
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500202
203 method.append(path);
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600204 method.append(
205 std::vector<std::string>({"xyz.openbmc_project.Object.Delete"}));
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500206 auto mapperResponseMsg = bus.call(method);
207 if (mapperResponseMsg.is_method_error())
208 {
209 log<level::ERR>("Error in Get Delete Object",
210 entry("VERSIONPATH=%s", path));
211 return;
212 }
213 std::map<std::string, std::vector<std::string>> mapperResponse;
214 mapperResponseMsg.read(mapperResponse);
215 if (mapperResponse.begin() == mapperResponse.end())
216 {
217 log<level::ERR>("ERROR in reading the mapper response",
218 entry("VERSIONPATH=%s", path));
219 return;
220 }
221
222 // Call the Delete object for <versionID> inside image_manager
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600223 method = this->bus.new_method_call(
224 (mapperResponse.begin()->first).c_str(), path.c_str(),
225 "xyz.openbmc_project.Object.Delete", "Delete");
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500226 mapperResponseMsg = bus.call(method);
227
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600228 // Check that the bus call didn't result in an error
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500229 if (mapperResponseMsg.is_method_error())
230 {
231 log<level::ERR>("Error in Deleting image from image manager",
232 entry("VERSIONPATH=%s", path));
233 return;
234 }
235}
236
Saqib Khan2021b4c2017-06-07 14:37:36 -0500237uint8_t RedundancyPriority::priority(uint8_t value)
238{
Saqib Khanb8e7f312017-08-12 10:24:10 -0500239 parent.parent.freePriority(value, parent.versionId);
Michael Tritz60bc20f2017-07-29 23:32:21 -0500240 storeToFile(parent.versionId, value);
Saqib Khan2021b4c2017-06-07 14:37:36 -0500241 return softwareServer::RedundancyPriority::priority(value);
242}
243
Michael Tritz9d25b602017-06-14 14:41:43 -0500244void Activation::unitStateChange(sdbusplus::message::message& msg)
245{
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600246 uint32_t newStateID{};
Michael Tritz9d25b602017-06-14 14:41:43 -0500247 sdbusplus::message::object_path newStateObjPath;
248 std::string newStateUnit{};
249 std::string newStateResult{};
250
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600251 // Read the msg and populate each variable
Michael Tritz9d25b602017-06-14 14:41:43 -0500252 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
253
Michael Tritz9d25b602017-06-14 14:41:43 -0500254 auto ubimountServiceFile =
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600255 "obmc-flash-bios-ubimount@" + versionId + ".service";
Michael Tritz9d25b602017-06-14 14:41:43 -0500256
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600257 if (newStateUnit == ubimountServiceFile && newStateResult == "done")
Michael Tritz9d25b602017-06-14 14:41:43 -0500258 {
Saqib Khan1e0aa5c2017-08-31 11:04:17 -0500259 ubiVolumesCreated = true;
Michael Tritz1793b642017-06-28 18:35:58 -0500260 activationProgress->progress(activationProgress->progress() + 50);
Michael Tritz9d25b602017-06-14 14:41:43 -0500261 }
262
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600263 if (ubiVolumesCreated)
Michael Tritz9d25b602017-06-14 14:41:43 -0500264 {
265 Activation::activation(
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600266 softwareServer::Activation::Activations::Activating);
Michael Tritz9d25b602017-06-14 14:41:43 -0500267 }
268
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600269 if ((newStateUnit == ubimountServiceFile) &&
Michael Tritz9d25b602017-06-14 14:41:43 -0500270 (newStateResult == "failed" || newStateResult == "dependency"))
271 {
272 Activation::activation(softwareServer::Activation::Activations::Failed);
273 }
274
275 return;
276}
277
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500278} // namespace updater
279} // namespace software
280} // namespace openpower