blob: 3edfb0c018a3acf00a1a81af579bdcbb9cfef33d [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,
Saqib Khan81bac882017-06-08 12:17:01 -0500110 *this,
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500111 versionId,
112 extendedVersion,
113 activationState)));
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)));
Saqib Khan00044f42017-07-10 17:24:43 -0500122 }
Patrick Williams3accb322017-05-30 16:29:52 -0500123 return;
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500124}
125
Saqib Khan7254f0e2017-04-10 21:45:37 -0500126std::string ItemUpdater::getExtendedVersion(const std::string& manifestFilePath)
127{
128 constexpr auto extendedVersionKey = "extended_version=";
129 constexpr auto extendedVersionKeySize = strlen(extendedVersionKey);
130
131 if (manifestFilePath.empty())
132 {
133 log<level::ERR>("Error MANIFESTFilePath is empty");
134 throw std::runtime_error("MANIFESTFilePath is empty");
135 }
136
137 std::string extendedVersion{};
138 std::ifstream efile;
139 std::string line;
140 efile.exceptions(std::ifstream::failbit
141 | std::ifstream::badbit
142 | std::ifstream::eofbit);
143
144 try
145 {
146 efile.open(manifestFilePath);
147 while (getline(efile, line))
148 {
149 if (line.compare(0, extendedVersionKeySize,
150 extendedVersionKey) == 0)
151 {
152 extendedVersion = line.substr(extendedVersionKeySize);
153 break;
154 }
155 }
156 efile.close();
157 }
158 catch (const std::exception& e)
159 {
160 log<level::ERR>("Error in reading Host MANIFEST file");
161 }
Saqib Khan7254f0e2017-04-10 21:45:37 -0500162 return extendedVersion;
163}
164
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500165int ItemUpdater::validateSquashFSImage(const std::string& filePath)
Saqib Khana8ade7e2017-04-12 10:27:56 -0500166{
Adriana Kobylak5ba6b102017-05-19 09:41:27 -0500167 fs::path file(filePath);
168 file /= squashFSImage;
Saqib Khana8ade7e2017-04-12 10:27:56 -0500169 std::ifstream efile(file.c_str());
170
171 if (efile.good() == 1)
172 {
173 return 0;
174 }
175 else
176 {
177 log<level::ERR>("Failed to find the SquashFS image.");
178 return -1;
179 }
180}
181
Michael Tritzdd961b62017-05-17 14:07:03 -0500182void ItemUpdater::reset()
183{
184 for(const auto& it : activations)
185 {
186 auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + it.first +
187 ".service";
188
189 // Remove the read-write partitions.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500190 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500191 SYSTEMD_BUSNAME,
192 SYSTEMD_PATH,
193 SYSTEMD_INTERFACE,
194 "StartUnit");
195 method.append(serviceFile, "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500196 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500197 }
198
199 // Remove the preserved partition.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500200 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500201 SYSTEMD_BUSNAME,
202 SYSTEMD_PATH,
203 SYSTEMD_INTERFACE,
204 "StartUnit");
205 method.append("obmc-flash-bios-ubiumount-prsv.service", "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500206 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500207
208 return;
209}
210
Saqib Khan81bac882017-06-08 12:17:01 -0500211void ItemUpdater::freePriority(uint8_t value)
212{
213 //TODO openbmc/openbmc#1896 Improve the performance of this function
214 for (const auto& intf : activations)
215 {
216 if(intf.second->redundancyPriority)
217 {
218 if (intf.second->redundancyPriority.get()->priority() == value)
219 {
220 intf.second->redundancyPriority.get()->priority(value+1);
221 }
222 }
223 }
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