blob: b6707358860684ae1219dc1ea4f05d7fdbd5153d [file] [log] [blame]
Lei YU01539e72019-07-31 10:57:38 +08001#include "config.h"
2
3#include "item_updater.hpp"
4
5#include <filesystem>
6#include <phosphor-logging/elog-errors.hpp>
7#include <phosphor-logging/log.hpp>
8#include <xyz/openbmc_project/Common/error.hpp>
9
10namespace phosphor
11{
12namespace software
13{
14namespace updater
15{
16namespace server = sdbusplus::xyz::openbmc_project::Software::server;
17namespace fs = std::filesystem;
18
19using namespace sdbusplus::xyz::openbmc_project::Common::Error;
20using namespace phosphor::logging;
21
22void ItemUpdater::createActivation(sdbusplus::message::message& m)
23{
24 using SVersion = server::Version;
25 using VersionPurpose = SVersion::VersionPurpose;
26 namespace msg = sdbusplus::message;
27 namespace variant_ns = msg::variant_ns;
28
29 sdbusplus::message::object_path objPath;
30 std::map<std::string, std::map<std::string, msg::variant<std::string>>>
31 interfaces;
32 m.read(objPath, interfaces);
33
34 std::string path(std::move(objPath));
35 std::string filePath;
36 auto purpose = VersionPurpose::Unknown;
37 std::string version;
38
39 for (const auto& [interfaceName, propertyMap] : interfaces)
40 {
41 if (interfaceName == VERSION_IFACE)
42 {
43 for (const auto& [propertyName, propertyValue] : propertyMap)
44 {
45 if (propertyName == "Purpose")
46 {
47 // Only process the PSU images
48 auto value = SVersion::convertVersionPurposeFromString(
49 variant_ns::get<std::string>(propertyValue));
50
51 if (value == VersionPurpose::PSU)
52 {
53 purpose = value;
54 }
55 }
56 else if (propertyName == "Version")
57 {
58 version = variant_ns::get<std::string>(propertyValue);
59 }
60 }
61 }
62 else if (interfaceName == FILEPATH_IFACE)
63 {
64 const auto& it = propertyMap.find("Path");
65 if (it != propertyMap.end())
66 {
67 filePath = variant_ns::get<std::string>(it->second);
68 }
69 }
70 }
71 if ((filePath.empty()) || (purpose == VersionPurpose::Unknown))
72 {
73 return;
74 }
75
76 // Version id is the last item in the path
77 auto pos = path.rfind("/");
78 if (pos == std::string::npos)
79 {
80 log<level::ERR>("No version id found in object path",
81 entry("OBJPATH=%s", path.c_str()));
82 return;
83 }
84
85 auto versionId = path.substr(pos + 1);
86
87 if (activations.find(versionId) == activations.end())
88 {
89 // Determine the Activation state by processing the given image dir.
Lei YU91029442019-08-01 15:57:31 +080090 AssociationList associations;
Lei YU01539e72019-07-31 10:57:38 +080091 auto activationState = server::Activation::Activations::Ready;
92
Lei YU91029442019-08-01 15:57:31 +080093 associations.emplace_back(std::make_tuple(ACTIVATION_FWD_ASSOCIATION,
94 ACTIVATION_REV_ASSOCIATION,
Lei YU5e0dcb32019-08-02 18:04:34 +080095 PSU_INVENTORY_PATH_BASE));
Lei YU91029442019-08-01 15:57:31 +080096
Lei YU01539e72019-07-31 10:57:38 +080097 fs::path manifestPath(filePath);
98 manifestPath /= MANIFEST_FILE;
99 std::string extendedVersion =
100 (Version::getValue(
101 manifestPath.string(),
102 std::map<std::string, std::string>{{"extended_version", ""}}))
103 .begin()
104 ->second;
105
106 auto activation = createActivationObject(
Lei YU91029442019-08-01 15:57:31 +0800107 path, versionId, extendedVersion, activationState, associations);
Lei YU01539e72019-07-31 10:57:38 +0800108 activations.emplace(versionId, std::move(activation));
109
110 auto versionPtr =
111 createVersionObject(path, versionId, version, purpose, filePath);
112 versions.emplace(versionId, std::move(versionPtr));
113 }
114 return;
115}
116
117void ItemUpdater::erase(std::string versionId)
118{
119 auto it = versions.find(versionId);
120 if (it == versions.end())
121 {
122 log<level::ERR>(("Error: Failed to find version " + versionId +
123 " in item updater versions map."
124 " Unable to remove.")
125 .c_str());
126 }
127 else
128 {
129 versions.erase(versionId);
130 }
131
132 // Removing entry in activations map
133 auto ita = activations.find(versionId);
134 if (ita == activations.end())
135 {
136 log<level::ERR>(("Error: Failed to find version " + versionId +
137 " in item updater activations map."
138 " Unable to remove.")
139 .c_str());
140 }
141 else
142 {
143 activations.erase(versionId);
144 }
145}
146
147void ItemUpdater::deleteAll()
148{
149 // TODO: when PSU's running firmware is implemented, delete all versions
150 // that are not the running firmware.
151}
152
Lei YU91029442019-08-01 15:57:31 +0800153void ItemUpdater::createActiveAssociation(const std::string& path)
154{
155 assocs.emplace_back(
156 std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path));
157 associations(assocs);
158}
159
160void ItemUpdater::updateFunctionalAssociation(const std::string& versionId)
161{
162 std::string path = std::string{SOFTWARE_OBJPATH} + '/' + versionId;
163 // remove all functional associations
164 for (auto iter = assocs.begin(); iter != assocs.end();)
165 {
166 if ((std::get<0>(*iter)).compare(FUNCTIONAL_FWD_ASSOCIATION) == 0)
167 {
168 iter = assocs.erase(iter);
169 }
170 else
171 {
172 ++iter;
173 }
174 }
175 assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION,
176 FUNCTIONAL_REV_ASSOCIATION, path));
177 associations(assocs);
178}
179
180void ItemUpdater::removeAssociation(const std::string& path)
181{
182 for (auto iter = assocs.begin(); iter != assocs.end();)
183 {
184 if ((std::get<2>(*iter)).compare(path) == 0)
185 {
186 iter = assocs.erase(iter);
187 associations(assocs);
188 }
189 else
190 {
191 ++iter;
192 }
193 }
194}
195
Lei YU01539e72019-07-31 10:57:38 +0800196std::unique_ptr<Activation> ItemUpdater::createActivationObject(
197 const std::string& path, const std::string& versionId,
198 const std::string& extVersion,
199 sdbusplus::xyz::openbmc_project::Software::server::Activation::Activations
Lei YU91029442019-08-01 15:57:31 +0800200 activationStatus,
201 const AssociationList& assocs)
Lei YU01539e72019-07-31 10:57:38 +0800202{
203 return std::make_unique<Activation>(bus, path, versionId, extVersion,
Lei YU91029442019-08-01 15:57:31 +0800204 activationStatus, assocs);
Lei YU01539e72019-07-31 10:57:38 +0800205}
206
207std::unique_ptr<Version> ItemUpdater::createVersionObject(
208 const std::string& objPath, const std::string& versionId,
209 const std::string& versionString,
210 sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
211 versionPurpose,
212 const std::string& filePath)
213{
214 auto version = std::make_unique<Version>(
215 bus, objPath, versionId, versionString, versionPurpose, filePath,
216 std::bind(&ItemUpdater::erase, this, std::placeholders::_1));
217 return version;
218}
219
220} // namespace updater
221} // namespace software
222} // namespace phosphor