blob: a8809e6108d564bea284d4bbd0e0b9ee5f25801b [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 Kobylakd6a549e2017-05-10 16:23:01 -05004#include <xyz/openbmc_project/Software/Version/server.hpp>
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05005#include "config.h"
6#include "item_updater.hpp"
Saqib Khana8ade7e2017-04-12 10:27:56 -05007#include "activation.hpp"
Adriana Kobylak2d8fa222017-03-15 12:34:32 -05008
9namespace openpower
10{
11namespace software
12{
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -050013namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050014{
15
Saqib Khana8ade7e2017-04-12 10:27:56 -050016// When you see server:: you know we're referencing our base class
17namespace server = sdbusplus::xyz::openbmc_project::Software::server;
18
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050019using namespace phosphor::logging;
20
Saqib Khana8ade7e2017-04-12 10:27:56 -050021constexpr auto squashFSImage = "pnor.xz.squashfs";
22
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050023void ItemUpdater::createActivation(sdbusplus::message::message& m)
Adriana Kobylak2d8fa222017-03-15 12:34:32 -050024{
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050025 sdbusplus::message::object_path objPath;
26 std::map<std::string,
27 std::map<std::string,
28 sdbusplus::message::variant<std::string>>> interfaces;
29 m.read(objPath, interfaces);
30 std::string path(std::move(objPath));
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050031
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050032 for (const auto& intf : interfaces)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050033 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050034 if (intf.first == VERSION_IFACE)
35 {
36 for (const auto& property : intf.second)
37 {
38 if (property.first == "Purpose")
39 {
40 // Only process the Host and System images
41 std::string value = sdbusplus::message::variant_ns::get<
42 std::string>(property.second);
43 if ((value != convertForMessage(
44 server::Version::VersionPurpose::Host)) &&
45 (value != convertForMessage(
46 server::Version::VersionPurpose::System)))
47 {
48 return;
49 }
50 }
51 }
52 }
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050053 }
54
Saqib Khan7254f0e2017-04-10 21:45:37 -050055 auto extendedVersion = ItemUpdater::getExtendedVersion(MANIFEST_FILE);
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050056 // Version id is the last item in the path
57 auto pos = path.rfind("/");
58 if (pos == std::string::npos)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050059 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050060 log<level::ERR>("No version id found in object path",
61 entry("OBJPATH=%s", path));
62 return;
63 }
64
65 auto versionId = path.substr(pos + 1);
66
67 if (activations.find(versionId) == activations.end())
68 {
69 // Determine the Activation state by processing the given image dir.
70 auto activationState = server::Activation::Activations::Invalid;
71 if (ItemUpdater::validateSquashFSImage(versionId) == 0)
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050072 {
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050073 activationState = server::Activation::Activations::Ready;
74
75 // Load the squashfs image to pnor so that it is available to be
76 // activated when requested.
77 // This is done since the image on the BMC can be removed.
78 constexpr auto squashfsMountService =
79 "obmc-flash-bios-squashfsmount@";
80 auto squashfsMountServiceFile =
81 std::string(squashfsMountService) +
82 versionId +
83 ".service";
84 auto method = bus.new_method_call(
85 SYSTEMD_BUSNAME,
86 SYSTEMD_PATH,
87 SYSTEMD_INTERFACE,
88 "StartUnit");
89 method.append(squashfsMountServiceFile, "replace");
90 bus.call_noreply(method);
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -050091 }
92
Adriana Kobylakd6a549e2017-05-10 16:23:01 -050093 activations.insert(std::make_pair(
94 versionId,
95 std::make_unique<Activation>(
96 bus,
97 path,
98 versionId,
99 extendedVersion,
100 activationState)));
Adriana Kobylakb66ac3a2017-03-28 13:33:20 -0500101 }
Patrick Williams3accb322017-05-30 16:29:52 -0500102 return;
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500103}
104
Saqib Khan7254f0e2017-04-10 21:45:37 -0500105std::string ItemUpdater::getExtendedVersion(const std::string& manifestFilePath)
106{
107 constexpr auto extendedVersionKey = "extended_version=";
108 constexpr auto extendedVersionKeySize = strlen(extendedVersionKey);
109
110 if (manifestFilePath.empty())
111 {
112 log<level::ERR>("Error MANIFESTFilePath is empty");
113 throw std::runtime_error("MANIFESTFilePath is empty");
114 }
115
116 std::string extendedVersion{};
117 std::ifstream efile;
118 std::string line;
119 efile.exceptions(std::ifstream::failbit
120 | std::ifstream::badbit
121 | std::ifstream::eofbit);
122
123 try
124 {
125 efile.open(manifestFilePath);
126 while (getline(efile, line))
127 {
128 if (line.compare(0, extendedVersionKeySize,
129 extendedVersionKey) == 0)
130 {
131 extendedVersion = line.substr(extendedVersionKeySize);
132 break;
133 }
134 }
135 efile.close();
136 }
137 catch (const std::exception& e)
138 {
139 log<level::ERR>("Error in reading Host MANIFEST file");
140 }
Saqib Khan7254f0e2017-04-10 21:45:37 -0500141 return extendedVersion;
142}
143
Saqib Khana8ade7e2017-04-12 10:27:56 -0500144int ItemUpdater::validateSquashFSImage(const std::string& versionId)
145{
146 auto file = IMAGE_DIR + versionId + "/" +
147 std::string(squashFSImage);
148 std::ifstream efile(file.c_str());
149
150 if (efile.good() == 1)
151 {
152 return 0;
153 }
154 else
155 {
156 log<level::ERR>("Failed to find the SquashFS image.");
157 return -1;
158 }
159}
160
Michael Tritzdd961b62017-05-17 14:07:03 -0500161void ItemUpdater::reset()
162{
163 for(const auto& it : activations)
164 {
165 auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + it.first +
166 ".service";
167
168 // Remove the read-write partitions.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500169 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500170 SYSTEMD_BUSNAME,
171 SYSTEMD_PATH,
172 SYSTEMD_INTERFACE,
173 "StartUnit");
174 method.append(serviceFile, "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500175 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500176 }
177
178 // Remove the preserved partition.
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500179 auto method = bus.new_method_call(
Michael Tritzdd961b62017-05-17 14:07:03 -0500180 SYSTEMD_BUSNAME,
181 SYSTEMD_PATH,
182 SYSTEMD_INTERFACE,
183 "StartUnit");
184 method.append("obmc-flash-bios-ubiumount-prsv.service", "replace");
Adriana Kobylakd6a549e2017-05-10 16:23:01 -0500185 bus.call_noreply(method);
Michael Tritzdd961b62017-05-17 14:07:03 -0500186
187 return;
188}
189
Adriana Kobylakbefe5ce2017-04-05 15:57:44 -0500190} // namespace updater
Adriana Kobylak2d8fa222017-03-15 12:34:32 -0500191} // namespace software
192} // namespace openpower