blob: 9c26b9dfa2dfc9b560ad63be0d590390f713bcff [file] [log] [blame]
Saqib Khan7254f0e2017-04-10 21:45:37 -05001#include <string>
2#include <fstream>
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -05003#include <phosphor-logging/log.hpp>
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05004#include "config.h"
5#include "item_updater.hpp"
Saqib Khana8ade7e2017-04-12 10:27:56 -05006#include "activation.hpp"
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05007
8namespace openpower
9{
10namespace software
11{
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050012namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050013{
14
Saqib Khana8ade7e2017-04-12 10:27:56 -050015// When you see server:: you know we're referencing our base class
16namespace server = sdbusplus::xyz::openbmc_project::Software::server;
17
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050018using namespace phosphor::logging;
19
Saqib Khana8ade7e2017-04-12 10:27:56 -050020constexpr auto squashFSImage = "pnor.xz.squashfs";
21
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050022int ItemUpdater::createActivation(sd_bus_message* msg,
23 void* userData,
24 sd_bus_error* retErr)
25{
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050026 auto* updater = static_cast<ItemUpdater*>(userData);
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050027 auto mapper = updater->busItem.new_method_call(
28 MAPPER_BUSNAME,
29 MAPPER_PATH,
30 MAPPER_INTERFACE,
31 "GetSubTreePaths");
32 mapper.append(SOFTWARE_OBJPATH,
33 1, // Depth
34 std::vector<std::string>({VERSION_IFACE}));
35
36 auto mapperResponseMsg = updater->busItem.call(mapper);
37 if (mapperResponseMsg.is_method_error())
38 {
39 log<level::ERR>("Error in mapper call",
40 entry("PATH=%s", SOFTWARE_OBJPATH),
41 entry("INTERFACE=%s", VERSION_IFACE));
42 return -1;
43 }
44
45 std::vector<std::string> mapperResponse;
46 mapperResponseMsg.read(mapperResponse);
47 if (mapperResponse.empty())
48 {
49 log<level::ERR>("Error reading mapper response",
50 entry("PATH=%s", SOFTWARE_OBJPATH),
51 entry("INTERFACE=%s", VERSION_IFACE));
52 return -1;
53 }
54
Saqib Khan7254f0e2017-04-10 21:45:37 -050055 auto extendedVersion = ItemUpdater::getExtendedVersion(MANIFEST_FILE);
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050056 for (const auto& resp : mapperResponse)
57 {
58 // Version id is the last item in the path
59 auto pos = resp.rfind("/");
60 if (pos == std::string::npos)
61 {
62 log<level::ERR>("No version id found in object path",
63 entry("OBJPATH=%s", resp));
64 return -1;
65 }
66
Adriana Kobylak268616b2017-04-05 15:23:30 -050067 auto versionId = resp.substr(pos + 1);
Saqib Khana8ade7e2017-04-12 10:27:56 -050068
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050069 if (updater->activations.find(versionId) == updater->activations.end())
70 {
Adriana Kobylak2fdb9312017-05-14 19:08:26 -050071 // Determine the Activation state by processing the given image dir.
72 auto activationState = server::Activation::Activations::Invalid;
73 if (ItemUpdater::validateSquashFSImage(versionId) == 0)
74 {
75 activationState = server::Activation::Activations::Ready;
76
77 // Load the squashfs image to pnor so that it is available to be
78 // activated when requested.
79 // This is done since the image on the BMC can be removed.
80 constexpr auto squashfsMountService =
81 "obmc-flash-bios-squashfsmount@";
82 auto squashfsMountServiceFile =
83 std::string(squashfsMountService) +
84 versionId +
85 ".service";
86 auto method = updater->busItem.new_method_call(
87 SYSTEMD_BUSNAME,
88 SYSTEMD_PATH,
89 SYSTEMD_INTERFACE,
90 "StartUnit");
91 method.append(squashfsMountServiceFile, "replace");
92 updater->busItem.call_noreply(method);
93 }
94
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050095 updater->activations.insert(std::make_pair(
96 versionId,
97 std::make_unique<Activation>(
98 updater->busItem,
Adriana Kobylakbc37a4c2017-04-10 09:45:36 -050099 resp,
Saqib Khan7254f0e2017-04-10 21:45:37 -0500100 versionId,
Saqib Khana8ade7e2017-04-12 10:27:56 -0500101 extendedVersion,
102 activationState)));
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -0500103 }
104 }
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500105 return 0;
106}
107
Saqib Khan7254f0e2017-04-10 21:45:37 -0500108std::string ItemUpdater::getExtendedVersion(const std::string& manifestFilePath)
109{
110 constexpr auto extendedVersionKey = "extended_version=";
111 constexpr auto extendedVersionKeySize = strlen(extendedVersionKey);
112
113 if (manifestFilePath.empty())
114 {
115 log<level::ERR>("Error MANIFESTFilePath is empty");
116 throw std::runtime_error("MANIFESTFilePath is empty");
117 }
118
119 std::string extendedVersion{};
120 std::ifstream efile;
121 std::string line;
122 efile.exceptions(std::ifstream::failbit
123 | std::ifstream::badbit
124 | std::ifstream::eofbit);
125
126 try
127 {
128 efile.open(manifestFilePath);
129 while (getline(efile, line))
130 {
131 if (line.compare(0, extendedVersionKeySize,
132 extendedVersionKey) == 0)
133 {
134 extendedVersion = line.substr(extendedVersionKeySize);
135 break;
136 }
137 }
138 efile.close();
139 }
140 catch (const std::exception& e)
141 {
142 log<level::ERR>("Error in reading Host MANIFEST file");
143 }
Saqib Khan7254f0e2017-04-10 21:45:37 -0500144 return extendedVersion;
145}
146
Saqib Khana8ade7e2017-04-12 10:27:56 -0500147int ItemUpdater::validateSquashFSImage(const std::string& versionId)
148{
149 auto file = IMAGE_DIR + versionId + "/" +
150 std::string(squashFSImage);
151 std::ifstream efile(file.c_str());
152
153 if (efile.good() == 1)
154 {
155 return 0;
156 }
157 else
158 {
159 log<level::ERR>("Failed to find the SquashFS image.");
160 return -1;
161 }
162}
163
Michael Tritzdd961b62017-05-17 14:07:03 -0500164void ItemUpdater::reset()
165{
166 for(const auto& it : activations)
167 {
168 auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + it.first +
169 ".service";
170
171 // Remove the read-write partitions.
172 auto method = busItem.new_method_call(
173 SYSTEMD_BUSNAME,
174 SYSTEMD_PATH,
175 SYSTEMD_INTERFACE,
176 "StartUnit");
177 method.append(serviceFile, "replace");
178 busItem.call_noreply(method);
179 }
180
181 // Remove the preserved partition.
182 auto method = busItem.new_method_call(
183 SYSTEMD_BUSNAME,
184 SYSTEMD_PATH,
185 SYSTEMD_INTERFACE,
186 "StartUnit");
187 method.append("obmc-flash-bios-ubiumount-prsv.service", "replace");
188 busItem.call_noreply(method);
189
190 return;
191}
192
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500193} // namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500194} // namespace software
195} // namespace openpower