| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 1 | #include "config.h" | 
|  | 2 |  | 
|  | 3 | #include "item_updater_ubi.hpp" | 
|  | 4 |  | 
| Lei YU | 9b21efc | 2019-02-21 15:52:53 +0800 | [diff] [blame] | 5 | #include "activation_ubi.hpp" | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 6 | #include "serialize.hpp" | 
| Lei YU | e499446 | 2019-03-14 14:41:53 +0800 | [diff] [blame] | 7 | #include "utils.hpp" | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 8 | #include "version.hpp" | 
|  | 9 | #include "xyz/openbmc_project/Common/error.hpp" | 
|  | 10 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 11 | #include <phosphor-logging/elog-errors.hpp> | 
|  | 12 | #include <phosphor-logging/log.hpp> | 
| Brad Bishop | 8facccf | 2020-11-04 09:44:58 -0500 | [diff] [blame] | 13 | #include <xyz/openbmc_project/Software/Version/server.hpp> | 
|  | 14 |  | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 15 | #include <filesystem> | 
| Brad Bishop | 8facccf | 2020-11-04 09:44:58 -0500 | [diff] [blame] | 16 | #include <fstream> | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 17 | #include <queue> | 
|  | 18 | #include <string> | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 19 |  | 
|  | 20 | namespace openpower | 
|  | 21 | { | 
|  | 22 | namespace software | 
|  | 23 | { | 
|  | 24 | namespace updater | 
|  | 25 | { | 
|  | 26 |  | 
|  | 27 | // When you see server:: you know we're referencing our base class | 
|  | 28 | namespace server = sdbusplus::xyz::openbmc_project::Software::server; | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 29 |  | 
|  | 30 | using namespace sdbusplus::xyz::openbmc_project::Common::Error; | 
|  | 31 | using namespace phosphor::logging; | 
|  | 32 |  | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 33 | std::unique_ptr<Activation> ItemUpdaterUbi::createActivationObject( | 
|  | 34 | const std::string& path, const std::string& versionId, | 
|  | 35 | const std::string& extVersion, | 
|  | 36 | sdbusplus::xyz::openbmc_project::Software::server::Activation::Activations | 
|  | 37 | activationStatus, | 
|  | 38 | AssociationList& assocs) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 39 | { | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 40 | return std::make_unique<ActivationUbi>( | 
|  | 41 | bus, path, *this, versionId, extVersion, activationStatus, assocs); | 
|  | 42 | } | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 43 |  | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 44 | std::unique_ptr<Version> ItemUpdaterUbi::createVersionObject( | 
|  | 45 | const std::string& objPath, const std::string& versionId, | 
|  | 46 | const std::string& versionString, | 
|  | 47 | sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose | 
|  | 48 | versionPurpose, | 
|  | 49 | const std::string& filePath) | 
|  | 50 | { | 
|  | 51 | auto version = std::make_unique<Version>( | 
|  | 52 | bus, objPath, *this, versionId, versionString, versionPurpose, filePath, | 
|  | 53 | std::bind(&ItemUpdaterUbi::erase, this, std::placeholders::_1)); | 
|  | 54 | version->deleteObject = std::make_unique<Delete>(bus, objPath, *version); | 
|  | 55 | return version; | 
|  | 56 | } | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 57 |  | 
| Lei YU | a9ac927 | 2019-02-22 16:38:35 +0800 | [diff] [blame] | 58 | bool ItemUpdaterUbi::validateImage(const std::string& path) | 
|  | 59 | { | 
|  | 60 | return validateSquashFSImage(path) == 0; | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 61 | } | 
|  | 62 |  | 
|  | 63 | void ItemUpdaterUbi::processPNORImage() | 
|  | 64 | { | 
|  | 65 | // Read pnor.toc from folders under /media/ | 
|  | 66 | // to get Active Software Versions. | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 67 | for (const auto& iter : std::filesystem::directory_iterator(MEDIA_DIR)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 68 | { | 
|  | 69 | auto activationState = server::Activation::Activations::Active; | 
|  | 70 |  | 
|  | 71 | static const auto PNOR_RO_PREFIX_LEN = strlen(PNOR_RO_PREFIX); | 
|  | 72 | static const auto PNOR_RW_PREFIX_LEN = strlen(PNOR_RW_PREFIX); | 
|  | 73 |  | 
|  | 74 | // Check if the PNOR_RO_PREFIX is the prefix of the iter.path | 
|  | 75 | if (0 == | 
|  | 76 | iter.path().native().compare(0, PNOR_RO_PREFIX_LEN, PNOR_RO_PREFIX)) | 
|  | 77 | { | 
|  | 78 | // The versionId is extracted from the path | 
|  | 79 | // for example /media/pnor-ro-2a1022fe. | 
|  | 80 | auto id = iter.path().native().substr(PNOR_RO_PREFIX_LEN); | 
|  | 81 | auto pnorTOC = iter.path() / PNOR_TOC_FILE; | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 82 | if (!std::filesystem::is_regular_file(pnorTOC)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 83 | { | 
|  | 84 | log<level::ERR>("Failed to read pnorTOC.", | 
|  | 85 | entry("FILENAME=%s", pnorTOC.c_str())); | 
|  | 86 | ItemUpdaterUbi::erase(id); | 
|  | 87 | continue; | 
|  | 88 | } | 
|  | 89 | auto keyValues = Version::getValue( | 
|  | 90 | pnorTOC, {{"version", ""}, {"extended_version", ""}}); | 
|  | 91 | auto& version = keyValues.at("version"); | 
|  | 92 | if (version.empty()) | 
|  | 93 | { | 
|  | 94 | log<level::ERR>("Failed to read version from pnorTOC", | 
|  | 95 | entry("FILENAME=%s", pnorTOC.c_str())); | 
|  | 96 | activationState = server::Activation::Activations::Invalid; | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | auto& extendedVersion = keyValues.at("extended_version"); | 
|  | 100 | if (extendedVersion.empty()) | 
|  | 101 | { | 
|  | 102 | log<level::ERR>("Failed to read extendedVersion from pnorTOC", | 
|  | 103 | entry("FILENAME=%s", pnorTOC.c_str())); | 
|  | 104 | activationState = server::Activation::Activations::Invalid; | 
|  | 105 | } | 
|  | 106 |  | 
|  | 107 | auto purpose = server::Version::VersionPurpose::Host; | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 108 | auto path = std::filesystem::path(SOFTWARE_OBJPATH) / id; | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 109 | AssociationList associations = {}; | 
|  | 110 |  | 
|  | 111 | if (activationState == server::Activation::Activations::Active) | 
|  | 112 | { | 
|  | 113 | // Create an association to the host inventory item | 
|  | 114 | associations.emplace_back(std::make_tuple( | 
|  | 115 | ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION, | 
|  | 116 | HOST_INVENTORY_PATH)); | 
|  | 117 |  | 
|  | 118 | // Create an active association since this image is active | 
|  | 119 | createActiveAssociation(path); | 
|  | 120 | } | 
|  | 121 |  | 
| Adriana Kobylak | 3c81037 | 2020-07-15 16:47:03 -0500 | [diff] [blame] | 122 | // All updateable firmware components must expose the updateable | 
|  | 123 | // association. | 
|  | 124 | createUpdateableAssociation(path); | 
|  | 125 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 126 | // Create Activation instance for this version. | 
|  | 127 | activations.insert( | 
| Lei YU | 9b21efc | 2019-02-21 15:52:53 +0800 | [diff] [blame] | 128 | std::make_pair(id, std::make_unique<ActivationUbi>( | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 129 | bus, path, *this, id, extendedVersion, | 
|  | 130 | activationState, associations))); | 
|  | 131 |  | 
|  | 132 | // If Active, create RedundancyPriority instance for this version. | 
|  | 133 | if (activationState == server::Activation::Activations::Active) | 
|  | 134 | { | 
|  | 135 | uint8_t priority = std::numeric_limits<uint8_t>::max(); | 
|  | 136 | if (!restoreFromFile(id, priority)) | 
|  | 137 | { | 
|  | 138 | log<level::ERR>("Unable to restore priority from file.", | 
|  | 139 | entry("VERSIONID=%s", id.c_str())); | 
|  | 140 | } | 
|  | 141 | activations.find(id)->second->redundancyPriority = | 
| Lei YU | 9b21efc | 2019-02-21 15:52:53 +0800 | [diff] [blame] | 142 | std::make_unique<RedundancyPriorityUbi>( | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 143 | bus, path, *(activations.find(id)->second), priority); | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | // Create Version instance for this version. | 
|  | 147 | auto versionPtr = std::make_unique<Version>( | 
|  | 148 | bus, path, *this, id, version, purpose, "", | 
|  | 149 | std::bind(&ItemUpdaterUbi::erase, this, std::placeholders::_1)); | 
|  | 150 | versionPtr->deleteObject = | 
|  | 151 | std::make_unique<Delete>(bus, path, *versionPtr); | 
|  | 152 | versions.insert(std::make_pair(id, std::move(versionPtr))); | 
|  | 153 | } | 
|  | 154 | else if (0 == iter.path().native().compare(0, PNOR_RW_PREFIX_LEN, | 
|  | 155 | PNOR_RW_PREFIX)) | 
|  | 156 | { | 
|  | 157 | auto id = iter.path().native().substr(PNOR_RW_PREFIX_LEN); | 
|  | 158 | auto roDir = PNOR_RO_PREFIX + id; | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 159 | if (!std::filesystem::is_directory(roDir)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 160 | { | 
|  | 161 | log<level::ERR>("No corresponding read-only volume found.", | 
|  | 162 | entry("DIRNAME=%s", roDir.c_str())); | 
|  | 163 | ItemUpdaterUbi::erase(id); | 
|  | 164 | } | 
|  | 165 | } | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | // Look at the RO symlink to determine if there is a functional image | 
|  | 169 | auto id = determineId(PNOR_RO_ACTIVE_PATH); | 
|  | 170 | if (!id.empty()) | 
|  | 171 | { | 
|  | 172 | updateFunctionalAssociation(id); | 
|  | 173 | } | 
|  | 174 | return; | 
|  | 175 | } | 
|  | 176 |  | 
|  | 177 | int ItemUpdaterUbi::validateSquashFSImage(const std::string& filePath) | 
|  | 178 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 179 | auto file = std::filesystem::path(filePath) / squashFSImage; | 
|  | 180 | if (std::filesystem::is_regular_file(file)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 181 | { | 
|  | 182 | return 0; | 
|  | 183 | } | 
|  | 184 | else | 
|  | 185 | { | 
|  | 186 | log<level::ERR>("Failed to find the SquashFS image."); | 
|  | 187 | return -1; | 
|  | 188 | } | 
|  | 189 | } | 
|  | 190 |  | 
| Lei YU | 1db9adf | 2019-03-05 16:02:31 +0800 | [diff] [blame] | 191 | void ItemUpdaterUbi::removeReadOnlyPartition(const std::string& versionId) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 192 | { | 
|  | 193 | auto serviceFile = "obmc-flash-bios-ubiumount-ro@" + versionId + ".service"; | 
|  | 194 |  | 
|  | 195 | // Remove the read-only partitions. | 
|  | 196 | auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, | 
|  | 197 | SYSTEMD_INTERFACE, "StartUnit"); | 
|  | 198 | method.append(serviceFile, "replace"); | 
|  | 199 | bus.call_noreply(method); | 
|  | 200 | } | 
|  | 201 |  | 
| Lei YU | 1db9adf | 2019-03-05 16:02:31 +0800 | [diff] [blame] | 202 | void ItemUpdaterUbi::removeReadWritePartition(const std::string& versionId) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 203 | { | 
|  | 204 | auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + versionId + ".service"; | 
|  | 205 |  | 
|  | 206 | // Remove the read-write partitions. | 
|  | 207 | auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, | 
|  | 208 | SYSTEMD_INTERFACE, "StartUnit"); | 
|  | 209 | method.append(serviceFile, "replace"); | 
|  | 210 | bus.call_noreply(method); | 
|  | 211 | } | 
|  | 212 |  | 
|  | 213 | void ItemUpdaterUbi::reset() | 
|  | 214 | { | 
| Lei YU | e499446 | 2019-03-14 14:41:53 +0800 | [diff] [blame] | 215 | utils::hiomapdSuspend(bus); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 216 |  | 
|  | 217 | constexpr static auto patchDir = "/usr/local/share/pnor"; | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 218 | if (std::filesystem::is_directory(patchDir)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 219 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 220 | for (const auto& iter : std::filesystem::directory_iterator(patchDir)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 221 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 222 | std::filesystem::remove_all(iter); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 223 | } | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | // Clear the read-write partitions. | 
|  | 227 | for (const auto& it : activations) | 
|  | 228 | { | 
|  | 229 | auto rwDir = PNOR_RW_PREFIX + it.first; | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 230 | if (std::filesystem::is_directory(rwDir)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 231 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 232 | for (const auto& iter : std::filesystem::directory_iterator(rwDir)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 233 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 234 | std::filesystem::remove_all(iter); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 235 | } | 
|  | 236 | } | 
|  | 237 | } | 
|  | 238 |  | 
|  | 239 | // Clear the preserved partition. | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 240 | if (std::filesystem::is_directory(PNOR_PRSV)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 241 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 242 | for (const auto& iter : std::filesystem::directory_iterator(PNOR_PRSV)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 243 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 244 | std::filesystem::remove_all(iter); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 245 | } | 
|  | 246 | } | 
|  | 247 |  | 
| Lei YU | e499446 | 2019-03-14 14:41:53 +0800 | [diff] [blame] | 248 | utils::hiomapdResume(bus); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 249 | } | 
|  | 250 |  | 
|  | 251 | bool ItemUpdaterUbi::isVersionFunctional(const std::string& versionId) | 
|  | 252 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 253 | if (!std::filesystem::exists(PNOR_RO_ACTIVE_PATH)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 254 | { | 
|  | 255 | return false; | 
|  | 256 | } | 
|  | 257 |  | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 258 | std::filesystem::path activeRO = | 
|  | 259 | std::filesystem::read_symlink(PNOR_RO_ACTIVE_PATH); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 260 |  | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 261 | if (!std::filesystem::is_directory(activeRO)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 262 | { | 
|  | 263 | return false; | 
|  | 264 | } | 
|  | 265 |  | 
|  | 266 | if (activeRO.string().find(versionId) == std::string::npos) | 
|  | 267 | { | 
|  | 268 | return false; | 
|  | 269 | } | 
|  | 270 |  | 
|  | 271 | // active PNOR is the version we're checking | 
|  | 272 | return true; | 
|  | 273 | } | 
|  | 274 |  | 
|  | 275 | void ItemUpdaterUbi::freePriority(uint8_t value, const std::string& versionId) | 
|  | 276 | { | 
| Adriana Kobylak | abe862a | 2019-07-17 16:09:00 -0500 | [diff] [blame] | 277 | //  Versions with the lowest priority in front | 
|  | 278 | std::priority_queue<std::pair<int, std::string>, | 
|  | 279 | std::vector<std::pair<int, std::string>>, | 
|  | 280 | std::greater<std::pair<int, std::string>>> | 
|  | 281 | versionsPQ; | 
|  | 282 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 283 | for (const auto& intf : activations) | 
|  | 284 | { | 
|  | 285 | if (intf.second->redundancyPriority) | 
|  | 286 | { | 
| Adriana Kobylak | abe862a | 2019-07-17 16:09:00 -0500 | [diff] [blame] | 287 | versionsPQ.push(std::make_pair( | 
|  | 288 | intf.second->redundancyPriority.get()->priority(), | 
|  | 289 | intf.second->versionId)); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 290 | } | 
|  | 291 | } | 
| Adriana Kobylak | abe862a | 2019-07-17 16:09:00 -0500 | [diff] [blame] | 292 |  | 
|  | 293 | while (!versionsPQ.empty()) | 
|  | 294 | { | 
|  | 295 | if (versionsPQ.top().first == value && | 
|  | 296 | versionsPQ.top().second != versionId) | 
|  | 297 | { | 
|  | 298 | // Increase priority by 1 and update its value | 
|  | 299 | ++value; | 
|  | 300 | storeToFile(versionsPQ.top().second, value); | 
|  | 301 | auto it = activations.find(versionsPQ.top().second); | 
|  | 302 | it->second->redundancyPriority.get()->sdbusplus::xyz:: | 
|  | 303 | openbmc_project::Software::server::RedundancyPriority::priority( | 
|  | 304 | value); | 
|  | 305 | } | 
|  | 306 | versionsPQ.pop(); | 
|  | 307 | } | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 308 | } | 
|  | 309 |  | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 310 | bool ItemUpdaterUbi::erase(std::string entryId) | 
|  | 311 | { | 
|  | 312 | if (!ItemUpdater::erase(entryId)) | 
|  | 313 | { | 
|  | 314 | return false; | 
|  | 315 | } | 
|  | 316 |  | 
|  | 317 | // Remove priority persistence file | 
|  | 318 | removeFile(entryId); | 
|  | 319 |  | 
|  | 320 | // Removing read-only and read-write partitions | 
|  | 321 | removeReadWritePartition(entryId); | 
|  | 322 | removeReadOnlyPartition(entryId); | 
|  | 323 |  | 
|  | 324 | return true; | 
|  | 325 | } | 
|  | 326 |  | 
|  | 327 | void ItemUpdaterUbi::deleteAll() | 
|  | 328 | { | 
|  | 329 | auto chassisOn = isChassisOn(); | 
|  | 330 |  | 
|  | 331 | for (const auto& activationIt : activations) | 
|  | 332 | { | 
|  | 333 | if (isVersionFunctional(activationIt.first) && chassisOn) | 
|  | 334 | { | 
|  | 335 | continue; | 
|  | 336 | } | 
|  | 337 | else | 
|  | 338 | { | 
|  | 339 | ItemUpdaterUbi::erase(activationIt.first); | 
|  | 340 | } | 
|  | 341 | } | 
|  | 342 |  | 
|  | 343 | // Remove any remaining pnor-ro- or pnor-rw- volumes that do not match | 
|  | 344 | // the current version. | 
|  | 345 | auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, | 
|  | 346 | SYSTEMD_INTERFACE, "StartUnit"); | 
|  | 347 | method.append("obmc-flash-bios-cleanup.service", "replace"); | 
|  | 348 | bus.call_noreply(method); | 
|  | 349 | } | 
|  | 350 |  | 
|  | 351 | // TODO: openbmc/openbmc#1402 Monitor flash usage | 
| Lei YU | 6da3dae | 2019-02-28 14:26:37 +0800 | [diff] [blame] | 352 | bool ItemUpdaterUbi::freeSpace() | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 353 | { | 
| Lei YU | 6da3dae | 2019-02-28 14:26:37 +0800 | [diff] [blame] | 354 | bool isSpaceFreed = false; | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 355 | //  Versions with the highest priority in front | 
|  | 356 | std::priority_queue<std::pair<int, std::string>, | 
|  | 357 | std::vector<std::pair<int, std::string>>, | 
|  | 358 | std::less<std::pair<int, std::string>>> | 
|  | 359 | versionsPQ; | 
|  | 360 |  | 
|  | 361 | std::size_t count = 0; | 
|  | 362 | for (const auto& iter : activations) | 
|  | 363 | { | 
|  | 364 | if (iter.second.get()->activation() == | 
|  | 365 | server::Activation::Activations::Active) | 
|  | 366 | { | 
|  | 367 | count++; | 
|  | 368 | // Don't put the functional version on the queue since we can't | 
|  | 369 | // remove the "running" PNOR version if it allows multiple PNORs | 
|  | 370 | // But removing functional version if there is only one PNOR. | 
|  | 371 | if (ACTIVE_PNOR_MAX_ALLOWED > 1 && | 
|  | 372 | isVersionFunctional(iter.second->versionId)) | 
|  | 373 | { | 
|  | 374 | continue; | 
|  | 375 | } | 
|  | 376 | versionsPQ.push(std::make_pair( | 
|  | 377 | iter.second->redundancyPriority.get()->priority(), | 
|  | 378 | iter.second->versionId)); | 
|  | 379 | } | 
|  | 380 | } | 
|  | 381 |  | 
|  | 382 | // If the number of PNOR versions is over ACTIVE_PNOR_MAX_ALLOWED -1, | 
|  | 383 | // remove the highest priority one(s). | 
|  | 384 | while ((count >= ACTIVE_PNOR_MAX_ALLOWED) && (!versionsPQ.empty())) | 
|  | 385 | { | 
|  | 386 | erase(versionsPQ.top().second); | 
|  | 387 | versionsPQ.pop(); | 
|  | 388 | count--; | 
| Lei YU | 6da3dae | 2019-02-28 14:26:37 +0800 | [diff] [blame] | 389 | isSpaceFreed = true; | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 390 | } | 
| Lei YU | 6da3dae | 2019-02-28 14:26:37 +0800 | [diff] [blame] | 391 | return isSpaceFreed; | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 392 | } | 
|  | 393 |  | 
| Lei YU | bee5140 | 2019-02-26 11:36:34 +0800 | [diff] [blame] | 394 | std::string ItemUpdaterUbi::determineId(const std::string& symlinkPath) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 395 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 396 | if (!std::filesystem::exists(symlinkPath)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 397 | { | 
|  | 398 | return {}; | 
|  | 399 | } | 
|  | 400 |  | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 401 | auto target = std::filesystem::canonical(symlinkPath).string(); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 402 |  | 
|  | 403 | // check to make sure the target really exists | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 404 | if (!std::filesystem::is_regular_file(target + "/" + PNOR_TOC_FILE)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 405 | { | 
|  | 406 | return {}; | 
|  | 407 | } | 
|  | 408 | // Get the image <id> from the symlink target | 
|  | 409 | // for example /media/ro-2a1022fe | 
|  | 410 | static const auto PNOR_RO_PREFIX_LEN = strlen(PNOR_RO_PREFIX); | 
|  | 411 | return target.substr(PNOR_RO_PREFIX_LEN); | 
|  | 412 | } | 
|  | 413 |  | 
| Lei YU | 716de5b | 2019-03-01 16:03:53 +0800 | [diff] [blame] | 414 | void GardResetUbi::reset() | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 415 | { | 
|  | 416 | // The GARD partition is currently misspelled "GUARD." This file path will | 
|  | 417 | // need to be updated in the future. | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 418 | auto path = std::filesystem::path(PNOR_PRSV_ACTIVE_PATH); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 419 | path /= "GUARD"; | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 420 |  | 
| Lei YU | e499446 | 2019-03-14 14:41:53 +0800 | [diff] [blame] | 421 | utils::hiomapdSuspend(bus); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 422 |  | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 423 | if (std::filesystem::is_regular_file(path)) | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 424 | { | 
| Brad Bishop | 9f44c99 | 2020-11-06 14:48:46 -0500 | [diff] [blame] | 425 | std::filesystem::remove(path); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 426 | } | 
|  | 427 |  | 
| Lei YU | e499446 | 2019-03-14 14:41:53 +0800 | [diff] [blame] | 428 | utils::hiomapdResume(bus); | 
| Lei YU | f3ce433 | 2019-02-21 14:09:49 +0800 | [diff] [blame] | 429 | } | 
|  | 430 |  | 
|  | 431 | } // namespace updater | 
|  | 432 | } // namespace software | 
|  | 433 | } // namespace openpower |