blob: 3fff1a41d567b0518ae1b0f5e11772e116e59f91 [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{
Patrick Williamse4290942017-06-16 05:43:08 -050027 using SVersion = server::Version;
28 using VersionPurpose = SVersion::VersionPurpose;
29 namespace msg = sdbusplus::message;
30 namespace variant_ns = msg::variant_ns;
31
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050032 sdbusplus::message::object_path objPath;
33 std::map<std::string,
Patrick Williamse4290942017-06-16 05:43:08 -050034 std::map<std::string, msg::variant<std::string>>> interfaces;
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050035 m.read(objPath, interfaces);
Patrick Williamse4290942017-06-16 05:43:08 -050036
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050037 std::string path(std::move(objPath));
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050038 std::string filePath;
Patrick Williamse4290942017-06-16 05:43:08 -050039 auto purpose = VersionPurpose::Unknown;
Saqib Khance148702017-06-11 12:01:58 -050040 std::string version;
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050041
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050042 for (const auto& intf : interfaces)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050043 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050044 if (intf.first == VERSION_IFACE)
45 {
46 for (const auto& property : intf.second)
47 {
48 if (property.first == "Purpose")
49 {
50 // Only process the Host and System images
Patrick Williamse4290942017-06-16 05:43:08 -050051 auto value = SVersion::convertVersionPurposeFromString(
52 variant_ns::get<std::string>(property.second));
53
54 if (value == VersionPurpose::Host ||
55 value == VersionPurpose::System)
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050056 {
Saqib Khance148702017-06-11 12:01:58 -050057 purpose = value;
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050058 }
59 }
Saqib Khance148702017-06-11 12:01:58 -050060 else if (property.first == "Version")
61 {
Patrick Williamse4290942017-06-16 05:43:08 -050062 version = variant_ns::get<std::string>(property.second);
Saqib Khance148702017-06-11 12:01:58 -050063 }
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050064 }
65 }
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050066 else if (intf.first == FILEPATH_IFACE)
67 {
68 for (const auto& property : intf.second)
69 {
70 if (property.first == "Path")
71 {
Patrick Williamse4290942017-06-16 05:43:08 -050072 filePath = variant_ns::get<std::string>(property.second);
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050073 }
74 }
75 }
76 }
Patrick Williamse4290942017-06-16 05:43:08 -050077 if ((filePath.empty()) || (purpose == VersionPurpose::Unknown))
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050078 {
79 return;
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050080 }
81
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050082 // Version id is the last item in the path
83 auto pos = path.rfind("/");
84 if (pos == std::string::npos)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050085 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050086 log<level::ERR>("No version id found in object path",
87 entry("OBJPATH=%s", path));
88 return;
89 }
90
91 auto versionId = path.substr(pos + 1);
92
93 if (activations.find(versionId) == activations.end())
94 {
95 // Determine the Activation state by processing the given image dir.
96 auto activationState = server::Activation::Activations::Invalid;
Adriana Kobylak5ba6b102017-05-19 09:41:27 -050097 if (ItemUpdater::validateSquashFSImage(filePath) == 0)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050098 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050099 activationState = server::Activation::Activations::Ready;
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -0500100 }
101
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500102 fs::path manifestPath(filePath);
103 manifestPath /= MANIFEST_FILE;
104 auto extendedVersion = ItemUpdater::getExtendedVersion(manifestPath);
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500105 activations.insert(std::make_pair(
106 versionId,
107 std::make_unique<Activation>(
108 bus,
109 path,
110 versionId,
111 extendedVersion,
112 activationState)));
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -0500113 }
Saqib Khance148702017-06-11 12:01:58 -0500114 versions.insert(std::make_pair(
115 versionId,
116 std::make_unique<Version>(
117 bus,
118 path,
119 version,
120 purpose,
121 filePath)));
Patrick Williams3accb322017-05-30 16:29:52 -0500122 return;
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500123}
124
Saqib Khan7254f0e2017-04-10 21:45:37 -0500125std::string ItemUpdater::getExtendedVersion(const std::string& manifestFilePath)
126{
127 constexpr auto extendedVersionKey = "extended_version=";
128 constexpr auto extendedVersionKeySize = strlen(extendedVersionKey);
129
130 if (manifestFilePath.empty())
131 {
132 log<level::ERR>("Error MANIFESTFilePath is empty");
133 throw std::runtime_error("MANIFESTFilePath is empty");
134 }
135
136 std::string extendedVersion{};
137 std::ifstream efile;
138 std::string line;
139 efile.exceptions(std::ifstream::failbit
140 | std::ifstream::badbit
141 | std::ifstream::eofbit);
142
143 try
144 {
145 efile.open(manifestFilePath);
146 while (getline(efile, line))
147 {
148 if (line.compare(0, extendedVersionKeySize,
149 extendedVersionKey) == 0)
150 {
151 extendedVersion = line.substr(extendedVersionKeySize);
152 break;
153 }
154 }
155 efile.close();
156 }
157 catch (const std::exception& e)
158 {
159 log<level::ERR>("Error in reading Host MANIFEST file");
160 }
Saqib Khan7254f0e2017-04-10 21:45:37 -0500161 return extendedVersion;
162}
163
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500164int ItemUpdater::validateSquashFSImage(const std::string& filePath)
Saqib Khana8ade7e2017-04-12 10:27:56 -0500165{
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500166 fs::path file(filePath);
167 file /= squashFSImage;
Saqib Khana8ade7e2017-04-12 10:27:56 -0500168 std::ifstream efile(file.c_str());
169
170 if (efile.good() == 1)
171 {
172 return 0;
173 }
174 else
175 {
176 log<level::ERR>("Failed to find the SquashFS image.");
177 return -1;
178 }
179}
180
Michael Tritzdd961b62017-05-17 14:07:03 -0500181void ItemUpdater::reset()
182{
183 for(const auto& it : activations)
184 {
185 auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + it.first +
186 ".service";
187
188 // Remove the read-write partitions.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500189 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500190 SYSTEMD_BUSNAME,
191 SYSTEMD_PATH,
192 SYSTEMD_INTERFACE,
193 "StartUnit");
194 method.append(serviceFile, "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500195 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500196 }
197
198 // Remove the preserved partition.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500199 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500200 SYSTEMD_BUSNAME,
201 SYSTEMD_PATH,
202 SYSTEMD_INTERFACE,
203 "StartUnit");
204 method.append("obmc-flash-bios-ubiumount-prsv.service", "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500205 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500206
207 return;
208}
209
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500210} // namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500211} // namespace software
212} // namespace openpower