1b0ce996aSGunnar Mills #include "config.h" 2b0ce996aSGunnar Mills 3b0ce996aSGunnar Mills #include "item_updater.hpp" 4b0ce996aSGunnar Mills 5b0ce996aSGunnar Mills #include "images.hpp" 6b0ce996aSGunnar Mills #include "serialize.hpp" 7b0ce996aSGunnar Mills #include "version.hpp" 81fd6dddfSChanh Nguyen #include "xyz/openbmc_project/Software/ExtendedVersion/server.hpp" 9b0ce996aSGunnar Mills #include "xyz/openbmc_project/Software/Version/server.hpp" 10b0ce996aSGunnar Mills 11d5b8f75cSAdriana Kobylak #include <phosphor-logging/elog-errors.hpp> 12b0ce996aSGunnar Mills #include <phosphor-logging/elog.hpp> 13c9bb6425SPatrick Williams #include <phosphor-logging/lg2.hpp> 1458aa7508SAdriana Kobylak #include <xyz/openbmc_project/Common/error.hpp> 1558aa7508SAdriana Kobylak #include <xyz/openbmc_project/Software/Image/error.hpp> 1658aa7508SAdriana Kobylak 1758aa7508SAdriana Kobylak #include <filesystem> 1858aa7508SAdriana Kobylak #include <fstream> 19204e1e74SAdriana Kobylak #include <queue> 20b77551cdSAdriana Kobylak #include <set> 21ec1b41c4SGunnar Mills #include <string> 22ec1b41c4SGunnar Mills 23ec1b41c4SGunnar Mills namespace phosphor 24ec1b41c4SGunnar Mills { 25ec1b41c4SGunnar Mills namespace software 26ec1b41c4SGunnar Mills { 27ec1b41c4SGunnar Mills namespace updater 28ec1b41c4SGunnar Mills { 29ec1b41c4SGunnar Mills 302ce7da29SGunnar Mills // When you see server:: you know we're referencing our base class 312ce7da29SGunnar Mills namespace server = sdbusplus::xyz::openbmc_project::Software::server; 320129d926SMichael Tritz namespace control = sdbusplus::xyz::openbmc_project::Control::server; 332ce7da29SGunnar Mills 34c9bb6425SPatrick Williams PHOSPHOR_LOG2_USING; 352ce7da29SGunnar Mills using namespace phosphor::logging; 3643699ca7SAdriana Kobylak using namespace sdbusplus::xyz::openbmc_project::Software::Image::Error; 372ab9b109SJayanth Othayoth using namespace phosphor::software::image; 38c98d912eSAdriana Kobylak namespace fs = std::filesystem; 39d5b8f75cSAdriana Kobylak using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 4035e83f3eSSaqib Khan 41e75d10f5SPatrick Williams void ItemUpdater::createActivation(sdbusplus::message::message& msg) 42ec1b41c4SGunnar Mills { 4384a0e693SSaqib Khan 4484a0e693SSaqib Khan using SVersion = server::Version; 4584a0e693SSaqib Khan using VersionPurpose = SVersion::VersionPurpose; 469a782243SGunnar Mills using VersionClass = phosphor::software::manager::Version; 4784a0e693SSaqib Khan 48bc1facd7SPatrick Williams sdbusplus::message::object_path objPath; 4984a0e693SSaqib Khan auto purpose = VersionPurpose::Unknown; 501fd6dddfSChanh Nguyen std::string extendedVersion; 51705f1bfcSSaqib Khan std::string version; 52bc1facd7SPatrick Williams std::map<std::string, std::map<std::string, std::variant<std::string>>> 532285fe0fSAdriana Kobylak interfaces; 54e75d10f5SPatrick Williams msg.read(objPath, interfaces); 552ce7da29SGunnar Mills std::string path(std::move(objPath)); 5619177d3eSSaqib Khan std::string filePath; 572ce7da29SGunnar Mills 582ce7da29SGunnar Mills for (const auto& intf : interfaces) 592ce7da29SGunnar Mills { 60705f1bfcSSaqib Khan if (intf.first == VERSION_IFACE) 612ce7da29SGunnar Mills { 622ce7da29SGunnar Mills for (const auto& property : intf.second) 632ce7da29SGunnar Mills { 64705f1bfcSSaqib Khan if (property.first == "Purpose") 652ce7da29SGunnar Mills { 6684a0e693SSaqib Khan auto value = SVersion::convertVersionPurposeFromString( 67e883fb8bSPatrick Williams std::get<std::string>(property.second)); 6884a0e693SSaqib Khan if (value == VersionPurpose::BMC || 69e9f6c845SVijay Khemka #ifdef HOST_BIOS_UPGRADE 70e9f6c845SVijay Khemka value == VersionPurpose::Host || 71e9f6c845SVijay Khemka #endif 7284a0e693SSaqib Khan value == VersionPurpose::System) 7384a0e693SSaqib Khan { 7484a0e693SSaqib Khan purpose = value; 7584a0e693SSaqib Khan } 76705f1bfcSSaqib Khan } 77705f1bfcSSaqib Khan else if (property.first == "Version") 78705f1bfcSSaqib Khan { 79e883fb8bSPatrick Williams version = std::get<std::string>(property.second); 80705f1bfcSSaqib Khan } 81705f1bfcSSaqib Khan } 82705f1bfcSSaqib Khan } 8319177d3eSSaqib Khan else if (intf.first == FILEPATH_IFACE) 8419177d3eSSaqib Khan { 8519177d3eSSaqib Khan for (const auto& property : intf.second) 8619177d3eSSaqib Khan { 8719177d3eSSaqib Khan if (property.first == "Path") 8819177d3eSSaqib Khan { 89e883fb8bSPatrick Williams filePath = std::get<std::string>(property.second); 9019177d3eSSaqib Khan } 9119177d3eSSaqib Khan } 9219177d3eSSaqib Khan } 931fd6dddfSChanh Nguyen else if (intf.first == EXTENDED_VERSION_IFACE) 941fd6dddfSChanh Nguyen { 951fd6dddfSChanh Nguyen for (const auto& property : intf.second) 961fd6dddfSChanh Nguyen { 971fd6dddfSChanh Nguyen if (property.first == "ExtendedVersion") 981fd6dddfSChanh Nguyen { 991fd6dddfSChanh Nguyen extendedVersion = std::get<std::string>(property.second); 1001fd6dddfSChanh Nguyen } 1011fd6dddfSChanh Nguyen } 1021fd6dddfSChanh Nguyen } 103705f1bfcSSaqib Khan } 1042285fe0fSAdriana Kobylak if (version.empty() || filePath.empty() || 10584a0e693SSaqib Khan purpose == VersionPurpose::Unknown) 1062ce7da29SGunnar Mills { 107e75d10f5SPatrick Williams return; 1082ce7da29SGunnar Mills } 1092ce7da29SGunnar Mills 1102ce7da29SGunnar Mills // Version id is the last item in the path 1112ce7da29SGunnar Mills auto pos = path.rfind("/"); 1122ce7da29SGunnar Mills if (pos == std::string::npos) 1132ce7da29SGunnar Mills { 114c9bb6425SPatrick Williams error("No version id found in object path: {PATH}", "PATH", path); 115e75d10f5SPatrick Williams return; 1162ce7da29SGunnar Mills } 1172ce7da29SGunnar Mills 1182ce7da29SGunnar Mills auto versionId = path.substr(pos + 1); 1192ce7da29SGunnar Mills 120e75d10f5SPatrick Williams if (activations.find(versionId) == activations.end()) 1212ce7da29SGunnar Mills { 12235e83f3eSSaqib Khan // Determine the Activation state by processing the given image dir. 12335e83f3eSSaqib Khan auto activationState = server::Activation::Activations::Invalid; 124e9f6c845SVijay Khemka ItemUpdater::ActivationStatus result; 125e9f6c845SVijay Khemka if (purpose == VersionPurpose::BMC || purpose == VersionPurpose::System) 126e9f6c845SVijay Khemka result = ItemUpdater::validateSquashFSImage(filePath); 127e9f6c845SVijay Khemka else 128e9f6c845SVijay Khemka result = ItemUpdater::ActivationStatus::ready; 129e9f6c845SVijay Khemka 13043b25cdeSGunnar Mills AssociationList associations = {}; 13143b25cdeSGunnar Mills 13235e83f3eSSaqib Khan if (result == ItemUpdater::ActivationStatus::ready) 13335e83f3eSSaqib Khan { 13435e83f3eSSaqib Khan activationState = server::Activation::Activations::Ready; 135b60add1eSGunnar Mills // Create an association to the BMC inventory item 1362285fe0fSAdriana Kobylak associations.emplace_back( 1372285fe0fSAdriana Kobylak std::make_tuple(ACTIVATION_FWD_ASSOCIATION, 1382285fe0fSAdriana Kobylak ACTIVATION_REV_ASSOCIATION, bmcInventoryPath)); 13943b25cdeSGunnar Mills } 140b60add1eSGunnar Mills 141ee13e831SSaqib Khan auto versionPtr = std::make_unique<VersionClass>( 1421fd6dddfSChanh Nguyen bus, path, version, purpose, extendedVersion, filePath, 14359b640b0SAdriana Kobylak std::bind(&ItemUpdater::erase, this, std::placeholders::_1), 14459b640b0SAdriana Kobylak versionId); 145ee13e831SSaqib Khan versionPtr->deleteObject = 1462285fe0fSAdriana Kobylak std::make_unique<phosphor::software::manager::Delete>(bus, path, 1472285fe0fSAdriana Kobylak *versionPtr); 148ee13e831SSaqib Khan versions.insert(std::make_pair(versionId, std::move(versionPtr))); 14988ba1f9eSAdriana Kobylak 15088ba1f9eSAdriana Kobylak activations.insert(std::make_pair( 15188ba1f9eSAdriana Kobylak versionId, 15288ba1f9eSAdriana Kobylak std::make_unique<Activation>(bus, path, *this, versionId, 15388ba1f9eSAdriana Kobylak activationState, associations))); 1542ce7da29SGunnar Mills } 155e75d10f5SPatrick Williams return; 156ec1b41c4SGunnar Mills } 157ec1b41c4SGunnar Mills 158ba239881SSaqib Khan void ItemUpdater::processBMCImage() 159ba239881SSaqib Khan { 16088e8a325SGunnar Mills using VersionClass = phosphor::software::manager::Version; 161269bff30SLei YU 162269bff30SLei YU // Check MEDIA_DIR and create if it does not exist 163269bff30SLei YU try 164269bff30SLei YU { 165269bff30SLei YU if (!fs::is_directory(MEDIA_DIR)) 166269bff30SLei YU { 167269bff30SLei YU fs::create_directory(MEDIA_DIR); 168269bff30SLei YU } 169269bff30SLei YU } 170269bff30SLei YU catch (const fs::filesystem_error& e) 171269bff30SLei YU { 172c9bb6425SPatrick Williams error("Failed to prepare dir: {ERROR}", "ERROR", e); 173269bff30SLei YU return; 174269bff30SLei YU } 175269bff30SLei YU 1761e81f23cSAdriana Kobylak // Functional images are mounted as rofs-<location>-functional 1771e81f23cSAdriana Kobylak constexpr auto functionalSuffix = "-functional"; 178d474d9cdSLei YU bool functionalFound = false; 17988e8a325SGunnar Mills 1801eef62deSSaqib Khan // Read os-release from folders under /media/ to get 1811eef62deSSaqib Khan // BMC Software Versions. 1821eef62deSSaqib Khan for (const auto& iter : fs::directory_iterator(MEDIA_DIR)) 1831eef62deSSaqib Khan { 1841eef62deSSaqib Khan auto activationState = server::Activation::Activations::Active; 1856fab70daSSaqib Khan static const auto BMC_RO_PREFIX_LEN = strlen(BMC_ROFS_PREFIX); 1861eef62deSSaqib Khan 1871eef62deSSaqib Khan // Check if the BMC_RO_PREFIXis the prefix of the iter.path 1882285fe0fSAdriana Kobylak if (0 == 1892285fe0fSAdriana Kobylak iter.path().native().compare(0, BMC_RO_PREFIX_LEN, BMC_ROFS_PREFIX)) 1901eef62deSSaqib Khan { 191716cd78dSAdriana Kobylak // Get the version to calculate the id 19224a8d83dSAdriana Kobylak fs::path releaseFile(OS_RELEASE_FILE); 19324a8d83dSAdriana Kobylak auto osRelease = iter.path() / releaseFile.relative_path(); 1941eef62deSSaqib Khan if (!fs::is_regular_file(osRelease)) 1951eef62deSSaqib Khan { 196e56bf878SLei YU #ifdef BMC_STATIC_DUAL_IMAGE 197e56bf878SLei YU // For dual image, it is possible that the secondary image is 198e56bf878SLei YU // empty or contains invalid data, ignore such case. 199e56bf878SLei YU info("Unable to find osRelease: {PATH}", "PATH", osRelease); 200e56bf878SLei YU #else 201c9bb6425SPatrick Williams error("Failed to read osRelease: {PATH}", "PATH", osRelease); 202716cd78dSAdriana Kobylak 203716cd78dSAdriana Kobylak // Try to get the version id from the mount directory name and 204716cd78dSAdriana Kobylak // call to delete it as this version may be corrupted. Dynamic 205716cd78dSAdriana Kobylak // volumes created by the UBI layout for example have the id in 206716cd78dSAdriana Kobylak // the mount directory name. The worst that can happen is that 207716cd78dSAdriana Kobylak // erase() is called with an non-existent id and returns. 208716cd78dSAdriana Kobylak auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN); 209021c365bSSaqib Khan ItemUpdater::erase(id); 210e56bf878SLei YU #endif 211716cd78dSAdriana Kobylak 212021c365bSSaqib Khan continue; 2131eef62deSSaqib Khan } 21488e8a325SGunnar Mills auto version = VersionClass::getBMCVersion(osRelease); 2151eef62deSSaqib Khan if (version.empty()) 2161eef62deSSaqib Khan { 217c9bb6425SPatrick Williams error("Failed to read version from osRelease: {PATH}", "PATH", 218c9bb6425SPatrick Williams osRelease); 219716cd78dSAdriana Kobylak 220716cd78dSAdriana Kobylak // Try to delete the version, same as above if the 221716cd78dSAdriana Kobylak // OS_RELEASE_FILE does not exist. 222716cd78dSAdriana Kobylak auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN); 223716cd78dSAdriana Kobylak ItemUpdater::erase(id); 224716cd78dSAdriana Kobylak 225716cd78dSAdriana Kobylak continue; 2261eef62deSSaqib Khan } 227021c365bSSaqib Khan 22859b640b0SAdriana Kobylak // The flash location is part of the mount name: rofs-<location> 22959b640b0SAdriana Kobylak auto flashId = iter.path().native().substr(BMC_RO_PREFIX_LEN); 23059b640b0SAdriana Kobylak 23159b640b0SAdriana Kobylak auto id = VersionClass::getId(version + flashId); 232716cd78dSAdriana Kobylak 233f383d27aSAdriana Kobylak // Check if the id has already been added. This can happen if the 234f383d27aSAdriana Kobylak // BMC partitions / devices were manually flashed with the same 235f383d27aSAdriana Kobylak // image. 236f383d27aSAdriana Kobylak if (versions.find(id) != versions.end()) 237f383d27aSAdriana Kobylak { 238f383d27aSAdriana Kobylak continue; 239f383d27aSAdriana Kobylak } 240f383d27aSAdriana Kobylak 2411e81f23cSAdriana Kobylak auto functional = false; 2421e81f23cSAdriana Kobylak if (iter.path().native().find(functionalSuffix) != 2431e81f23cSAdriana Kobylak std::string::npos) 2441e81f23cSAdriana Kobylak { 2451e81f23cSAdriana Kobylak // Set functional to true and remove the functional suffix 2461e81f23cSAdriana Kobylak functional = true; 2471e81f23cSAdriana Kobylak flashId.erase(flashId.length() - strlen(functionalSuffix)); 248d474d9cdSLei YU functionalFound = true; 2491e81f23cSAdriana Kobylak } 250780220f2SAdriana Kobylak 2511eef62deSSaqib Khan auto purpose = server::Version::VersionPurpose::BMC; 252780220f2SAdriana Kobylak restorePurpose(flashId, purpose); 253ec4eec34SAdriana Kobylak 2541fd6dddfSChanh Nguyen // Read os-release from /etc/ to get the BMC extended version 2551fd6dddfSChanh Nguyen std::string extendedVersion = 2561fd6dddfSChanh Nguyen VersionClass::getBMCExtendedVersion(osRelease); 2571fd6dddfSChanh Nguyen 2581eef62deSSaqib Khan auto path = fs::path(SOFTWARE_OBJPATH) / id; 2591eef62deSSaqib Khan 260269bff30SLei YU // Create functional association if this is the functional 261269bff30SLei YU // version 2621e81f23cSAdriana Kobylak if (functional) 26388e8a325SGunnar Mills { 26488e8a325SGunnar Mills createFunctionalAssociation(path); 26588e8a325SGunnar Mills } 26688e8a325SGunnar Mills 26743b25cdeSGunnar Mills AssociationList associations = {}; 26843b25cdeSGunnar Mills 26943b25cdeSGunnar Mills if (activationState == server::Activation::Activations::Active) 27043b25cdeSGunnar Mills { 27143b25cdeSGunnar Mills // Create an association to the BMC inventory item 27243b25cdeSGunnar Mills associations.emplace_back(std::make_tuple( 2732285fe0fSAdriana Kobylak ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION, 27443b25cdeSGunnar Mills bmcInventoryPath)); 27543b25cdeSGunnar Mills 27643b25cdeSGunnar Mills // Create an active association since this image is active 27743b25cdeSGunnar Mills createActiveAssociation(path); 27843b25cdeSGunnar Mills } 27943b25cdeSGunnar Mills 280bbebec79SAppaRao Puli // All updateable firmware components must expose the updateable 281bbebec79SAppaRao Puli // association. 282bbebec79SAppaRao Puli createUpdateableAssociation(path); 283bbebec79SAppaRao Puli 284ee590c74SAdriana Kobylak // Create Version instance for this version. 285ee590c74SAdriana Kobylak auto versionPtr = std::make_unique<VersionClass>( 286a84f06d2SAdriana Kobylak bus, path, version, purpose, extendedVersion, flashId, 28759b640b0SAdriana Kobylak std::bind(&ItemUpdater::erase, this, std::placeholders::_1), 28859b640b0SAdriana Kobylak id); 2891e81f23cSAdriana Kobylak if (functional) 2901e81f23cSAdriana Kobylak { 2911e81f23cSAdriana Kobylak versionPtr->setFunctional(true); 2921e81f23cSAdriana Kobylak } 2931e81f23cSAdriana Kobylak else 294ee13e831SSaqib Khan { 295ee13e831SSaqib Khan versionPtr->deleteObject = 296ee13e831SSaqib Khan std::make_unique<phosphor::software::manager::Delete>( 297ee13e831SSaqib Khan bus, path, *versionPtr); 298ee13e831SSaqib Khan } 2992285fe0fSAdriana Kobylak versions.insert(std::make_pair(id, std::move(versionPtr))); 300ee590c74SAdriana Kobylak 3011eef62deSSaqib Khan // Create Activation instance for this version. 302ee13e831SSaqib Khan activations.insert(std::make_pair( 3032285fe0fSAdriana Kobylak id, std::make_unique<Activation>( 3042285fe0fSAdriana Kobylak bus, path, *this, id, activationState, associations))); 3051eef62deSSaqib Khan 306bdf2d6ceSLei YU #ifdef BMC_STATIC_DUAL_IMAGE 307bdf2d6ceSLei YU uint8_t priority; 308bdf2d6ceSLei YU if ((functional && (runningImageSlot == 0)) || 309bdf2d6ceSLei YU (!functional && (runningImageSlot == 1))) 310bdf2d6ceSLei YU { 311bdf2d6ceSLei YU priority = 0; 312bdf2d6ceSLei YU } 313bdf2d6ceSLei YU else 314bdf2d6ceSLei YU { 315bdf2d6ceSLei YU priority = 1; 316bdf2d6ceSLei YU } 317bdf2d6ceSLei YU activations.find(id)->second->redundancyPriority = 318bdf2d6ceSLei YU std::make_unique<RedundancyPriority>( 319bdf2d6ceSLei YU bus, path, *(activations.find(id)->second), priority, 320bdf2d6ceSLei YU false); 321bdf2d6ceSLei YU #else 322269bff30SLei YU // If Active, create RedundancyPriority instance for this 323269bff30SLei YU // version. 3241eef62deSSaqib Khan if (activationState == server::Activation::Activations::Active) 3251eef62deSSaqib Khan { 3261eef62deSSaqib Khan uint8_t priority = std::numeric_limits<uint8_t>::max(); 327780220f2SAdriana Kobylak if (!restorePriority(flashId, priority)) 3281eef62deSSaqib Khan { 3291e81f23cSAdriana Kobylak if (functional) 330ee590c74SAdriana Kobylak { 331ee590c74SAdriana Kobylak priority = 0; 332ee590c74SAdriana Kobylak } 333ee590c74SAdriana Kobylak else 334ee590c74SAdriana Kobylak { 335c9bb6425SPatrick Williams error( 336c9bb6425SPatrick Williams "Unable to restore priority from file for {VERSIONID}", 337c9bb6425SPatrick Williams "VERSIONID", id); 3381eef62deSSaqib Khan } 339ee590c74SAdriana Kobylak } 3401eef62deSSaqib Khan activations.find(id)->second->redundancyPriority = 3411eef62deSSaqib Khan std::make_unique<RedundancyPriority>( 3422285fe0fSAdriana Kobylak bus, path, *(activations.find(id)->second), priority, 343b77551cdSAdriana Kobylak false); 3441eef62deSSaqib Khan } 345bdf2d6ceSLei YU #endif 3461eef62deSSaqib Khan } 3471eef62deSSaqib Khan } 348dcbfa04aSSaqib Khan 349d474d9cdSLei YU if (!functionalFound) 350dcbfa04aSSaqib Khan { 351d474d9cdSLei YU // If there is no functional version found, read the /etc/os-release and 352d474d9cdSLei YU // create rofs-<versionId>-functional under MEDIA_DIR, then call again 353d474d9cdSLei YU // processBMCImage() to create the D-Bus interface for it. 354d16bcbd5SGunnar Mills auto version = VersionClass::getBMCVersion(OS_RELEASE_FILE); 35559b640b0SAdriana Kobylak auto id = phosphor::software::manager::Version::getId(version + 35659b640b0SAdriana Kobylak functionalSuffix); 3571e81f23cSAdriana Kobylak auto versionFileDir = BMC_ROFS_PREFIX + id + functionalSuffix + "/etc/"; 358dcbfa04aSSaqib Khan try 359dcbfa04aSSaqib Khan { 360dcbfa04aSSaqib Khan if (!fs::is_directory(versionFileDir)) 361dcbfa04aSSaqib Khan { 362dcbfa04aSSaqib Khan fs::create_directories(versionFileDir); 363dcbfa04aSSaqib Khan } 3641e81f23cSAdriana Kobylak auto versionFilePath = 3651e81f23cSAdriana Kobylak BMC_ROFS_PREFIX + id + functionalSuffix + OS_RELEASE_FILE; 366dcbfa04aSSaqib Khan fs::create_directory_symlink(OS_RELEASE_FILE, versionFilePath); 367dcbfa04aSSaqib Khan ItemUpdater::processBMCImage(); 368dcbfa04aSSaqib Khan } 369dcbfa04aSSaqib Khan catch (const std::exception& e) 370dcbfa04aSSaqib Khan { 371c9bb6425SPatrick Williams error("Exception during processing: {ERROR}", "ERROR", e); 372dcbfa04aSSaqib Khan } 373dcbfa04aSSaqib Khan } 374eaa1ee05SEddie James 375eaa1ee05SEddie James mirrorUbootToAlt(); 376ba239881SSaqib Khan return; 377ba239881SSaqib Khan } 378ba239881SSaqib Khan 3793526ef73SLeonel Gonzalez void ItemUpdater::erase(std::string entryId) 3803526ef73SLeonel Gonzalez { 3816d873715SEddie James // Find entry in versions map 3826d873715SEddie James auto it = versions.find(entryId); 3836d873715SEddie James if (it != versions.end()) 3846d873715SEddie James { 3850f88b5afSLei YU if (it->second->isFunctional() && ACTIVE_BMC_MAX_ALLOWED > 1) 3866d873715SEddie James { 387c9bb6425SPatrick Williams error( 388c9bb6425SPatrick Williams "Version ({VERSIONID}) is currently running on the BMC; unable to remove.", 389c9bb6425SPatrick Williams "VERSIONID", entryId); 3906d873715SEddie James return; 3916d873715SEddie James } 392d1a55adcSAdriana Kobylak } 3936d873715SEddie James 394d1a55adcSAdriana Kobylak // First call resetUbootEnvVars() so that the BMC points to a valid image to 395d1a55adcSAdriana Kobylak // boot from. If resetUbootEnvVars() is called after the image is actually 396d1a55adcSAdriana Kobylak // deleted from the BMC flash, there'd be a time window where the BMC would 397d1a55adcSAdriana Kobylak // be pointing to a non-existent image to boot from. 398d1a55adcSAdriana Kobylak // Need to remove the entries from the activations map before that call so 399d1a55adcSAdriana Kobylak // that resetUbootEnvVars() doesn't use the version to be deleted. 400d1a55adcSAdriana Kobylak auto iteratorActivations = activations.find(entryId); 401d1a55adcSAdriana Kobylak if (iteratorActivations == activations.end()) 402d1a55adcSAdriana Kobylak { 403c9bb6425SPatrick Williams error( 404c9bb6425SPatrick Williams "Failed to find version ({VERSIONID}) in item updater activations map; unable to remove.", 405c9bb6425SPatrick Williams "VERSIONID", entryId); 406d1a55adcSAdriana Kobylak } 407d1a55adcSAdriana Kobylak else 408d1a55adcSAdriana Kobylak { 409d1a55adcSAdriana Kobylak removeAssociations(iteratorActivations->second->path); 410ae06d76aSZami Seck iteratorActivations->second->deleteImageManagerObject(); 411d1a55adcSAdriana Kobylak this->activations.erase(entryId); 412d1a55adcSAdriana Kobylak } 413d1a55adcSAdriana Kobylak ItemUpdater::resetUbootEnvVars(); 414d1a55adcSAdriana Kobylak 415d1a55adcSAdriana Kobylak if (it != versions.end()) 416d1a55adcSAdriana Kobylak { 417780220f2SAdriana Kobylak auto flashId = it->second->path(); 418780220f2SAdriana Kobylak 41925773a7eSAdriana Kobylak // Delete version data if it has been installed on flash (path is not 42025773a7eSAdriana Kobylak // the upload directory) 42125773a7eSAdriana Kobylak if (flashId.find(IMG_UPLOAD_DIR) == std::string::npos) 42225773a7eSAdriana Kobylak { 4233526ef73SLeonel Gonzalez removeReadOnlyPartition(entryId); 424780220f2SAdriana Kobylak removePersistDataDirectory(flashId); 42525773a7eSAdriana Kobylak helper.clearEntry(flashId); 42625773a7eSAdriana Kobylak } 427ee13e831SSaqib Khan 428ee13e831SSaqib Khan // Removing entry in versions map 429ee13e831SSaqib Khan this->versions.erase(entryId); 4306d873715SEddie James } 4313526ef73SLeonel Gonzalez 432ee13e831SSaqib Khan return; 4333526ef73SLeonel Gonzalez } 4343526ef73SLeonel Gonzalez 435bc1bf3afSMichael Tritz void ItemUpdater::deleteAll() 436bc1bf3afSMichael Tritz { 43783cd21fbSAdriana Kobylak std::vector<std::string> deletableVersions; 43883cd21fbSAdriana Kobylak 439bc1bf3afSMichael Tritz for (const auto& versionIt : versions) 440bc1bf3afSMichael Tritz { 441bc1bf3afSMichael Tritz if (!versionIt.second->isFunctional()) 442bc1bf3afSMichael Tritz { 44383cd21fbSAdriana Kobylak deletableVersions.push_back(versionIt.first); 444bc1bf3afSMichael Tritz } 445bc1bf3afSMichael Tritz } 446bc1bf3afSMichael Tritz 44783cd21fbSAdriana Kobylak for (const auto& deletableIt : deletableVersions) 44883cd21fbSAdriana Kobylak { 44983cd21fbSAdriana Kobylak ItemUpdater::erase(deletableIt); 45083cd21fbSAdriana Kobylak } 45183cd21fbSAdriana Kobylak 45256aaf454SLei YU helper.cleanup(); 453bc1bf3afSMichael Tritz } 454bc1bf3afSMichael Tritz 4552285fe0fSAdriana Kobylak ItemUpdater::ActivationStatus 4562285fe0fSAdriana Kobylak ItemUpdater::validateSquashFSImage(const std::string& filePath) 45735e83f3eSSaqib Khan { 4588e9ccfe7SBright Cheng bool valid = true; 45935e83f3eSSaqib Khan 4608e9ccfe7SBright Cheng // Record the images which are being updated 4618e9ccfe7SBright Cheng // First check for the fullimage, then check for images with partitions 4628e9ccfe7SBright Cheng imageUpdateList.push_back(bmcFullImages); 4638e9ccfe7SBright Cheng valid = checkImage(filePath, imageUpdateList); 4648e9ccfe7SBright Cheng if (!valid) 465b1cfdf99SMichael Tritz { 4668e9ccfe7SBright Cheng imageUpdateList.clear(); 4678e9ccfe7SBright Cheng imageUpdateList.assign(bmcImages.begin(), bmcImages.end()); 4688e9ccfe7SBright Cheng valid = checkImage(filePath, imageUpdateList); 4698e9ccfe7SBright Cheng if (!valid) 47035e83f3eSSaqib Khan { 471c9bb6425SPatrick Williams error("Failed to find the needed BMC images."); 47235e83f3eSSaqib Khan return ItemUpdater::ActivationStatus::invalid; 47335e83f3eSSaqib Khan } 4748e9ccfe7SBright Cheng } 475b1cfdf99SMichael Tritz 476b1cfdf99SMichael Tritz return ItemUpdater::ActivationStatus::ready; 47735e83f3eSSaqib Khan } 47835e83f3eSSaqib Khan 479bbcb7be1SAdriana Kobylak void ItemUpdater::savePriority(const std::string& versionId, uint8_t value) 480bbcb7be1SAdriana Kobylak { 481780220f2SAdriana Kobylak auto flashId = versions.find(versionId)->second->path(); 482780220f2SAdriana Kobylak storePriority(flashId, value); 48325773a7eSAdriana Kobylak helper.setEntry(flashId, value); 484bbcb7be1SAdriana Kobylak } 485bbcb7be1SAdriana Kobylak 486b9da6634SSaqib Khan void ItemUpdater::freePriority(uint8_t value, const std::string& versionId) 4874c1aec09SSaqib Khan { 488b77551cdSAdriana Kobylak std::map<std::string, uint8_t> priorityMap; 489b77551cdSAdriana Kobylak 490b77551cdSAdriana Kobylak // Insert the requested version and priority, it may not exist yet. 491b77551cdSAdriana Kobylak priorityMap.insert(std::make_pair(versionId, value)); 492b77551cdSAdriana Kobylak 4934c1aec09SSaqib Khan for (const auto& intf : activations) 4944c1aec09SSaqib Khan { 4954c1aec09SSaqib Khan if (intf.second->redundancyPriority) 4964c1aec09SSaqib Khan { 497b77551cdSAdriana Kobylak priorityMap.insert(std::make_pair( 4982285fe0fSAdriana Kobylak intf.first, intf.second->redundancyPriority.get()->priority())); 499b77551cdSAdriana Kobylak } 500b77551cdSAdriana Kobylak } 501b77551cdSAdriana Kobylak 502b77551cdSAdriana Kobylak // Lambda function to compare 2 priority values, use <= to allow duplicates 5032285fe0fSAdriana Kobylak typedef std::function<bool(std::pair<std::string, uint8_t>, 5042285fe0fSAdriana Kobylak std::pair<std::string, uint8_t>)> 5052285fe0fSAdriana Kobylak cmpPriority; 5062285fe0fSAdriana Kobylak cmpPriority cmpPriorityFunc = 5072285fe0fSAdriana Kobylak [](std::pair<std::string, uint8_t> priority1, 5082285fe0fSAdriana Kobylak std::pair<std::string, uint8_t> priority2) { 509b77551cdSAdriana Kobylak return priority1.second <= priority2.second; 510b77551cdSAdriana Kobylak }; 511b77551cdSAdriana Kobylak 512b77551cdSAdriana Kobylak // Sort versions by ascending priority 513b77551cdSAdriana Kobylak std::set<std::pair<std::string, uint8_t>, cmpPriority> prioritySet( 514b77551cdSAdriana Kobylak priorityMap.begin(), priorityMap.end(), cmpPriorityFunc); 515b77551cdSAdriana Kobylak 516b77551cdSAdriana Kobylak auto freePriorityValue = value; 517b77551cdSAdriana Kobylak for (auto& element : prioritySet) 518b77551cdSAdriana Kobylak { 519b77551cdSAdriana Kobylak if (element.first == versionId) 520b77551cdSAdriana Kobylak { 521b77551cdSAdriana Kobylak continue; 522b77551cdSAdriana Kobylak } 523b77551cdSAdriana Kobylak if (element.second == freePriorityValue) 524b77551cdSAdriana Kobylak { 525b77551cdSAdriana Kobylak ++freePriorityValue; 526b77551cdSAdriana Kobylak auto it = activations.find(element.first); 527b77551cdSAdriana Kobylak it->second->redundancyPriority.get()->sdbusPriority( 528b77551cdSAdriana Kobylak freePriorityValue); 5294c1aec09SSaqib Khan } 5304c1aec09SSaqib Khan } 531b77551cdSAdriana Kobylak 532b77551cdSAdriana Kobylak auto lowestVersion = prioritySet.begin()->first; 533b77551cdSAdriana Kobylak if (value == prioritySet.begin()->second) 534b77551cdSAdriana Kobylak { 535b77551cdSAdriana Kobylak lowestVersion = versionId; 5364c1aec09SSaqib Khan } 537b77551cdSAdriana Kobylak updateUbootEnvVars(lowestVersion); 5384c1aec09SSaqib Khan } 5394c1aec09SSaqib Khan 54037a59043SMichael Tritz void ItemUpdater::reset() 54137a59043SMichael Tritz { 54256aaf454SLei YU helper.factoryReset(); 54337a59043SMichael Tritz 544c9bb6425SPatrick Williams info("BMC factory reset will take effect upon reboot."); 54537a59043SMichael Tritz } 54637a59043SMichael Tritz 5473526ef73SLeonel Gonzalez void ItemUpdater::removeReadOnlyPartition(std::string versionId) 5483526ef73SLeonel Gonzalez { 54925773a7eSAdriana Kobylak auto flashId = versions.find(versionId)->second->path(); 55025773a7eSAdriana Kobylak helper.removeVersion(flashId); 5513526ef73SLeonel Gonzalez } 5523526ef73SLeonel Gonzalez 5530129d926SMichael Tritz bool ItemUpdater::fieldModeEnabled(bool value) 5540129d926SMichael Tritz { 5550129d926SMichael Tritz // enabling field mode is intended to be one way: false -> true 5560129d926SMichael Tritz if (value && !control::FieldMode::fieldModeEnabled()) 5570129d926SMichael Tritz { 5580129d926SMichael Tritz control::FieldMode::fieldModeEnabled(value); 5590129d926SMichael Tritz 56022848eceSAdriana Kobylak auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 56122848eceSAdriana Kobylak SYSTEMD_INTERFACE, "StartUnit"); 56222848eceSAdriana Kobylak method.append("obmc-flash-bmc-setenv@fieldmode\\x3dtrue.service", 56322848eceSAdriana Kobylak "replace"); 56422848eceSAdriana Kobylak bus.call_noreply(method); 56522848eceSAdriana Kobylak 56622848eceSAdriana Kobylak method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 56722848eceSAdriana Kobylak SYSTEMD_INTERFACE, "StopUnit"); 56822848eceSAdriana Kobylak method.append("usr-local.mount", "replace"); 56922848eceSAdriana Kobylak bus.call_noreply(method); 57022848eceSAdriana Kobylak 57122848eceSAdriana Kobylak std::vector<std::string> usrLocal = {"usr-local.mount"}; 57222848eceSAdriana Kobylak 57322848eceSAdriana Kobylak method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 57422848eceSAdriana Kobylak SYSTEMD_INTERFACE, "MaskUnitFiles"); 57522848eceSAdriana Kobylak method.append(usrLocal, false, true); 57622848eceSAdriana Kobylak bus.call_noreply(method); 5770129d926SMichael Tritz } 578d5b8f75cSAdriana Kobylak else if (!value && control::FieldMode::fieldModeEnabled()) 579d5b8f75cSAdriana Kobylak { 580d5b8f75cSAdriana Kobylak elog<NotAllowed>(xyz::openbmc_project::Common::NotAllowed::REASON( 581d5b8f75cSAdriana Kobylak "FieldMode is not allowed to be cleared")); 582d5b8f75cSAdriana Kobylak } 5830129d926SMichael Tritz 5840129d926SMichael Tritz return control::FieldMode::fieldModeEnabled(); 5850129d926SMichael Tritz } 5860129d926SMichael Tritz 5870129d926SMichael Tritz void ItemUpdater::restoreFieldModeStatus() 5880129d926SMichael Tritz { 589ff0b421dSMichael Tritz std::ifstream input("/dev/mtd/u-boot-env"); 5900129d926SMichael Tritz std::string envVar; 5910129d926SMichael Tritz std::getline(input, envVar); 5920129d926SMichael Tritz 5930129d926SMichael Tritz if (envVar.find("fieldmode=true") != std::string::npos) 5940129d926SMichael Tritz { 5950129d926SMichael Tritz ItemUpdater::fieldModeEnabled(true); 5960129d926SMichael Tritz } 5970129d926SMichael Tritz } 5980129d926SMichael Tritz 599b60add1eSGunnar Mills void ItemUpdater::setBMCInventoryPath() 600b60add1eSGunnar Mills { 601b60add1eSGunnar Mills auto depth = 0; 6022285fe0fSAdriana Kobylak auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, 6032285fe0fSAdriana Kobylak MAPPER_INTERFACE, "GetSubTreePaths"); 604b60add1eSGunnar Mills 6051254c628SAdriana Kobylak mapperCall.append(INVENTORY_PATH); 606b60add1eSGunnar Mills mapperCall.append(depth); 6071254c628SAdriana Kobylak std::vector<std::string> filter = {BMC_INVENTORY_INTERFACE}; 608b60add1eSGunnar Mills mapperCall.append(filter); 609b60add1eSGunnar Mills 61087c78173SEd Tanous try 611b60add1eSGunnar Mills { 61287c78173SEd Tanous auto response = bus.call(mapperCall); 613b60add1eSGunnar Mills 614b60add1eSGunnar Mills using ObjectPaths = std::vector<std::string>; 615b60add1eSGunnar Mills ObjectPaths result; 616b60add1eSGunnar Mills response.read(result); 617b60add1eSGunnar Mills 6181254c628SAdriana Kobylak if (!result.empty()) 619b60add1eSGunnar Mills { 6201254c628SAdriana Kobylak bmcInventoryPath = result.front(); 621b60add1eSGunnar Mills } 62287c78173SEd Tanous } 6234ce901c5SPatrick Williams catch (const sdbusplus::exception::exception& e) 62487c78173SEd Tanous { 625c9bb6425SPatrick Williams error("Error in mapper GetSubTreePath: {ERROR}", "ERROR", e); 62687c78173SEd Tanous return; 62787c78173SEd Tanous } 628b60add1eSGunnar Mills 629b60add1eSGunnar Mills return; 630b60add1eSGunnar Mills } 631b60add1eSGunnar Mills 632f10b2326SGunnar Mills void ItemUpdater::createActiveAssociation(const std::string& path) 633ded875dcSGunnar Mills { 6342285fe0fSAdriana Kobylak assocs.emplace_back( 6352285fe0fSAdriana Kobylak std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path)); 636ded875dcSGunnar Mills associations(assocs); 637ded875dcSGunnar Mills } 638ded875dcSGunnar Mills 63988e8a325SGunnar Mills void ItemUpdater::createFunctionalAssociation(const std::string& path) 64088e8a325SGunnar Mills { 64188e8a325SGunnar Mills assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION, 6422285fe0fSAdriana Kobylak FUNCTIONAL_REV_ASSOCIATION, path)); 64388e8a325SGunnar Mills associations(assocs); 64488e8a325SGunnar Mills } 64588e8a325SGunnar Mills 646bbebec79SAppaRao Puli void ItemUpdater::createUpdateableAssociation(const std::string& path) 647bbebec79SAppaRao Puli { 648bbebec79SAppaRao Puli assocs.emplace_back(std::make_tuple(UPDATEABLE_FWD_ASSOCIATION, 649bbebec79SAppaRao Puli UPDATEABLE_REV_ASSOCIATION, path)); 650bbebec79SAppaRao Puli associations(assocs); 651bbebec79SAppaRao Puli } 652bbebec79SAppaRao Puli 653991af7ecSAdriana Kobylak void ItemUpdater::removeAssociations(const std::string& path) 654ded875dcSGunnar Mills { 655ded875dcSGunnar Mills for (auto iter = assocs.begin(); iter != assocs.end();) 656ded875dcSGunnar Mills { 657991af7ecSAdriana Kobylak if ((std::get<2>(*iter)).compare(path) == 0) 658ded875dcSGunnar Mills { 659ded875dcSGunnar Mills iter = assocs.erase(iter); 660ded875dcSGunnar Mills associations(assocs); 661ded875dcSGunnar Mills } 662ded875dcSGunnar Mills else 663ded875dcSGunnar Mills { 664ded875dcSGunnar Mills ++iter; 665ded875dcSGunnar Mills } 666ded875dcSGunnar Mills } 667ded875dcSGunnar Mills } 668ded875dcSGunnar Mills 669b9da6634SSaqib Khan bool ItemUpdater::isLowestPriority(uint8_t value) 670b9da6634SSaqib Khan { 671b9da6634SSaqib Khan for (const auto& intf : activations) 672b9da6634SSaqib Khan { 673b9da6634SSaqib Khan if (intf.second->redundancyPriority) 674b9da6634SSaqib Khan { 675b9da6634SSaqib Khan if (intf.second->redundancyPriority.get()->priority() < value) 676b9da6634SSaqib Khan { 677b9da6634SSaqib Khan return false; 678b9da6634SSaqib Khan } 679b9da6634SSaqib Khan } 680b9da6634SSaqib Khan } 681b9da6634SSaqib Khan return true; 682b9da6634SSaqib Khan } 683b9da6634SSaqib Khan 684b77551cdSAdriana Kobylak void ItemUpdater::updateUbootEnvVars(const std::string& versionId) 685b77551cdSAdriana Kobylak { 6869c76a0acSLei YU auto it = versions.find(versionId); 6879c76a0acSLei YU if (it == versions.end()) 6889c76a0acSLei YU { 6899c76a0acSLei YU return; 6909c76a0acSLei YU } 6919c76a0acSLei YU auto flashId = it->second->path(); 69225773a7eSAdriana Kobylak helper.updateUbootVersionId(flashId); 693b77551cdSAdriana Kobylak } 694b77551cdSAdriana Kobylak 69549446ae9SSaqib Khan void ItemUpdater::resetUbootEnvVars() 69649446ae9SSaqib Khan { 69749446ae9SSaqib Khan decltype(activations.begin()->second->redundancyPriority.get()->priority()) 69849446ae9SSaqib Khan lowestPriority = std::numeric_limits<uint8_t>::max(); 69949446ae9SSaqib Khan decltype(activations.begin()->second->versionId) lowestPriorityVersion; 70049446ae9SSaqib Khan for (const auto& intf : activations) 70149446ae9SSaqib Khan { 70249446ae9SSaqib Khan if (!intf.second->redundancyPriority.get()) 70349446ae9SSaqib Khan { 70449446ae9SSaqib Khan // Skip this version if the redundancyPriority is not initialized. 70549446ae9SSaqib Khan continue; 70649446ae9SSaqib Khan } 70749446ae9SSaqib Khan 7082285fe0fSAdriana Kobylak if (intf.second->redundancyPriority.get()->priority() <= lowestPriority) 70949446ae9SSaqib Khan { 71049446ae9SSaqib Khan lowestPriority = intf.second->redundancyPriority.get()->priority(); 71149446ae9SSaqib Khan lowestPriorityVersion = intf.second->versionId; 71249446ae9SSaqib Khan } 71349446ae9SSaqib Khan } 71449446ae9SSaqib Khan 715f0382c35SSaqib Khan // Update the U-boot environment variable to point to the lowest priority 716b77551cdSAdriana Kobylak updateUbootEnvVars(lowestPriorityVersion); 71749446ae9SSaqib Khan } 71849446ae9SSaqib Khan 719*d8c9eea3SLei YU void ItemUpdater::freeSpace([[maybe_unused]] const Activation& caller) 720204e1e74SAdriana Kobylak { 721*d8c9eea3SLei YU #ifdef BMC_STATIC_DUAL_IMAGE 722*d8c9eea3SLei YU // For the golden image case, always remove the version on the primary side 723*d8c9eea3SLei YU std::string versionIDtoErase; 724*d8c9eea3SLei YU for (const auto& iter : activations) 725*d8c9eea3SLei YU { 726*d8c9eea3SLei YU if (iter.second->redundancyPriority && 727*d8c9eea3SLei YU iter.second->redundancyPriority.get()->priority() == 0) 728*d8c9eea3SLei YU { 729*d8c9eea3SLei YU versionIDtoErase = iter.second->versionId; 730*d8c9eea3SLei YU break; 731*d8c9eea3SLei YU } 732*d8c9eea3SLei YU } 733*d8c9eea3SLei YU if (!versionIDtoErase.empty()) 734*d8c9eea3SLei YU { 735*d8c9eea3SLei YU erase(versionIDtoErase); 736*d8c9eea3SLei YU } 737*d8c9eea3SLei YU else 738*d8c9eea3SLei YU { 739*d8c9eea3SLei YU warning("Failed to find version to erase"); 740*d8c9eea3SLei YU } 741*d8c9eea3SLei YU #else 742204e1e74SAdriana Kobylak // Versions with the highest priority in front 743204e1e74SAdriana Kobylak std::priority_queue<std::pair<int, std::string>, 744204e1e74SAdriana Kobylak std::vector<std::pair<int, std::string>>, 7452285fe0fSAdriana Kobylak std::less<std::pair<int, std::string>>> 7462285fe0fSAdriana Kobylak versionsPQ; 747204e1e74SAdriana Kobylak 748204e1e74SAdriana Kobylak std::size_t count = 0; 749204e1e74SAdriana Kobylak for (const auto& iter : activations) 750204e1e74SAdriana Kobylak { 751204e1e74SAdriana Kobylak if ((iter.second.get()->activation() == 752204e1e74SAdriana Kobylak server::Activation::Activations::Active) || 753204e1e74SAdriana Kobylak (iter.second.get()->activation() == 754204e1e74SAdriana Kobylak server::Activation::Activations::Failed)) 755204e1e74SAdriana Kobylak { 756204e1e74SAdriana Kobylak count++; 757204e1e74SAdriana Kobylak // Don't put the functional version on the queue since we can't 758204e1e74SAdriana Kobylak // remove the "running" BMC version. 7590f88b5afSLei YU // If ACTIVE_BMC_MAX_ALLOWED <= 1, there is only one active BMC, 7600f88b5afSLei YU // so remove functional version as well. 761a6963590SAdriana Kobylak // Don't delete the the Activation object that called this function. 762a6963590SAdriana Kobylak if ((versions.find(iter.second->versionId) 763a6963590SAdriana Kobylak ->second->isFunctional() && 764a6963590SAdriana Kobylak ACTIVE_BMC_MAX_ALLOWED > 1) || 765a6963590SAdriana Kobylak (iter.second->versionId == caller.versionId)) 766204e1e74SAdriana Kobylak { 767204e1e74SAdriana Kobylak continue; 768204e1e74SAdriana Kobylak } 769a6963590SAdriana Kobylak 770a6963590SAdriana Kobylak // Failed activations don't have priority, assign them a large value 771a6963590SAdriana Kobylak // for sorting purposes. 772a6963590SAdriana Kobylak auto priority = 999; 773a6963590SAdriana Kobylak if (iter.second.get()->activation() == 774cfb4b209SLei YU server::Activation::Activations::Active && 775cfb4b209SLei YU iter.second->redundancyPriority) 776a6963590SAdriana Kobylak { 777a6963590SAdriana Kobylak priority = iter.second->redundancyPriority.get()->priority(); 778a6963590SAdriana Kobylak } 779a6963590SAdriana Kobylak 780a6963590SAdriana Kobylak versionsPQ.push(std::make_pair(priority, iter.second->versionId)); 781204e1e74SAdriana Kobylak } 782204e1e74SAdriana Kobylak } 783204e1e74SAdriana Kobylak 784204e1e74SAdriana Kobylak // If the number of BMC versions is over ACTIVE_BMC_MAX_ALLOWED -1, 785204e1e74SAdriana Kobylak // remove the highest priority one(s). 786204e1e74SAdriana Kobylak while ((count >= ACTIVE_BMC_MAX_ALLOWED) && (!versionsPQ.empty())) 787204e1e74SAdriana Kobylak { 788204e1e74SAdriana Kobylak erase(versionsPQ.top().second); 789204e1e74SAdriana Kobylak versionsPQ.pop(); 790204e1e74SAdriana Kobylak count--; 791204e1e74SAdriana Kobylak } 792*d8c9eea3SLei YU #endif 793204e1e74SAdriana Kobylak } 794204e1e74SAdriana Kobylak 795eaa1ee05SEddie James void ItemUpdater::mirrorUbootToAlt() 796eaa1ee05SEddie James { 79756aaf454SLei YU helper.mirrorAlt(); 798eaa1ee05SEddie James } 799eaa1ee05SEddie James 8008e9ccfe7SBright Cheng bool ItemUpdater::checkImage(const std::string& filePath, 8018e9ccfe7SBright Cheng const std::vector<std::string>& imageList) 8028e9ccfe7SBright Cheng { 8038e9ccfe7SBright Cheng bool valid = true; 8048e9ccfe7SBright Cheng 8058e9ccfe7SBright Cheng for (auto& bmcImage : imageList) 8068e9ccfe7SBright Cheng { 8078e9ccfe7SBright Cheng fs::path file(filePath); 8088e9ccfe7SBright Cheng file /= bmcImage; 8098e9ccfe7SBright Cheng std::ifstream efile(file.c_str()); 8108e9ccfe7SBright Cheng if (efile.good() != 1) 8118e9ccfe7SBright Cheng { 8128e9ccfe7SBright Cheng valid = false; 8138e9ccfe7SBright Cheng break; 8148e9ccfe7SBright Cheng } 8158e9ccfe7SBright Cheng } 8168e9ccfe7SBright Cheng 8178e9ccfe7SBright Cheng return valid; 8188e9ccfe7SBright Cheng } 8198e9ccfe7SBright Cheng 8206e9fb1d6SLei YU #ifdef HOST_BIOS_UPGRADE 8216e9fb1d6SLei YU void ItemUpdater::createBIOSObject() 8226e9fb1d6SLei YU { 8236e9fb1d6SLei YU std::string path = BIOS_OBJPATH; 8246e9fb1d6SLei YU // Get version id from last item in the path 8256e9fb1d6SLei YU auto pos = path.rfind("/"); 8266e9fb1d6SLei YU if (pos == std::string::npos) 8276e9fb1d6SLei YU { 828c9bb6425SPatrick Williams error("No version id found in object path {PATH}", "PATH", path); 8296e9fb1d6SLei YU return; 8306e9fb1d6SLei YU } 8316e9fb1d6SLei YU 8326e9fb1d6SLei YU createActiveAssociation(path); 8336e9fb1d6SLei YU createFunctionalAssociation(path); 8346e9fb1d6SLei YU 8356e9fb1d6SLei YU auto versionId = path.substr(pos + 1); 8366e9fb1d6SLei YU auto version = "null"; 8376e9fb1d6SLei YU AssociationList assocs = {}; 8386e9fb1d6SLei YU biosActivation = std::make_unique<Activation>( 8396e9fb1d6SLei YU bus, path, *this, versionId, server::Activation::Activations::Active, 8406e9fb1d6SLei YU assocs); 8416e9fb1d6SLei YU auto dummyErase = [](std::string /*entryId*/) { 8426e9fb1d6SLei YU // Do nothing; 8436e9fb1d6SLei YU }; 8446e9fb1d6SLei YU biosVersion = std::make_unique<VersionClass>( 8456e9fb1d6SLei YU bus, path, version, VersionPurpose::Host, "", "", 84659b640b0SAdriana Kobylak std::bind(dummyErase, std::placeholders::_1), ""); 8476e9fb1d6SLei YU biosVersion->deleteObject = 8486e9fb1d6SLei YU std::make_unique<phosphor::software::manager::Delete>(bus, path, 8496e9fb1d6SLei YU *biosVersion); 8506e9fb1d6SLei YU } 8516e9fb1d6SLei YU #endif 8526e9fb1d6SLei YU 853531fbc25SLei YU void ItemUpdater::getRunningSlot() 854531fbc25SLei YU { 855531fbc25SLei YU // Check /run/media/slot to get the slot number 856531fbc25SLei YU constexpr auto slotFile = "/run/media/slot"; 857531fbc25SLei YU std::fstream f(slotFile, std::ios_base::in); 858531fbc25SLei YU f >> runningImageSlot; 859531fbc25SLei YU } 860531fbc25SLei YU 861ec1b41c4SGunnar Mills } // namespace updater 862ec1b41c4SGunnar Mills } // namespace software 863ec1b41c4SGunnar Mills } // namespace phosphor 864