blob: 80568fe77c3525418d1fc7d6cefee6ca146b663b [file] [log] [blame]
Saqib Khan35e83f32017-05-22 11:37:32 -05001#include <fstream>
Gunnar Millsec1b41c2017-05-02 12:20:36 -05002#include <string>
Gunnar Mills2ce7da22017-05-04 15:37:56 -05003#include <phosphor-logging/log.hpp>
Gunnar Millsec1b41c2017-05-02 12:20:36 -05004#include "config.h"
Gunnar Mills2ce7da22017-05-04 15:37:56 -05005#include "item_updater.hpp"
6#include "xyz/openbmc_project/Software/Version/server.hpp"
Saqib Khan35e83f32017-05-22 11:37:32 -05007#include <experimental/filesystem>
Saqib Khan705f1bf2017-06-09 23:58:38 -05008#include "version.hpp"
Gunnar Millsec1b41c2017-05-02 12:20:36 -05009
10namespace phosphor
11{
12namespace software
13{
14namespace updater
15{
16
Gunnar Mills2ce7da22017-05-04 15:37:56 -050017// When you see server:: you know we're referencing our base class
18namespace server = sdbusplus::xyz::openbmc_project::Software::server;
19
20using namespace phosphor::logging;
Saqib Khan35e83f32017-05-22 11:37:32 -050021namespace fs = std::experimental::filesystem;
22
23constexpr auto bmcImage = "image-rofs";
Gunnar Mills2ce7da22017-05-04 15:37:56 -050024
Patrick Williamse75d10f2017-05-30 16:56:32 -050025void ItemUpdater::createActivation(sdbusplus::message::message& msg)
Gunnar Millsec1b41c2017-05-02 12:20:36 -050026{
Saqib Khan84a0e692017-06-28 17:27:01 -050027
28 using SVersion = server::Version;
29 using VersionPurpose = SVersion::VersionPurpose;
30 namespace mesg = sdbusplus::message;
31 namespace variant_ns = mesg::variant_ns;
32
33 mesg::object_path objPath;
34 auto purpose = VersionPurpose::Unknown;
Saqib Khan705f1bf2017-06-09 23:58:38 -050035 std::string version;
Gunnar Mills2ce7da22017-05-04 15:37:56 -050036 std::map<std::string,
Patrick Williamse75d10f2017-05-30 16:56:32 -050037 std::map<std::string,
Saqib Khan84a0e692017-06-28 17:27:01 -050038 mesg::variant<std::string>>> interfaces;
Patrick Williamse75d10f2017-05-30 16:56:32 -050039 msg.read(objPath, interfaces);
Gunnar Mills2ce7da22017-05-04 15:37:56 -050040 std::string path(std::move(objPath));
Saqib Khan19177d32017-06-20 08:11:49 -050041 std::string filePath;
Gunnar Mills2ce7da22017-05-04 15:37:56 -050042
43 for (const auto& intf : interfaces)
44 {
Saqib Khan705f1bf2017-06-09 23:58:38 -050045 if (intf.first == VERSION_IFACE)
Gunnar Mills2ce7da22017-05-04 15:37:56 -050046 {
Saqib Khan705f1bf2017-06-09 23:58:38 -050047 for (const auto& property : intf.second)
Gunnar Mills2ce7da22017-05-04 15:37:56 -050048 {
Saqib Khan705f1bf2017-06-09 23:58:38 -050049 if (property.first == "Purpose")
Gunnar Mills2ce7da22017-05-04 15:37:56 -050050 {
Saqib Khan84a0e692017-06-28 17:27:01 -050051 auto value = SVersion::convertVersionPurposeFromString(
52 variant_ns::get<std::string>(property.second));
53 if (value == VersionPurpose::BMC ||
54 value == VersionPurpose::System)
55 {
56 purpose = value;
57 }
Saqib Khan705f1bf2017-06-09 23:58:38 -050058 }
59 else if (property.first == "Version")
60 {
Saqib Khan84a0e692017-06-28 17:27:01 -050061 version = variant_ns::get<std::string>(property.second);
Gunnar Mills2ce7da22017-05-04 15:37:56 -050062 }
63 }
64 }
Saqib Khan19177d32017-06-20 08:11:49 -050065 else if (intf.first == FILEPATH_IFACE)
66 {
67 for (const auto& property : intf.second)
68 {
69 if (property.first == "Path")
70 {
Saqib Khan84a0e692017-06-28 17:27:01 -050071 filePath = variant_ns::get<std::string>(property.second);
Saqib Khan19177d32017-06-20 08:11:49 -050072 }
73 }
74 }
Gunnar Mills2ce7da22017-05-04 15:37:56 -050075 }
Saqib Khan705f1bf2017-06-09 23:58:38 -050076 if (version.empty() ||
Saqib Khan19177d32017-06-20 08:11:49 -050077 filePath.empty() ||
Saqib Khan84a0e692017-06-28 17:27:01 -050078 purpose == VersionPurpose::Unknown)
Saqib Khan705f1bf2017-06-09 23:58:38 -050079 {
80 return;
81 }
Gunnar Mills2ce7da22017-05-04 15:37:56 -050082
83 // Version id is the last item in the path
84 auto pos = path.rfind("/");
85 if (pos == std::string::npos)
86 {
87 log<level::ERR>("No version id found in object path",
88 entry("OBJPATH=%s", path));
Patrick Williamse75d10f2017-05-30 16:56:32 -050089 return;
Gunnar Mills2ce7da22017-05-04 15:37:56 -050090 }
91
92 auto versionId = path.substr(pos + 1);
93
Patrick Williamse75d10f2017-05-30 16:56:32 -050094 if (activations.find(versionId) == activations.end())
Gunnar Mills2ce7da22017-05-04 15:37:56 -050095 {
Saqib Khan35e83f32017-05-22 11:37:32 -050096 // Determine the Activation state by processing the given image dir.
97 auto activationState = server::Activation::Activations::Invalid;
98 ItemUpdater::ActivationStatus result = ItemUpdater::
Saqib Khan19177d32017-06-20 08:11:49 -050099 validateSquashFSImage(filePath);
Saqib Khan35e83f32017-05-22 11:37:32 -0500100 if (result == ItemUpdater::ActivationStatus::ready)
101 {
102 activationState = server::Activation::Activations::Ready;
103 }
Saqib Khan35e83f32017-05-22 11:37:32 -0500104 activations.insert(std::make_pair(
Saqib Khan705f1bf2017-06-09 23:58:38 -0500105 versionId,
106 std::make_unique<Activation>(
107 bus,
108 path,
Saqib Khan4c1aec02017-07-06 11:46:13 -0500109 *this,
Saqib Khan35e83f32017-05-22 11:37:32 -0500110 versionId,
Saqib Khan705f1bf2017-06-09 23:58:38 -0500111 activationState)));
112 versions.insert(std::make_pair(
113 versionId,
114 std::make_unique<phosphor::software::
115 manager::Version>(
116 bus,
117 path,
118 version,
119 purpose,
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500120 filePath,
121 std::bind(&ItemUpdater::erase,
122 this,
123 std::placeholders::_1))));
Gunnar Mills2ce7da22017-05-04 15:37:56 -0500124 }
Saqib Khan7b5010f2017-08-09 10:03:11 -0500125 else
126 {
127 log<level::INFO>("Software Object with the same version already exists",
128 entry("VERSION_ID=%s", versionId));
129 }
Patrick Williamse75d10f2017-05-30 16:56:32 -0500130 return;
Gunnar Millsec1b41c2017-05-02 12:20:36 -0500131}
132
Saqib Khanba239882017-05-26 08:41:54 -0500133void ItemUpdater::processBMCImage()
134{
135 auto purpose = server::Version::VersionPurpose::BMC;
136 auto version = phosphor::software::manager::Version::getBMCVersion();
137 auto id = phosphor::software::manager::Version::getId(version);
138 auto path = std::string{SOFTWARE_OBJPATH} + '/' + id;
139 activations.insert(std::make_pair(
140 id,
141 std::make_unique<Activation>(
142 bus,
143 path,
Saqib Khan4c1aec02017-07-06 11:46:13 -0500144 *this,
Saqib Khanba239882017-05-26 08:41:54 -0500145 id,
146 server::Activation::Activations::Active)));
147 versions.insert(std::make_pair(
148 id,
149 std::make_unique<phosphor::software::
150 manager::Version>(
151 bus,
152 path,
153 version,
154 purpose,
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500155 "",
156 std::bind(&ItemUpdater::erase,
157 this,
158 std::placeholders::_1))));
159
Saqib Khanba239882017-05-26 08:41:54 -0500160 return;
161}
162
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500163void ItemUpdater::erase(std::string entryId)
164{
165 // Delete ReadWrite and ReadOnly partitions
166 removeReadWritePartition(entryId);
167 removeReadOnlyPartition(entryId);
168
169 // Removing entry in versions map
170 auto it = versions.find(entryId);
171 if (it == versions.end())
172 {
173 log<level::ERR>(("Error: Failed to find version " + entryId + \
174 " in item updater versions map." \
175 " Unable to remove.").c_str());
176 return;
177 }
178 this->versions.erase(entryId);
179
180 // Removing entry in activations map
181 auto ita = activations.find(entryId);
182 if (ita == activations.end())
183 {
184 log<level::ERR>(("Error: Failed to find version " + entryId + \
185 " in item updater activations map." \
186 " Unable to remove.").c_str());
187 return;
188 }
189 // TODO: openbmc/openbmc#1986
190 // Test if this is the currently running image
191 // If not, don't continue.
192
193 this->activations.erase(entryId);
194}
195
Saqib Khan35e83f32017-05-22 11:37:32 -0500196ItemUpdater::ActivationStatus ItemUpdater::validateSquashFSImage(
Saqib Khan19177d32017-06-20 08:11:49 -0500197 const std::string& filePath)
Saqib Khan35e83f32017-05-22 11:37:32 -0500198{
199
Saqib Khan19177d32017-06-20 08:11:49 -0500200 fs::path file(filePath);
Saqib Khan35e83f32017-05-22 11:37:32 -0500201 file /= bmcImage;
202 std::ifstream efile(file.c_str());
203
204 if (efile.good() == 1)
205 {
206 return ItemUpdater::ActivationStatus::ready;
207 }
208 else
209 {
Saqib Khan19177d32017-06-20 08:11:49 -0500210 log<level::ERR>("Failed to find the BMC image.");
Saqib Khan35e83f32017-05-22 11:37:32 -0500211 return ItemUpdater::ActivationStatus::invalid;
212 }
213}
214
Saqib Khan4c1aec02017-07-06 11:46:13 -0500215void ItemUpdater::freePriority(uint8_t value)
216{
217 //TODO openbmc/openbmc#1896 Improve the performance of this function
218 for (const auto& intf : activations)
219 {
220 if(intf.second->redundancyPriority)
221 {
222 if (intf.second->redundancyPriority.get()->priority() == value)
223 {
224 intf.second->redundancyPriority.get()->priority(value+1);
225 }
226 }
227 }
228}
229
Michael Tritz37a59042017-07-12 13:44:53 -0500230void ItemUpdater::reset()
231{
232 // Mark the read-write partition for recreation upon reboot.
233 auto method = bus.new_method_call(
234 SYSTEMD_BUSNAME,
235 SYSTEMD_PATH,
236 SYSTEMD_INTERFACE,
237 "StartUnit");
238 method.append("obmc-flash-bmc-setenv@rwreset=true.service", "replace");
239 bus.call_noreply(method);
240
241 log<level::INFO>("BMC factory reset will take effect upon reboot.");
242
243 return;
244}
245
Leonel Gonzalez3526ef72017-07-07 14:38:25 -0500246void ItemUpdater::removeReadOnlyPartition(std::string versionId)
247{
248 auto serviceFile = "obmc-flash-bmc-ubiro-remove@" + versionId +
249 ".service";
250
251 // Remove the read-only partitions.
252 auto method = bus.new_method_call(
253 SYSTEMD_BUSNAME,
254 SYSTEMD_PATH,
255 SYSTEMD_INTERFACE,
256 "StartUnit");
257 method.append(serviceFile, "replace");
258 bus.call_noreply(method);
259}
260
261void ItemUpdater::removeReadWritePartition(std::string versionId)
262{
263 auto serviceFile = "obmc-flash-bmc-ubirw-remove.service";
264
265 // Remove the read-write partitions.
266 auto method = bus.new_method_call(
267 SYSTEMD_BUSNAME,
268 SYSTEMD_PATH,
269 SYSTEMD_INTERFACE,
270 "StartUnit");
271 method.append(serviceFile, "replace");
272 bus.call_noreply(method);
273}
274
Gunnar Millsec1b41c2017-05-02 12:20:36 -0500275} // namespace updater
276} // namespace software
277} // namespace phosphor