blob: 41e4196dff352dd3da37786473b5407e597fd9c8 [file] [log] [blame]
Saqib Khan7254f0e2017-04-10 21:45:37 -05001#include <string>
Adriana Kobylak5ba6b102017-05-19 09:41:27 -05002#include <experimental/filesystem>
Saqib Khan7254f0e2017-04-10 21:45:37 -05003#include <fstream>
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -05004#include <phosphor-logging/log.hpp>
Adriana Kobylakd6a549e2017-05-10 16:23:01 -05005#include <xyz/openbmc_project/Software/Version/server.hpp>
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05006#include "config.h"
7#include "item_updater.hpp"
Saqib Khana8ade7e2017-04-12 10:27:56 -05008#include "activation.hpp"
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05009
10namespace openpower
11{
12namespace software
13{
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050014namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050015{
16
Saqib Khana8ade7e2017-04-12 10:27:56 -050017// When you see server:: you know we're referencing our base class
18namespace server = sdbusplus::xyz::openbmc_project::Software::server;
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050019namespace fs = std::experimental::filesystem;
Saqib Khana8ade7e2017-04-12 10:27:56 -050020
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050021using namespace phosphor::logging;
22
Saqib Khana8ade7e2017-04-12 10:27:56 -050023constexpr auto squashFSImage = "pnor.xz.squashfs";
24
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050025void ItemUpdater::createActivation(sdbusplus::message::message& m)
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050026{
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050027 sdbusplus::message::object_path objPath;
28 std::map<std::string,
29 std::map<std::string,
30 sdbusplus::message::variant<std::string>>> interfaces;
31 m.read(objPath, interfaces);
32 std::string path(std::move(objPath));
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050033 std::string filePath;
Saqib Khance148702017-06-11 12:01:58 -050034 auto purpose = server::Version::VersionPurpose::Unknown;
35 std::string version;
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050036
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050037 for (const auto& intf : interfaces)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050038 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050039 if (intf.first == VERSION_IFACE)
40 {
41 for (const auto& property : intf.second)
42 {
43 if (property.first == "Purpose")
44 {
45 // Only process the Host and System images
Saqib Khance148702017-06-11 12:01:58 -050046 std::string str = sdbusplus::message::variant_ns::get<
47 std::string>(property.second);
48 auto value = server::Version::
49 convertVersionPurposeFromString(str);
50 if (value == server::Version::VersionPurpose::Host ||
51 value == server::Version::VersionPurpose::System)
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050052 {
Saqib Khance148702017-06-11 12:01:58 -050053 purpose = value;
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050054 }
55 }
Saqib Khance148702017-06-11 12:01:58 -050056 else if (property.first == "Version")
57 {
58 version = sdbusplus::message::variant_ns::
59 get<std::string>(property.second);
60 }
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050061 }
62 }
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050063 else if (intf.first == FILEPATH_IFACE)
64 {
65 for (const auto& property : intf.second)
66 {
67 if (property.first == "Path")
68 {
69 filePath = sdbusplus::message::variant_ns::get<
70 std::string>(property.second);
71 }
72 }
73 }
74 }
Saqib Khance148702017-06-11 12:01:58 -050075 if ((filePath.empty()) || (purpose == server::Version::
76 VersionPurpose::Unknown))
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050077 {
78 return;
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050079 }
80
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050081 // Version id is the last item in the path
82 auto pos = path.rfind("/");
83 if (pos == std::string::npos)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050084 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050085 log<level::ERR>("No version id found in object path",
86 entry("OBJPATH=%s", path));
87 return;
88 }
89
90 auto versionId = path.substr(pos + 1);
91
92 if (activations.find(versionId) == activations.end())
93 {
94 // Determine the Activation state by processing the given image dir.
95 auto activationState = server::Activation::Activations::Invalid;
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050096 if (ItemUpdater::validateSquashFSImage(filePath) == 0)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050097 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050098 activationState = server::Activation::Activations::Ready;
99
100 // Load the squashfs image to pnor so that it is available to be
101 // activated when requested.
102 // This is done since the image on the BMC can be removed.
103 constexpr auto squashfsMountService =
104 "obmc-flash-bios-squashfsmount@";
105 auto squashfsMountServiceFile =
106 std::string(squashfsMountService) +
107 versionId +
108 ".service";
109 auto method = bus.new_method_call(
110 SYSTEMD_BUSNAME,
111 SYSTEMD_PATH,
112 SYSTEMD_INTERFACE,
113 "StartUnit");
114 method.append(squashfsMountServiceFile, "replace");
115 bus.call_noreply(method);
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -0500116 }
117
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500118 fs::path manifestPath(filePath);
119 manifestPath /= MANIFEST_FILE;
120 auto extendedVersion = ItemUpdater::getExtendedVersion(manifestPath);
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500121 activations.insert(std::make_pair(
122 versionId,
123 std::make_unique<Activation>(
124 bus,
125 path,
126 versionId,
127 extendedVersion,
128 activationState)));
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -0500129 }
Saqib Khance148702017-06-11 12:01:58 -0500130 versions.insert(std::make_pair(
131 versionId,
132 std::make_unique<Version>(
133 bus,
134 path,
135 version,
136 purpose,
137 filePath)));
Patrick Williams3accb322017-05-30 16:29:52 -0500138 return;
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500139}
140
Saqib Khan7254f0e2017-04-10 21:45:37 -0500141std::string ItemUpdater::getExtendedVersion(const std::string& manifestFilePath)
142{
143 constexpr auto extendedVersionKey = "extended_version=";
144 constexpr auto extendedVersionKeySize = strlen(extendedVersionKey);
145
146 if (manifestFilePath.empty())
147 {
148 log<level::ERR>("Error MANIFESTFilePath is empty");
149 throw std::runtime_error("MANIFESTFilePath is empty");
150 }
151
152 std::string extendedVersion{};
153 std::ifstream efile;
154 std::string line;
155 efile.exceptions(std::ifstream::failbit
156 | std::ifstream::badbit
157 | std::ifstream::eofbit);
158
159 try
160 {
161 efile.open(manifestFilePath);
162 while (getline(efile, line))
163 {
164 if (line.compare(0, extendedVersionKeySize,
165 extendedVersionKey) == 0)
166 {
167 extendedVersion = line.substr(extendedVersionKeySize);
168 break;
169 }
170 }
171 efile.close();
172 }
173 catch (const std::exception& e)
174 {
175 log<level::ERR>("Error in reading Host MANIFEST file");
176 }
Saqib Khan7254f0e2017-04-10 21:45:37 -0500177 return extendedVersion;
178}
179
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500180int ItemUpdater::validateSquashFSImage(const std::string& filePath)
Saqib Khana8ade7e2017-04-12 10:27:56 -0500181{
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500182 fs::path file(filePath);
183 file /= squashFSImage;
Saqib Khana8ade7e2017-04-12 10:27:56 -0500184 std::ifstream efile(file.c_str());
185
186 if (efile.good() == 1)
187 {
188 return 0;
189 }
190 else
191 {
192 log<level::ERR>("Failed to find the SquashFS image.");
193 return -1;
194 }
195}
196
Michael Tritzdd961b62017-05-17 14:07:03 -0500197void ItemUpdater::reset()
198{
199 for(const auto& it : activations)
200 {
201 auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + it.first +
202 ".service";
203
204 // Remove the read-write partitions.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500205 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500206 SYSTEMD_BUSNAME,
207 SYSTEMD_PATH,
208 SYSTEMD_INTERFACE,
209 "StartUnit");
210 method.append(serviceFile, "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500211 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500212 }
213
214 // Remove the preserved partition.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500215 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500216 SYSTEMD_BUSNAME,
217 SYSTEMD_PATH,
218 SYSTEMD_INTERFACE,
219 "StartUnit");
220 method.append("obmc-flash-bios-ubiumount-prsv.service", "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500221 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500222
223 return;
224}
225
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500226} // namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500227} // namespace software
228} // namespace openpower