blob: b87370208db03a0a4273585562f0547f115b3324 [file] [log] [blame]
Adriana Kobylak692b5552017-04-17 14:02:58 -05001#include "config.h"
Gunnar Millsf6ed5892018-09-07 17:08:02 -05002
3#include "activation.hpp"
4
Saqib Khan81bac882017-06-08 12:17:01 -05005#include "item_updater.hpp"
Gunnar Millsf6ed5892018-09-07 17:08:02 -05006
Jayashankar Padath4d3d9122019-07-24 16:46:22 +05307#include <phosphor-logging/elog-errors.hpp>
8#include <phosphor-logging/elog.hpp>
Saqib Khan7f80e0b2017-10-22 11:29:07 -05009#include <phosphor-logging/log.hpp>
Gunnar Mills74b657e2018-07-13 09:27:31 -050010#include <sdbusplus/exception.hpp>
Jayashankar Padath4d3d9122019-07-24 16:46:22 +053011#include <sdbusplus/server.hpp>
12#include <xyz/openbmc_project/Common/error.hpp>
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050013
Brad Bishop9f44c992020-11-06 14:48:46 -050014#include <filesystem>
Brad Bishop8facccf2020-11-04 09:44:58 -050015
Jayanth Othayoth4016e522018-03-20 09:39:06 -050016#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth4016e522018-03-20 09:39:06 -050017#include "image_verify.hpp"
Jayanth Othayoth4016e522018-03-20 09:39:06 -050018#endif
19
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050020namespace openpower
21{
22namespace software
23{
24namespace updater
25{
26
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050027namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
28
Saqib Khan7f80e0b2017-10-22 11:29:07 -050029using namespace phosphor::logging;
Jayanth Othayoth4016e522018-03-20 09:39:06 -050030using InternalFailure =
31 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Jayanth Othayoth11271fb2018-03-29 10:25:50 -050032
Jayashankar Padath4d3d9122019-07-24 16:46:22 +053033#ifdef WANT_SIGNATURE_VERIFY
Jayanth Othayoth11271fb2018-03-29 10:25:50 -050034// Field mode path and interface.
35constexpr auto FIELDMODE_PATH("/xyz/openbmc_project/software");
36constexpr auto FIELDMODE_INTERFACE("xyz.openbmc_project.Control.FieldMode");
Jayanth Othayoth4016e522018-03-20 09:39:06 -050037#endif
38
Adriana Kobylak70dcb632018-02-27 15:46:52 -060039constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
40constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
Michael Tritz9d25b602017-06-14 14:41:43 -050041
42void Activation::subscribeToSystemdSignals()
43{
Adriana Kobylak70dcb632018-02-27 15:46:52 -060044 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
45 SYSTEMD_INTERFACE, "Subscribe");
Gunnar Mills74b657e2018-07-13 09:27:31 -050046 try
47 {
48 this->bus.call_noreply(method);
49 }
Patrick Williams0dea1992022-07-22 19:26:52 -050050 catch (const sdbusplus::exception_t& e)
Gunnar Mills74b657e2018-07-13 09:27:31 -050051 {
52 if (e.name() != nullptr &&
53 strcmp("org.freedesktop.systemd1.AlreadySubscribed", e.name()) == 0)
54 {
55 // If an Activation attempt fails, the Unsubscribe method is not
56 // called. This may lead to an AlreadySubscribed error if the
57 // Activation is re-attempted.
58 }
59 else
60 {
61 log<level::ERR>("Error subscribing to systemd",
62 entry("ERROR=%s", e.what()));
63 }
64 }
Michael Tritz9d25b602017-06-14 14:41:43 -050065 return;
66}
67
Michael Tritz1cb127f2017-07-26 15:40:38 -050068void Activation::unsubscribeFromSystemdSignals()
69{
Adriana Kobylak70dcb632018-02-27 15:46:52 -060070 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
71 SYSTEMD_INTERFACE, "Unsubscribe");
Michael Tritz1cb127f2017-07-26 15:40:38 -050072 this->bus.call_noreply(method);
73
74 return;
75}
76
Adriana Kobylak70dcb632018-02-27 15:46:52 -060077auto Activation::requestedActivation(RequestedActivations value)
78 -> RequestedActivations
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050079{
80 if ((value == softwareServer::Activation::RequestedActivations::Active) &&
81 (softwareServer::Activation::requestedActivation() !=
Adriana Kobylak70dcb632018-02-27 15:46:52 -060082 softwareServer::Activation::RequestedActivations::Active))
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050083 {
84 if ((softwareServer::Activation::activation() ==
Adriana Kobylak70dcb632018-02-27 15:46:52 -060085 softwareServer::Activation::Activations::Ready) ||
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050086 (softwareServer::Activation::activation() ==
Adriana Kobylak70dcb632018-02-27 15:46:52 -060087 softwareServer::Activation::Activations::Failed))
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050088 {
Lei YUa2e67162019-02-22 17:35:24 +080089 activation(softwareServer::Activation::Activations::Activating);
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050090 }
91 }
Adriana Kobylak99c8c0e2017-04-17 13:39:11 -050092 return softwareServer::Activation::requestedActivation(value);
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050093}
94
Saqib Khan7f80e0b2017-10-22 11:29:07 -050095void Activation::deleteImageManagerObject()
96{
97 // Get the Delete object for <versionID> inside image_manager
Lei YUc9caf862019-01-24 15:40:25 +080098 constexpr auto versionServiceStr = "xyz.openbmc_project.Software.Version";
99 constexpr auto deleteInterface = "xyz.openbmc_project.Object.Delete";
100 std::string versionService;
Adriana Kobylak70dcb632018-02-27 15:46:52 -0600101 auto method = this->bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
102 MAPPER_INTERFACE, "GetObject");
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500103
104 method.append(path);
Lei YUc9caf862019-01-24 15:40:25 +0800105 method.append(std::vector<std::string>({deleteInterface}));
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500106
107 std::map<std::string, std::vector<std::string>> mapperResponse;
108
109 try
110 {
111 auto mapperResponseMsg = bus.call(method);
112 mapperResponseMsg.read(mapperResponse);
113 if (mapperResponse.begin() == mapperResponse.end())
114 {
115 log<level::ERR>("ERROR in reading the mapper response",
116 entry("VERSIONPATH=%s", path.c_str()));
117 return;
118 }
119 }
Patrick Williams0dea1992022-07-22 19:26:52 -0500120 catch (const sdbusplus::exception_t& e)
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500121 {
122 log<level::ERR>("Error in Get Delete Object",
Joseph Reynoldsafd0a452018-05-30 11:16:03 -0500123 entry("VERSIONPATH=%s", path.c_str()));
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500124 return;
125 }
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500126
Lei YUc9caf862019-01-24 15:40:25 +0800127 // We need to find the phosphor-software-manager's version service
128 // to invoke the delete interface
129 for (auto resp : mapperResponse)
130 {
131 if (resp.first.find(versionServiceStr) != std::string::npos)
132 {
133 versionService = resp.first;
134 }
135 }
136
137 if (versionService.empty())
138 {
139 log<level::ERR>("Error finding version service");
140 return;
141 }
142
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500143 // Call the Delete object for <versionID> inside image_manager
Lei YUc9caf862019-01-24 15:40:25 +0800144 method = this->bus.new_method_call(versionService.c_str(), path.c_str(),
145 deleteInterface, "Delete");
Adriana Kobylakab435df2018-07-16 11:37:19 -0500146 try
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500147 {
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500148 bus.call(method);
Adriana Kobylakab435df2018-07-16 11:37:19 -0500149 }
Patrick Williams0dea1992022-07-22 19:26:52 -0500150 catch (const sdbusplus::exception_t& e)
Adriana Kobylakab435df2018-07-16 11:37:19 -0500151 {
152 if (e.name() != nullptr && strcmp("System.Error.ELOOP", e.name()) == 0)
153 {
154 // TODO: Error being tracked with openbmc/openbmc#3311
155 }
156 else
157 {
158 log<level::ERR>("Error performing call to Delete object path",
159 entry("ERROR=%s", e.what()),
160 entry("PATH=%s", path.c_str()));
161 }
Saqib Khan7f80e0b2017-10-22 11:29:07 -0500162 return;
163 }
164}
165
Jayashankar Padath4d3d9122019-07-24 16:46:22 +0530166bool Activation::checkApplyTimeImmediate()
167{
168 auto service = utils::getService(bus, applyTimeObjPath, applyTimeIntf);
169 if (service.empty())
170 {
171 log<level::INFO>("Error getting the service name for Host image "
172 "ApplyTime. The Host needs to be manually rebooted to "
173 "complete the image activation if needed "
174 "immediately.");
175 }
176 else
177 {
178
179 auto method = bus.new_method_call(service.c_str(), applyTimeObjPath,
180 dbusPropIntf, "Get");
181 method.append(applyTimeIntf, applyTimeProp);
182
183 try
184 {
185 auto reply = bus.call(method);
186
Patrick Williams212102e2020-05-13 17:50:50 -0500187 std::variant<std::string> result;
Jayashankar Padath4d3d9122019-07-24 16:46:22 +0530188 reply.read(result);
Patrick Williams550f31b2020-05-13 11:15:24 -0500189 auto applyTime = std::get<std::string>(result);
Jayashankar Padath4d3d9122019-07-24 16:46:22 +0530190 if (applyTime == applyTimeImmediate)
191 {
192 return true;
193 }
194 }
Patrick Williams0dea1992022-07-22 19:26:52 -0500195 catch (const sdbusplus::exception_t& e)
Jayashankar Padath4d3d9122019-07-24 16:46:22 +0530196 {
197 log<level::ERR>("Error in getting ApplyTime",
198 entry("ERROR=%s", e.what()));
199 }
200 }
201 return false;
202}
203
204void Activation::rebootHost()
205{
206 auto service = utils::getService(bus, hostStateObjPath, hostStateIntf);
207 if (service.empty())
208 {
209 log<level::ALERT>("Error in getting the service name to reboot the "
210 "Host. The Host needs to be manually rebooted to "
211 "complete the image activation.");
212 }
213
214 auto method = bus.new_method_call(service.c_str(), hostStateObjPath,
215 dbusPropIntf, "Set");
Patrick Williams212102e2020-05-13 17:50:50 -0500216 std::variant<std::string> hostReboot = hostStateRebootVal;
Jayashankar Padath4d3d9122019-07-24 16:46:22 +0530217 method.append(hostStateIntf, hostStateRebootProp, hostReboot);
218
219 try
220 {
221 auto reply = bus.call(method);
222 }
Patrick Williams0dea1992022-07-22 19:26:52 -0500223 catch (const sdbusplus::exception_t& e)
Jayashankar Padath4d3d9122019-07-24 16:46:22 +0530224 {
225 log<level::ALERT>("Error in trying to reboot the Host. "
226 "The Host needs to be manually rebooted to complete "
227 "the image activation.",
228 entry("ERROR=%s", e.what()));
229 report<InternalFailure>();
230 }
231}
232
Saqib Khan2021b4c2017-06-07 14:37:36 -0500233uint8_t RedundancyPriority::priority(uint8_t value)
234{
Saqib Khanb8e7f312017-08-12 10:24:10 -0500235 parent.parent.freePriority(value, parent.versionId);
Saqib Khan2021b4c2017-06-07 14:37:36 -0500236 return softwareServer::RedundancyPriority::priority(value);
237}
238
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500239#ifdef WANT_SIGNATURE_VERIFY
Lei YU2b2d2292019-03-18 15:22:56 +0800240bool Activation::validateSignature(const std::string& pnorFileName)
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500241{
242 using Signature = openpower::software::image::Signature;
Brad Bishop9f44c992020-11-06 14:48:46 -0500243 std::filesystem::path imageDir(IMG_DIR);
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500244
Lei YU2b2d2292019-03-18 15:22:56 +0800245 Signature signature(imageDir / versionId, pnorFileName,
246 PNOR_SIGNED_IMAGE_CONF_PATH);
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500247
248 // Validate the signed image.
249 if (signature.verify())
250 {
251 return true;
252 }
253 // Log error and continue activation process, if field mode disabled.
254 log<level::ERR>("Error occurred during image validation");
255 report<InternalFailure>();
256
257 try
258 {
259 if (!fieldModeEnabled())
260 {
261 return true;
262 }
263 }
264 catch (const InternalFailure& e)
265 {
266 report<InternalFailure>();
267 }
268 return false;
269}
270
271bool Activation::fieldModeEnabled()
272{
Lei YUe4994462019-03-14 14:41:53 +0800273 auto fieldModeSvc =
274 utils::getService(bus, FIELDMODE_PATH, FIELDMODE_INTERFACE);
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500275
276 auto method = bus.new_method_call(fieldModeSvc.c_str(), FIELDMODE_PATH,
277 "org.freedesktop.DBus.Properties", "Get");
278
279 method.append(FIELDMODE_INTERFACE, "FieldModeEnabled");
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500280
Patrick Williams212102e2020-05-13 17:50:50 -0500281 std::variant<bool> fieldMode;
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500282
283 try
284 {
285 auto reply = bus.call(method);
286 reply.read(fieldMode);
Patrick Williams550f31b2020-05-13 11:15:24 -0500287 return std::get<bool>(fieldMode);
Adriana Kobylakb8cb0cc2019-05-31 09:58:04 -0500288 }
Patrick Williams0dea1992022-07-22 19:26:52 -0500289 catch (const sdbusplus::exception_t& e)
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500290 {
291 log<level::ERR>("Error in fieldModeEnabled getValue");
292 elog<InternalFailure>();
293 }
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500294}
295
Jayanth Othayoth11271fb2018-03-29 10:25:50 -0500296#endif
297
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500298} // namespace updater
299} // namespace software
300} // namespace openpower