Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 1 | #include "config.h" |
| 2 | |
| 3 | #include "item_updater.hpp" |
| 4 | |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 5 | #include "runtime_warning.hpp" |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 6 | #include "utils.hpp" |
| 7 | |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 8 | #include <phosphor-logging/elog-errors.hpp> |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 9 | #include <phosphor-logging/lg2.hpp> |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 10 | #include <xyz/openbmc_project/Common/error.hpp> |
| 11 | |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 12 | #include <exception> |
Patrick Williams | 5670b18 | 2023-05-10 07:50:50 -0500 | [diff] [blame] | 13 | #include <filesystem> |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 14 | #include <format> |
| 15 | #include <set> |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 16 | #include <stdexcept> |
Patrick Williams | 5670b18 | 2023-05-10 07:50:50 -0500 | [diff] [blame] | 17 | |
Lei YU | fda15a3 | 2019-09-19 14:43:02 +0800 | [diff] [blame] | 18 | namespace |
| 19 | { |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 20 | constexpr auto MANIFEST_VERSION = "version"; |
| 21 | constexpr auto MANIFEST_EXTENDED_VERSION = "extended_version"; |
| 22 | } // namespace |
Lei YU | fda15a3 | 2019-09-19 14:43:02 +0800 | [diff] [blame] | 23 | |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 24 | namespace phosphor |
| 25 | { |
| 26 | namespace software |
| 27 | { |
| 28 | namespace updater |
| 29 | { |
| 30 | namespace server = sdbusplus::xyz::openbmc_project::Software::server; |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 31 | |
| 32 | using namespace sdbusplus::xyz::openbmc_project::Common::Error; |
| 33 | using namespace phosphor::logging; |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 34 | using SVersion = server::Version; |
| 35 | using VersionPurpose = SVersion::VersionPurpose; |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 36 | |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 37 | void ItemUpdater::onVersionInterfacesAddedMsg(sdbusplus::message_t& msg) |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 38 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 39 | try |
| 40 | { |
| 41 | sdbusplus::message::object_path objPath; |
| 42 | InterfacesAddedMap interfaces; |
| 43 | msg.read(objPath, interfaces); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 44 | |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 45 | std::string path(std::move(objPath)); |
| 46 | onVersionInterfacesAdded(path, interfaces); |
| 47 | } |
| 48 | catch (const std::exception& e) |
| 49 | { |
| 50 | lg2::error("Unable to handle version InterfacesAdded event: {ERROR}", |
| 51 | "ERROR", e); |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | void ItemUpdater::onVersionInterfacesAdded(const std::string& path, |
| 56 | const InterfacesAddedMap& interfaces) |
| 57 | { |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 58 | std::string filePath; |
| 59 | auto purpose = VersionPurpose::Unknown; |
| 60 | std::string version; |
| 61 | |
| 62 | for (const auto& [interfaceName, propertyMap] : interfaces) |
| 63 | { |
| 64 | if (interfaceName == VERSION_IFACE) |
| 65 | { |
| 66 | for (const auto& [propertyName, propertyValue] : propertyMap) |
| 67 | { |
| 68 | if (propertyName == "Purpose") |
| 69 | { |
| 70 | // Only process the PSU images |
| 71 | auto value = SVersion::convertVersionPurposeFromString( |
Lei YU | 1517f5f | 2019-10-14 16:44:42 +0800 | [diff] [blame] | 72 | std::get<std::string>(propertyValue)); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 73 | |
| 74 | if (value == VersionPurpose::PSU) |
| 75 | { |
| 76 | purpose = value; |
| 77 | } |
| 78 | } |
Lei YU | f77189f | 2019-08-07 14:26:30 +0800 | [diff] [blame] | 79 | else if (propertyName == VERSION) |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 80 | { |
Lei YU | 1517f5f | 2019-10-14 16:44:42 +0800 | [diff] [blame] | 81 | version = std::get<std::string>(propertyValue); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 82 | } |
| 83 | } |
| 84 | } |
| 85 | else if (interfaceName == FILEPATH_IFACE) |
| 86 | { |
| 87 | const auto& it = propertyMap.find("Path"); |
| 88 | if (it != propertyMap.end()) |
| 89 | { |
Lei YU | 1517f5f | 2019-10-14 16:44:42 +0800 | [diff] [blame] | 90 | filePath = std::get<std::string>(it->second); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 91 | } |
| 92 | } |
| 93 | } |
| 94 | if ((filePath.empty()) || (purpose == VersionPurpose::Unknown)) |
| 95 | { |
| 96 | return; |
| 97 | } |
| 98 | |
Shawn McCarney | 799f514 | 2024-09-26 14:50:25 -0500 | [diff] [blame] | 99 | // If we are only installing PSU images from the built-in directory, ignore |
| 100 | // PSU images from other directories |
| 101 | if (ALWAYS_USE_BUILTIN_IMG_DIR && !filePath.starts_with(IMG_DIR_BUILTIN)) |
| 102 | { |
| 103 | return; |
| 104 | } |
| 105 | |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 106 | // Version id is the last item in the path |
George Liu | a0f2cf7 | 2024-08-23 14:50:12 +0800 | [diff] [blame] | 107 | auto pos = path.rfind('/'); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 108 | if (pos == std::string::npos) |
| 109 | { |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 110 | lg2::error("No version id found in object path {OBJPATH}", "OBJPATH", |
| 111 | path); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 112 | return; |
| 113 | } |
| 114 | |
| 115 | auto versionId = path.substr(pos + 1); |
| 116 | |
| 117 | if (activations.find(versionId) == activations.end()) |
| 118 | { |
| 119 | // Determine the Activation state by processing the given image dir. |
Lei YU | 9102944 | 2019-08-01 15:57:31 +0800 | [diff] [blame] | 120 | AssociationList associations; |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 121 | auto activationState = Activation::Status::Ready; |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 122 | |
Patrick Williams | bab5ed9 | 2024-08-16 15:20:54 -0400 | [diff] [blame] | 123 | associations.emplace_back(std::make_tuple( |
| 124 | ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION, |
| 125 | PSU_INVENTORY_PATH_BASE)); |
Lei YU | 9102944 | 2019-08-01 15:57:31 +0800 | [diff] [blame] | 126 | |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 127 | fs::path manifestPath(filePath); |
| 128 | manifestPath /= MANIFEST_FILE; |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 129 | std::string extendedVersion = |
| 130 | Version::getValue(manifestPath, {MANIFEST_EXTENDED_VERSION}); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 131 | |
Lei YU | 9930137 | 2019-09-29 16:27:12 +0800 | [diff] [blame] | 132 | auto activation = |
| 133 | createActivationObject(path, versionId, extendedVersion, |
| 134 | activationState, associations, filePath); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 135 | activations.emplace(versionId, std::move(activation)); |
| 136 | |
Patrick Williams | bab5ed9 | 2024-08-16 15:20:54 -0400 | [diff] [blame] | 137 | auto versionPtr = |
| 138 | createVersionObject(path, versionId, version, purpose); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 139 | versions.emplace(versionId, std::move(versionPtr)); |
| 140 | } |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 141 | } |
| 142 | |
Lei YU | a5c47bb | 2019-09-29 11:28:53 +0800 | [diff] [blame] | 143 | void ItemUpdater::erase(const std::string& versionId) |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 144 | { |
| 145 | auto it = versions.find(versionId); |
| 146 | if (it == versions.end()) |
| 147 | { |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 148 | lg2::error("Error: Failed to find version {VERSION_ID} in " |
| 149 | "item updater versions map. Unable to remove.", |
| 150 | "VERSION_ID", versionId); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 151 | } |
| 152 | else |
| 153 | { |
Lei YU | 1517f5f | 2019-10-14 16:44:42 +0800 | [diff] [blame] | 154 | versionStrings.erase(it->second->getVersionString()); |
| 155 | versions.erase(it); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | // Removing entry in activations map |
| 159 | auto ita = activations.find(versionId); |
| 160 | if (ita == activations.end()) |
| 161 | { |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 162 | lg2::error("Error: Failed to find version {VERSION_ID} in " |
| 163 | "item updater activations map. Unable to remove.", |
| 164 | "VERSION_ID", versionId); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 165 | } |
| 166 | else |
| 167 | { |
| 168 | activations.erase(versionId); |
| 169 | } |
| 170 | } |
| 171 | |
Lei YU | 9102944 | 2019-08-01 15:57:31 +0800 | [diff] [blame] | 172 | void ItemUpdater::createActiveAssociation(const std::string& path) |
| 173 | { |
| 174 | assocs.emplace_back( |
| 175 | std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path)); |
| 176 | associations(assocs); |
| 177 | } |
| 178 | |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 179 | void ItemUpdater::addFunctionalAssociation(const std::string& path) |
Lei YU | 9102944 | 2019-08-01 15:57:31 +0800 | [diff] [blame] | 180 | { |
Lei YU | 9102944 | 2019-08-01 15:57:31 +0800 | [diff] [blame] | 181 | assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION, |
| 182 | FUNCTIONAL_REV_ASSOCIATION, path)); |
| 183 | associations(assocs); |
| 184 | } |
| 185 | |
Lei YU | a8b966f | 2020-03-18 10:32:24 +0800 | [diff] [blame] | 186 | void ItemUpdater::addUpdateableAssociation(const std::string& path) |
| 187 | { |
| 188 | assocs.emplace_back(std::make_tuple(UPDATEABLE_FWD_ASSOCIATION, |
| 189 | UPDATEABLE_REV_ASSOCIATION, path)); |
| 190 | associations(assocs); |
| 191 | } |
| 192 | |
Lei YU | 9102944 | 2019-08-01 15:57:31 +0800 | [diff] [blame] | 193 | void ItemUpdater::removeAssociation(const std::string& path) |
| 194 | { |
| 195 | for (auto iter = assocs.begin(); iter != assocs.end();) |
| 196 | { |
George Liu | a5205e4 | 2024-08-23 15:27:54 +0800 | [diff] [blame] | 197 | if ((std::get<2>(*iter)) == path) |
Lei YU | 9102944 | 2019-08-01 15:57:31 +0800 | [diff] [blame] | 198 | { |
| 199 | iter = assocs.erase(iter); |
| 200 | associations(assocs); |
| 201 | } |
| 202 | else |
| 203 | { |
| 204 | ++iter; |
| 205 | } |
| 206 | } |
| 207 | } |
| 208 | |
Lei YU | ffb3653 | 2019-10-15 13:55:24 +0800 | [diff] [blame] | 209 | void ItemUpdater::onUpdateDone(const std::string& versionId, |
| 210 | const std::string& psuInventoryPath) |
| 211 | { |
| 212 | // After update is done, remove old activation objects |
| 213 | for (auto it = activations.begin(); it != activations.end(); ++it) |
| 214 | { |
| 215 | if (it->second->getVersionId() != versionId && |
| 216 | utils::isAssociated(psuInventoryPath, it->second->associations())) |
| 217 | { |
| 218 | removePsuObject(psuInventoryPath); |
| 219 | break; |
| 220 | } |
| 221 | } |
Lei YU | 1517f5f | 2019-10-14 16:44:42 +0800 | [diff] [blame] | 222 | |
| 223 | auto it = activations.find(versionId); |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 224 | if (it == activations.end()) |
| 225 | { |
| 226 | lg2::error("Unable to find Activation for version ID {VERSION_ID}", |
| 227 | "VERSION_ID", versionId); |
| 228 | } |
| 229 | else |
| 230 | { |
| 231 | psuPathActivationMap.emplace(psuInventoryPath, it->second); |
| 232 | } |
Lei YU | ffb3653 | 2019-10-15 13:55:24 +0800 | [diff] [blame] | 233 | } |
| 234 | |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 235 | std::unique_ptr<Activation> ItemUpdater::createActivationObject( |
| 236 | const std::string& path, const std::string& versionId, |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 237 | const std::string& extVersion, Activation::Status activationStatus, |
Lei YU | 9930137 | 2019-09-29 16:27:12 +0800 | [diff] [blame] | 238 | const AssociationList& assocs, const std::string& filePath) |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 239 | { |
| 240 | return std::make_unique<Activation>(bus, path, versionId, extVersion, |
Lei YU | ffb3653 | 2019-10-15 13:55:24 +0800 | [diff] [blame] | 241 | activationStatus, assocs, filePath, |
| 242 | this, this); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 243 | } |
| 244 | |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 245 | void ItemUpdater::createPsuObject(const std::string& psuInventoryPath, |
| 246 | const std::string& psuVersion) |
| 247 | { |
| 248 | auto versionId = utils::getVersionId(psuVersion); |
| 249 | auto path = std::string(SOFTWARE_OBJPATH) + "/" + versionId; |
| 250 | |
| 251 | auto it = activations.find(versionId); |
| 252 | if (it != activations.end()) |
| 253 | { |
| 254 | // The versionId is already created, associate the path |
| 255 | auto associations = it->second->associations(); |
Patrick Williams | bab5ed9 | 2024-08-16 15:20:54 -0400 | [diff] [blame] | 256 | associations.emplace_back( |
| 257 | std::make_tuple(ACTIVATION_FWD_ASSOCIATION, |
| 258 | ACTIVATION_REV_ASSOCIATION, psuInventoryPath)); |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 259 | it->second->associations(associations); |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 260 | psuPathActivationMap.emplace(psuInventoryPath, it->second); |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 261 | } |
| 262 | else |
| 263 | { |
| 264 | // Create a new object for running PSU inventory |
| 265 | AssociationList associations; |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 266 | auto activationState = Activation::Status::Active; |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 267 | |
Patrick Williams | bab5ed9 | 2024-08-16 15:20:54 -0400 | [diff] [blame] | 268 | associations.emplace_back( |
| 269 | std::make_tuple(ACTIVATION_FWD_ASSOCIATION, |
| 270 | ACTIVATION_REV_ASSOCIATION, psuInventoryPath)); |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 271 | |
Lei YU | 9930137 | 2019-09-29 16:27:12 +0800 | [diff] [blame] | 272 | auto activation = createActivationObject( |
| 273 | path, versionId, "", activationState, associations, ""); |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 274 | activations.emplace(versionId, std::move(activation)); |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 275 | psuPathActivationMap.emplace(psuInventoryPath, activations[versionId]); |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 276 | |
| 277 | auto versionPtr = createVersionObject(path, versionId, psuVersion, |
Lei YU | 9930137 | 2019-09-29 16:27:12 +0800 | [diff] [blame] | 278 | VersionPurpose::PSU); |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 279 | versions.emplace(versionId, std::move(versionPtr)); |
| 280 | |
| 281 | createActiveAssociation(path); |
| 282 | addFunctionalAssociation(path); |
Lei YU | a8b966f | 2020-03-18 10:32:24 +0800 | [diff] [blame] | 283 | addUpdateableAssociation(path); |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 284 | } |
| 285 | } |
| 286 | |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 287 | void ItemUpdater::removePsuObject(const std::string& psuInventoryPath) |
| 288 | { |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 289 | auto it = psuPathActivationMap.find(psuInventoryPath); |
| 290 | if (it == psuPathActivationMap.end()) |
| 291 | { |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 292 | lg2::error("No Activation found for PSU {PSUPATH}", "PSUPATH", |
| 293 | psuInventoryPath); |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 294 | return; |
| 295 | } |
| 296 | const auto& activationPtr = it->second; |
| 297 | psuPathActivationMap.erase(psuInventoryPath); |
| 298 | |
| 299 | auto associations = activationPtr->associations(); |
| 300 | for (auto iter = associations.begin(); iter != associations.end();) |
| 301 | { |
George Liu | a5205e4 | 2024-08-23 15:27:54 +0800 | [diff] [blame] | 302 | if ((std::get<2>(*iter)) == psuInventoryPath) |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 303 | { |
| 304 | iter = associations.erase(iter); |
| 305 | } |
| 306 | else |
| 307 | { |
| 308 | ++iter; |
| 309 | } |
| 310 | } |
| 311 | if (associations.empty()) |
| 312 | { |
| 313 | // Remove the activation |
Lei YU | a5c47bb | 2019-09-29 11:28:53 +0800 | [diff] [blame] | 314 | erase(activationPtr->getVersionId()); |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 315 | } |
| 316 | else |
| 317 | { |
| 318 | // Update association |
| 319 | activationPtr->associations(associations); |
| 320 | } |
| 321 | } |
| 322 | |
Shawn McCarney | 73a6f0d | 2024-10-30 16:11:29 -0500 | [diff] [blame] | 323 | void ItemUpdater::addPsuToStatusMap(const std::string& psuPath) |
| 324 | { |
| 325 | if (!psuStatusMap.contains(psuPath)) |
| 326 | { |
| 327 | psuStatusMap[psuPath] = {false, ""}; |
| 328 | |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 329 | // Add PropertiesChanged listener for Item interface so we are notified |
| 330 | // when Present property changes |
Shawn McCarney | 73a6f0d | 2024-10-30 16:11:29 -0500 | [diff] [blame] | 331 | psuMatches.emplace_back( |
| 332 | bus, MatchRules::propertiesChanged(psuPath, ITEM_IFACE), |
| 333 | std::bind(&ItemUpdater::onPsuInventoryChangedMsg, this, |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 334 | std::placeholders::_1)); |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | void ItemUpdater::handlePSUPresenceChanged(const std::string& psuPath) |
| 339 | { |
| 340 | if (psuStatusMap.contains(psuPath)) |
| 341 | { |
| 342 | if (psuStatusMap[psuPath].present) |
| 343 | { |
| 344 | // PSU is now present |
| 345 | psuStatusMap[psuPath].model = utils::getModel(psuPath); |
| 346 | auto version = utils::getVersion(psuPath); |
| 347 | if (!version.empty() && !psuPathActivationMap.contains(psuPath)) |
| 348 | { |
| 349 | createPsuObject(psuPath, version); |
| 350 | } |
| 351 | } |
| 352 | else |
| 353 | { |
| 354 | // PSU is now missing |
| 355 | psuStatusMap[psuPath].model.clear(); |
| 356 | if (psuPathActivationMap.contains(psuPath)) |
| 357 | { |
| 358 | removePsuObject(psuPath); |
| 359 | } |
| 360 | } |
Shawn McCarney | 73a6f0d | 2024-10-30 16:11:29 -0500 | [diff] [blame] | 361 | } |
| 362 | } |
| 363 | |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 364 | std::unique_ptr<Version> ItemUpdater::createVersionObject( |
| 365 | const std::string& objPath, const std::string& versionId, |
| 366 | const std::string& versionString, |
| 367 | sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose |
Lei YU | 9930137 | 2019-09-29 16:27:12 +0800 | [diff] [blame] | 368 | versionPurpose) |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 369 | { |
Lei YU | 6520748 | 2019-10-11 16:39:36 +0800 | [diff] [blame] | 370 | versionStrings.insert(versionString); |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 371 | auto version = std::make_unique<Version>( |
Lei YU | 9930137 | 2019-09-29 16:27:12 +0800 | [diff] [blame] | 372 | bus, objPath, versionId, versionString, versionPurpose, |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 373 | std::bind(&ItemUpdater::erase, this, std::placeholders::_1)); |
| 374 | return version; |
| 375 | } |
| 376 | |
Patrick Williams | 374fae5 | 2022-07-22 19:26:55 -0500 | [diff] [blame] | 377 | void ItemUpdater::onPsuInventoryChangedMsg(sdbusplus::message_t& msg) |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 378 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 379 | try |
Lei YU | 1517f5f | 2019-10-14 16:44:42 +0800 | [diff] [blame] | 380 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 381 | using Interface = std::string; |
| 382 | Interface interface; |
| 383 | Properties properties; |
| 384 | std::string psuPath = msg.get_path(); |
| 385 | |
| 386 | msg.read(interface, properties); |
| 387 | onPsuInventoryChanged(psuPath, properties); |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 388 | } |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 389 | catch (const std::exception& e) |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 390 | { |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 391 | lg2::error( |
| 392 | "Unable to handle inventory PropertiesChanged event: {ERROR}", |
| 393 | "ERROR", e); |
Lei YU | bd3b007 | 2019-08-08 13:09:50 +0800 | [diff] [blame] | 394 | } |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 395 | } |
| 396 | |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 397 | void ItemUpdater::onPsuInventoryChanged(const std::string& psuPath, |
| 398 | const Properties& properties) |
| 399 | { |
| 400 | if (psuStatusMap.contains(psuPath) && properties.contains(PRESENT)) |
| 401 | { |
| 402 | psuStatusMap[psuPath].present = std::get<bool>(properties.at(PRESENT)); |
| 403 | handlePSUPresenceChanged(psuPath); |
| 404 | if (psuStatusMap[psuPath].present) |
| 405 | { |
| 406 | // Check if there are new PSU images to update |
| 407 | processStoredImage(); |
| 408 | syncToLatestImage(); |
| 409 | } |
| 410 | } |
| 411 | } |
| 412 | |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 413 | void ItemUpdater::processPSUImage() |
| 414 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 415 | try |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 416 | { |
Shawn McCarney | d57bd2f | 2024-12-02 18:40:28 -0600 | [diff] [blame] | 417 | auto paths = utils::getPSUInventoryPaths(bus); |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 418 | for (const auto& p : paths) |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 419 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 420 | try |
| 421 | { |
| 422 | addPsuToStatusMap(p); |
| 423 | auto service = utils::getService(bus, p.c_str(), ITEM_IFACE); |
| 424 | psuStatusMap[p].present = utils::getProperty<bool>( |
| 425 | bus, service.c_str(), p.c_str(), ITEM_IFACE, PRESENT); |
| 426 | handlePSUPresenceChanged(p); |
| 427 | } |
| 428 | catch (const std::exception& e) |
| 429 | { |
| 430 | // Ignore errors; the information might not be available yet |
| 431 | } |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 432 | } |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 433 | } |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 434 | catch (const std::exception& e) |
| 435 | { |
| 436 | // Ignore errors; the information might not be available yet |
| 437 | } |
Lei YU | ad90ad5 | 2019-08-06 11:19:28 +0800 | [diff] [blame] | 438 | } |
| 439 | |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 440 | void ItemUpdater::processStoredImage() |
| 441 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 442 | // Build list of directories to scan |
| 443 | std::vector<fs::path> paths; |
| 444 | paths.emplace_back(IMG_DIR_BUILTIN); |
Faisal Awada | fb86e79 | 2024-09-11 10:51:17 -0500 | [diff] [blame] | 445 | if (!ALWAYS_USE_BUILTIN_IMG_DIR) |
| 446 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 447 | paths.emplace_back(IMG_DIR_PERSIST); |
| 448 | } |
| 449 | |
| 450 | // Scan directories |
| 451 | auto logMsg = "Unable to find PSU firmware in directory {PATH}: {ERROR}"; |
| 452 | for (const auto& path : paths) |
| 453 | { |
| 454 | try |
| 455 | { |
| 456 | scanDirectory(path); |
| 457 | } |
| 458 | catch (const RuntimeWarning& r) |
| 459 | { |
| 460 | lg2::warning(logMsg, "PATH", path, "ERROR", r); |
| 461 | } |
| 462 | catch (const std::exception& e) |
| 463 | { |
| 464 | lg2::error(logMsg, "PATH", path, "ERROR", e); |
| 465 | } |
Faisal Awada | fb86e79 | 2024-09-11 10:51:17 -0500 | [diff] [blame] | 466 | } |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 467 | } |
| 468 | |
| 469 | void ItemUpdater::scanDirectory(const fs::path& dir) |
| 470 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 471 | // Find the model subdirectory within the specified directory |
| 472 | auto modelDir = findModelDirectory(dir); |
| 473 | if (modelDir.empty()) |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 474 | { |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 475 | return; |
| 476 | } |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 477 | |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 478 | // Verify a manifest file exists within the model subdirectory |
| 479 | auto manifest = modelDir / MANIFEST_FILE; |
| 480 | if (!fs::exists(manifest)) |
| 481 | { |
| 482 | throw std::runtime_error{ |
| 483 | std::format("Manifest file does not exist: {}", manifest.c_str())}; |
| 484 | } |
| 485 | if (!fs::is_regular_file(manifest)) |
| 486 | { |
| 487 | throw std::runtime_error{ |
| 488 | std::format("Path is not a file: {}", manifest.c_str())}; |
| 489 | } |
| 490 | |
| 491 | // Get version, extVersion, and model from manifest file |
| 492 | auto ret = Version::getValues( |
| 493 | manifest.string(), {MANIFEST_VERSION, MANIFEST_EXTENDED_VERSION}); |
| 494 | auto version = ret[MANIFEST_VERSION]; |
| 495 | auto extVersion = ret[MANIFEST_EXTENDED_VERSION]; |
| 496 | auto info = Version::getExtVersionInfo(extVersion); |
| 497 | auto model = info["model"]; |
| 498 | |
| 499 | // Verify version and model are valid |
| 500 | if (version.empty() || model.empty()) |
| 501 | { |
| 502 | throw std::runtime_error{std::format( |
| 503 | "Invalid information in manifest: path={}, version={}, model={}", |
| 504 | manifest.c_str(), version, model)}; |
| 505 | } |
| 506 | |
| 507 | // Verify model from manifest matches the subdirectory name |
| 508 | if (modelDir.stem() != model) |
| 509 | { |
| 510 | throw std::runtime_error{std::format( |
| 511 | "Model in manifest does not match path: model={}, path={}", model, |
| 512 | modelDir.c_str())}; |
| 513 | } |
| 514 | |
| 515 | // Found a valid PSU image directory; write path to journal |
| 516 | lg2::info("Found PSU firmware image directory: {PATH}", "PATH", modelDir); |
| 517 | |
| 518 | // Calculate version ID and check if an Activation for it exists |
| 519 | auto versionId = utils::getVersionId(version); |
| 520 | auto it = activations.find(versionId); |
| 521 | if (it == activations.end()) |
| 522 | { |
| 523 | // This is a version that is different than the running PSUs |
| 524 | auto activationState = Activation::Status::Ready; |
| 525 | auto purpose = VersionPurpose::PSU; |
| 526 | auto objPath = std::string(SOFTWARE_OBJPATH) + "/" + versionId; |
| 527 | |
| 528 | auto activation = createActivationObject(objPath, versionId, extVersion, |
| 529 | activationState, {}, modelDir); |
| 530 | activations.emplace(versionId, std::move(activation)); |
| 531 | |
| 532 | auto versionPtr = |
| 533 | createVersionObject(objPath, versionId, version, purpose); |
| 534 | versions.emplace(versionId, std::move(versionPtr)); |
| 535 | } |
| 536 | else |
| 537 | { |
Shawn McCarney | 17c2c94 | 2024-12-10 17:32:30 -0600 | [diff] [blame] | 538 | // Activation already exists. It may have been created for code that is |
| 539 | // running on one or more PSUs. Set Path and ExtendedVersion properties. |
| 540 | // The properties are not set when the Activation is created for code |
| 541 | // running on a PSU. The properties are needed to update other PSUs. |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 542 | it->second->path(modelDir); |
Shawn McCarney | 17c2c94 | 2024-12-10 17:32:30 -0600 | [diff] [blame] | 543 | it->second->extendedVersion(extVersion); |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 544 | } |
| 545 | } |
| 546 | |
| 547 | fs::path ItemUpdater::findModelDirectory(const fs::path& dir) |
| 548 | { |
| 549 | fs::path modelDir; |
| 550 | |
| 551 | // Verify directory path exists and is a directory |
| 552 | if (!fs::exists(dir)) |
| 553 | { |
| 554 | // Warning condition. IMG_DIR_BUILTIN might not be used. IMG_DIR_PERSIST |
| 555 | // might not exist if an image from IMG_DIR has not been stored. |
| 556 | throw RuntimeWarning{ |
| 557 | std::format("Directory does not exist: {}", dir.c_str())}; |
| 558 | } |
| 559 | if (!fs::is_directory(dir)) |
| 560 | { |
| 561 | throw std::runtime_error{ |
| 562 | std::format("Path is not a directory: {}", dir.c_str())}; |
| 563 | } |
| 564 | |
| 565 | // Get the model name of the PSUs that have been found. Note that we |
| 566 | // might not have found the PSU information yet on D-Bus. |
| 567 | std::string model; |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 568 | for (const auto& [key, item] : psuStatusMap) |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 569 | { |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 570 | if (!item.model.empty()) |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 571 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 572 | model = item.model; |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 573 | break; |
| 574 | } |
| 575 | } |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 576 | if (!model.empty()) |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 577 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 578 | // Verify model subdirectory path exists and is a directory |
| 579 | auto subDir = dir / model; |
| 580 | if (!fs::exists(subDir)) |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 581 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 582 | // Warning condition. Subdirectory may not exist in IMG_DIR_PERSIST |
| 583 | // if no image has been stored there. May also not exist if |
| 584 | // firmware update is not supported for this PSU model. |
| 585 | throw RuntimeWarning{ |
| 586 | std::format("Directory does not exist: {}", subDir.c_str())}; |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 587 | } |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 588 | if (!fs::is_directory(subDir)) |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 589 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 590 | throw std::runtime_error{ |
| 591 | std::format("Path is not a directory: {}", subDir.c_str())}; |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 592 | } |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 593 | modelDir = subDir; |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 594 | } |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 595 | |
| 596 | return modelDir; |
Lei YU | 58c26e3 | 2019-09-27 17:52:06 +0800 | [diff] [blame] | 597 | } |
| 598 | |
Lei YU | 6520748 | 2019-10-11 16:39:36 +0800 | [diff] [blame] | 599 | std::optional<std::string> ItemUpdater::getLatestVersionId() |
| 600 | { |
Faisal Awada | fb86e79 | 2024-09-11 10:51:17 -0500 | [diff] [blame] | 601 | std::string latestVersion; |
| 602 | if (ALWAYS_USE_BUILTIN_IMG_DIR) |
| 603 | { |
| 604 | latestVersion = getFWVersionFromBuiltinDir(); |
| 605 | } |
| 606 | else |
| 607 | { |
| 608 | latestVersion = utils::getLatestVersion(versionStrings); |
| 609 | } |
Lei YU | 6520748 | 2019-10-11 16:39:36 +0800 | [diff] [blame] | 610 | if (latestVersion.empty()) |
| 611 | { |
| 612 | return {}; |
| 613 | } |
| 614 | |
| 615 | std::optional<std::string> versionId; |
| 616 | for (const auto& v : versions) |
| 617 | { |
| 618 | if (v.second->version() == latestVersion) |
| 619 | { |
| 620 | versionId = v.first; |
| 621 | break; |
| 622 | } |
| 623 | } |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 624 | if (!versionId.has_value()) |
| 625 | { |
| 626 | lg2::error("Unable to find versionId for latest version {VERSION}", |
| 627 | "VERSION", latestVersion); |
| 628 | } |
Lei YU | 6520748 | 2019-10-11 16:39:36 +0800 | [diff] [blame] | 629 | return versionId; |
| 630 | } |
| 631 | |
Lei YU | 63f9e71 | 2019-10-12 15:16:55 +0800 | [diff] [blame] | 632 | void ItemUpdater::syncToLatestImage() |
| 633 | { |
| 634 | auto latestVersionId = getLatestVersionId(); |
| 635 | if (!latestVersionId) |
| 636 | { |
| 637 | return; |
| 638 | } |
| 639 | const auto& it = activations.find(*latestVersionId); |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 640 | if (it == activations.end()) |
| 641 | |
| 642 | { |
| 643 | lg2::error("Unable to find Activation for versionId {VERSION_ID}", |
| 644 | "VERSION_ID", *latestVersionId); |
| 645 | return; |
| 646 | } |
Lei YU | 63f9e71 | 2019-10-12 15:16:55 +0800 | [diff] [blame] | 647 | const auto& activation = it->second; |
| 648 | const auto& assocs = activation->associations(); |
| 649 | |
Shawn McCarney | d57bd2f | 2024-12-02 18:40:28 -0600 | [diff] [blame] | 650 | auto paths = utils::getPSUInventoryPaths(bus); |
Lei YU | 63f9e71 | 2019-10-12 15:16:55 +0800 | [diff] [blame] | 651 | for (const auto& p : paths) |
| 652 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 653 | // If there is a present PSU that is not associated with the latest |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 654 | // image, run the activation so that all PSUs are running the same |
| 655 | // latest image. |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 656 | if (psuStatusMap.contains(p) && psuStatusMap[p].present) |
Lei YU | 63f9e71 | 2019-10-12 15:16:55 +0800 | [diff] [blame] | 657 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 658 | if (!utils::isAssociated(p, assocs)) |
| 659 | { |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 660 | lg2::info("Automatically update PSUs to versionId {VERSION_ID}", |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 661 | "VERSION_ID", *latestVersionId); |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 662 | invokeActivation(activation); |
| 663 | break; |
| 664 | } |
Lei YU | 63f9e71 | 2019-10-12 15:16:55 +0800 | [diff] [blame] | 665 | } |
| 666 | } |
| 667 | } |
| 668 | |
Patrick Williams | 20a045f | 2024-12-18 11:21:25 -0500 | [diff] [blame] | 669 | void |
| 670 | ItemUpdater::invokeActivation(const std::unique_ptr<Activation>& activation) |
Lei YU | 63f9e71 | 2019-10-12 15:16:55 +0800 | [diff] [blame] | 671 | { |
| 672 | activation->requestedActivation(Activation::RequestedActivations::Active); |
| 673 | } |
| 674 | |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 675 | void ItemUpdater::onPSUInterfacesAdded(sdbusplus::message_t& msg) |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 676 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 677 | // Maintain static set of valid PSU paths. This is needed if PSU interface |
| 678 | // comes in a separate InterfacesAdded message from Item interface. |
| 679 | static std::set<std::string> psuPaths{}; |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 680 | |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 681 | try |
Shawn McCarney | 73a6f0d | 2024-10-30 16:11:29 -0500 | [diff] [blame] | 682 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 683 | sdbusplus::message::object_path objPath; |
Shawn McCarney | 487e2e1 | 2024-11-25 17:19:46 -0600 | [diff] [blame] | 684 | InterfacesAddedMap interfaces; |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 685 | msg.read(objPath, interfaces); |
| 686 | std::string path = objPath.str; |
Shawn McCarney | 73a6f0d | 2024-10-30 16:11:29 -0500 | [diff] [blame] | 687 | |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 688 | if (interfaces.contains(PSU_INVENTORY_IFACE)) |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 689 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 690 | psuPaths.insert(path); |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 691 | } |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 692 | |
| 693 | if (interfaces.contains(ITEM_IFACE) && psuPaths.contains(path) && |
| 694 | !psuStatusMap.contains(path)) |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 695 | { |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 696 | auto interface = interfaces[ITEM_IFACE]; |
| 697 | if (interface.contains(PRESENT)) |
| 698 | { |
| 699 | addPsuToStatusMap(path); |
| 700 | psuStatusMap[path].present = std::get<bool>(interface[PRESENT]); |
| 701 | handlePSUPresenceChanged(path); |
| 702 | if (psuStatusMap[path].present) |
| 703 | { |
| 704 | // Check if there are new PSU images to update |
| 705 | processStoredImage(); |
| 706 | syncToLatestImage(); |
| 707 | } |
| 708 | } |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 709 | } |
| 710 | } |
Shawn McCarney | 783406e | 2024-11-17 21:49:37 -0600 | [diff] [blame] | 711 | catch (const std::exception& e) |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 712 | { |
Shawn McCarney | cdf86de | 2024-11-26 10:02:14 -0600 | [diff] [blame] | 713 | lg2::error("Unable to handle inventory InterfacesAdded event: {ERROR}", |
| 714 | "ERROR", e); |
Faisal Awada | 760053d | 2024-05-16 13:31:32 -0500 | [diff] [blame] | 715 | } |
| 716 | } |
| 717 | |
| 718 | void ItemUpdater::processPSUImageAndSyncToLatest() |
| 719 | { |
| 720 | processPSUImage(); |
| 721 | processStoredImage(); |
| 722 | syncToLatestImage(); |
| 723 | } |
| 724 | |
Faisal Awada | fb86e79 | 2024-09-11 10:51:17 -0500 | [diff] [blame] | 725 | std::string ItemUpdater::getFWVersionFromBuiltinDir() |
| 726 | { |
| 727 | std::string version; |
| 728 | for (const auto& activation : activations) |
| 729 | { |
| 730 | if (activation.second->path().starts_with(IMG_DIR_BUILTIN)) |
| 731 | { |
| 732 | std::string versionId = activation.second->getVersionId(); |
| 733 | auto it = versions.find(versionId); |
| 734 | if (it != versions.end()) |
| 735 | { |
| 736 | const auto& versionPtr = it->second; |
| 737 | version = versionPtr->version(); |
| 738 | break; |
| 739 | } |
| 740 | } |
| 741 | } |
| 742 | return version; |
| 743 | } |
| 744 | |
Lei YU | 01539e7 | 2019-07-31 10:57:38 +0800 | [diff] [blame] | 745 | } // namespace updater |
| 746 | } // namespace software |
| 747 | } // namespace phosphor |