blob: 3f72aebe5b0e3e4f8a0cf2674d7b5fa46301060e [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
69 // Determine the Activation state by processing the given image dir.
70 auto activationState = server::Activation::Activations::Invalid;
71 if (ItemUpdater::validateSquashFSImage(versionId) == 0)
72 {
73 activationState = server::Activation::Activations::Ready;
74 }
75
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050076 if (updater->activations.find(versionId) == updater->activations.end())
77 {
78 updater->activations.insert(std::make_pair(
79 versionId,
80 std::make_unique<Activation>(
81 updater->busItem,
Adriana Kobylakbc37a4c2017-04-10 09:45:36 -050082 resp,
Saqib Khan7254f0e2017-04-10 21:45:37 -050083 versionId,
Saqib Khana8ade7e2017-04-12 10:27:56 -050084 extendedVersion,
85 activationState)));
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050086 }
87 }
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050088 return 0;
89}
90
Saqib Khan7254f0e2017-04-10 21:45:37 -050091std::string ItemUpdater::getExtendedVersion(const std::string& manifestFilePath)
92{
93 constexpr auto extendedVersionKey = "extended_version=";
94 constexpr auto extendedVersionKeySize = strlen(extendedVersionKey);
95
96 if (manifestFilePath.empty())
97 {
98 log<level::ERR>("Error MANIFESTFilePath is empty");
99 throw std::runtime_error("MANIFESTFilePath is empty");
100 }
101
102 std::string extendedVersion{};
103 std::ifstream efile;
104 std::string line;
105 efile.exceptions(std::ifstream::failbit
106 | std::ifstream::badbit
107 | std::ifstream::eofbit);
108
109 try
110 {
111 efile.open(manifestFilePath);
112 while (getline(efile, line))
113 {
114 if (line.compare(0, extendedVersionKeySize,
115 extendedVersionKey) == 0)
116 {
117 extendedVersion = line.substr(extendedVersionKeySize);
118 break;
119 }
120 }
121 efile.close();
122 }
123 catch (const std::exception& e)
124 {
125 log<level::ERR>("Error in reading Host MANIFEST file");
126 }
Saqib Khan7254f0e2017-04-10 21:45:37 -0500127 return extendedVersion;
128}
129
Saqib Khana8ade7e2017-04-12 10:27:56 -0500130int ItemUpdater::validateSquashFSImage(const std::string& versionId)
131{
132 auto file = IMAGE_DIR + versionId + "/" +
133 std::string(squashFSImage);
134 std::ifstream efile(file.c_str());
135
136 if (efile.good() == 1)
137 {
138 return 0;
139 }
140 else
141 {
142 log<level::ERR>("Failed to find the SquashFS image.");
143 return -1;
144 }
145}
146
Michael Tritzdd961b62017-05-17 14:07:03 -0500147void ItemUpdater::reset()
148{
149 for(const auto& it : activations)
150 {
151 auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + it.first +
152 ".service";
153
154 // Remove the read-write partitions.
155 auto method = busItem.new_method_call(
156 SYSTEMD_BUSNAME,
157 SYSTEMD_PATH,
158 SYSTEMD_INTERFACE,
159 "StartUnit");
160 method.append(serviceFile, "replace");
161 busItem.call_noreply(method);
162 }
163
164 // Remove the preserved partition.
165 auto method = busItem.new_method_call(
166 SYSTEMD_BUSNAME,
167 SYSTEMD_PATH,
168 SYSTEMD_INTERFACE,
169 "StartUnit");
170 method.append("obmc-flash-bios-ubiumount-prsv.service", "replace");
171 busItem.call_noreply(method);
172
173 return;
174}
175
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500176} // namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500177} // namespace software
178} // namespace openpower