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 activations.insert(std::make_pair( 142ee13e831SSaqib Khan versionId, 1432285fe0fSAdriana Kobylak std::make_unique<Activation>(bus, path, *this, versionId, 1442285fe0fSAdriana Kobylak activationState, associations))); 1454254beceSMichael Tritz 146ee13e831SSaqib Khan auto versionPtr = std::make_unique<VersionClass>( 1471fd6dddfSChanh Nguyen bus, path, version, purpose, extendedVersion, filePath, 1482285fe0fSAdriana Kobylak std::bind(&ItemUpdater::erase, this, std::placeholders::_1)); 149ee13e831SSaqib Khan versionPtr->deleteObject = 1502285fe0fSAdriana Kobylak std::make_unique<phosphor::software::manager::Delete>(bus, path, 1512285fe0fSAdriana Kobylak *versionPtr); 152ee13e831SSaqib Khan versions.insert(std::make_pair(versionId, std::move(versionPtr))); 1532ce7da29SGunnar Mills } 154e75d10f5SPatrick Williams return; 155ec1b41c4SGunnar Mills } 156ec1b41c4SGunnar Mills 157ba239881SSaqib Khan void ItemUpdater::processBMCImage() 158ba239881SSaqib Khan { 15988e8a325SGunnar Mills using VersionClass = phosphor::software::manager::Version; 160269bff30SLei YU 161269bff30SLei YU // Check MEDIA_DIR and create if it does not exist 162269bff30SLei YU try 163269bff30SLei YU { 164269bff30SLei YU if (!fs::is_directory(MEDIA_DIR)) 165269bff30SLei YU { 166269bff30SLei YU fs::create_directory(MEDIA_DIR); 167269bff30SLei YU } 168269bff30SLei YU } 169269bff30SLei YU catch (const fs::filesystem_error& e) 170269bff30SLei YU { 171c9bb6425SPatrick Williams error("Failed to prepare dir: {ERROR}", "ERROR", e); 172269bff30SLei YU return; 173269bff30SLei YU } 174269bff30SLei YU 17588e8a325SGunnar Mills // Read os-release from /etc/ to get the functional BMC version 17688e8a325SGunnar Mills auto functionalVersion = VersionClass::getBMCVersion(OS_RELEASE_FILE); 17788e8a325SGunnar Mills 1781eef62deSSaqib Khan // Read os-release from folders under /media/ to get 1791eef62deSSaqib Khan // BMC Software Versions. 1801eef62deSSaqib Khan for (const auto& iter : fs::directory_iterator(MEDIA_DIR)) 1811eef62deSSaqib Khan { 1821eef62deSSaqib Khan auto activationState = server::Activation::Activations::Active; 1836fab70daSSaqib Khan static const auto BMC_RO_PREFIX_LEN = strlen(BMC_ROFS_PREFIX); 1841eef62deSSaqib Khan 1851eef62deSSaqib Khan // Check if the BMC_RO_PREFIXis the prefix of the iter.path 1862285fe0fSAdriana Kobylak if (0 == 1872285fe0fSAdriana Kobylak iter.path().native().compare(0, BMC_RO_PREFIX_LEN, BMC_ROFS_PREFIX)) 1881eef62deSSaqib Khan { 189716cd78dSAdriana Kobylak // Get the version to calculate the id 19024a8d83dSAdriana Kobylak fs::path releaseFile(OS_RELEASE_FILE); 19124a8d83dSAdriana Kobylak auto osRelease = iter.path() / releaseFile.relative_path(); 1921eef62deSSaqib Khan if (!fs::is_regular_file(osRelease)) 1931eef62deSSaqib Khan { 194c9bb6425SPatrick Williams error("Failed to read osRelease: {PATH}", "PATH", osRelease); 195716cd78dSAdriana Kobylak 196716cd78dSAdriana Kobylak // Try to get the version id from the mount directory name and 197716cd78dSAdriana Kobylak // call to delete it as this version may be corrupted. Dynamic 198716cd78dSAdriana Kobylak // volumes created by the UBI layout for example have the id in 199716cd78dSAdriana Kobylak // the mount directory name. The worst that can happen is that 200716cd78dSAdriana Kobylak // erase() is called with an non-existent id and returns. 201716cd78dSAdriana Kobylak auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN); 202021c365bSSaqib Khan ItemUpdater::erase(id); 203716cd78dSAdriana Kobylak 204021c365bSSaqib Khan continue; 2051eef62deSSaqib Khan } 20688e8a325SGunnar Mills auto version = VersionClass::getBMCVersion(osRelease); 2071eef62deSSaqib Khan if (version.empty()) 2081eef62deSSaqib Khan { 209c9bb6425SPatrick Williams error("Failed to read version from osRelease: {PATH}", "PATH", 210c9bb6425SPatrick Williams osRelease); 211716cd78dSAdriana Kobylak 212716cd78dSAdriana Kobylak // Try to delete the version, same as above if the 213716cd78dSAdriana Kobylak // OS_RELEASE_FILE does not exist. 214716cd78dSAdriana Kobylak auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN); 215716cd78dSAdriana Kobylak ItemUpdater::erase(id); 216716cd78dSAdriana Kobylak 217716cd78dSAdriana Kobylak continue; 2181eef62deSSaqib Khan } 219021c365bSSaqib Khan 220716cd78dSAdriana Kobylak auto id = VersionClass::getId(version); 221716cd78dSAdriana Kobylak 222f383d27aSAdriana Kobylak // Check if the id has already been added. This can happen if the 223f383d27aSAdriana Kobylak // BMC partitions / devices were manually flashed with the same 224f383d27aSAdriana Kobylak // image. 225f383d27aSAdriana Kobylak if (versions.find(id) != versions.end()) 226f383d27aSAdriana Kobylak { 227f383d27aSAdriana Kobylak continue; 228f383d27aSAdriana Kobylak } 229f383d27aSAdriana Kobylak 230780220f2SAdriana Kobylak // The flash location is part of the mount name: rofs-<location> 231780220f2SAdriana Kobylak auto flashId = iter.path().native().substr(BMC_RO_PREFIX_LEN); 232780220f2SAdriana Kobylak 2331eef62deSSaqib Khan auto purpose = server::Version::VersionPurpose::BMC; 234780220f2SAdriana Kobylak restorePurpose(flashId, purpose); 235ec4eec34SAdriana Kobylak 2361fd6dddfSChanh Nguyen // Read os-release from /etc/ to get the BMC extended version 2371fd6dddfSChanh Nguyen std::string extendedVersion = 2381fd6dddfSChanh Nguyen VersionClass::getBMCExtendedVersion(osRelease); 2391fd6dddfSChanh Nguyen 2401eef62deSSaqib Khan auto path = fs::path(SOFTWARE_OBJPATH) / id; 2411eef62deSSaqib Khan 242269bff30SLei YU // Create functional association if this is the functional 243269bff30SLei YU // version 24488e8a325SGunnar Mills if (version.compare(functionalVersion) == 0) 24588e8a325SGunnar Mills { 24688e8a325SGunnar Mills createFunctionalAssociation(path); 24788e8a325SGunnar Mills } 24888e8a325SGunnar Mills 24943b25cdeSGunnar Mills AssociationList associations = {}; 25043b25cdeSGunnar Mills 25143b25cdeSGunnar Mills if (activationState == server::Activation::Activations::Active) 25243b25cdeSGunnar Mills { 25343b25cdeSGunnar Mills // Create an association to the BMC inventory item 25443b25cdeSGunnar Mills associations.emplace_back(std::make_tuple( 2552285fe0fSAdriana Kobylak ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION, 25643b25cdeSGunnar Mills bmcInventoryPath)); 25743b25cdeSGunnar Mills 25843b25cdeSGunnar Mills // Create an active association since this image is active 25943b25cdeSGunnar Mills createActiveAssociation(path); 26043b25cdeSGunnar Mills } 26143b25cdeSGunnar Mills 262bbebec79SAppaRao Puli // All updateable firmware components must expose the updateable 263bbebec79SAppaRao Puli // association. 264bbebec79SAppaRao Puli createUpdateableAssociation(path); 265bbebec79SAppaRao Puli 266ee590c74SAdriana Kobylak // Create Version instance for this version. 267ee590c74SAdriana Kobylak auto versionPtr = std::make_unique<VersionClass>( 268a84f06d2SAdriana Kobylak bus, path, version, purpose, extendedVersion, flashId, 2692285fe0fSAdriana Kobylak std::bind(&ItemUpdater::erase, this, std::placeholders::_1)); 270ee590c74SAdriana Kobylak auto isVersionFunctional = versionPtr->isFunctional(); 271ee13e831SSaqib Khan if (!isVersionFunctional) 272ee13e831SSaqib Khan { 273ee13e831SSaqib Khan versionPtr->deleteObject = 274ee13e831SSaqib Khan std::make_unique<phosphor::software::manager::Delete>( 275ee13e831SSaqib Khan bus, path, *versionPtr); 276ee13e831SSaqib Khan } 2772285fe0fSAdriana Kobylak versions.insert(std::make_pair(id, std::move(versionPtr))); 278ee590c74SAdriana Kobylak 2791eef62deSSaqib Khan // Create Activation instance for this version. 280ee13e831SSaqib Khan activations.insert(std::make_pair( 2812285fe0fSAdriana Kobylak id, std::make_unique<Activation>( 2822285fe0fSAdriana Kobylak bus, path, *this, id, activationState, associations))); 2831eef62deSSaqib Khan 284269bff30SLei YU // If Active, create RedundancyPriority instance for this 285269bff30SLei YU // version. 2861eef62deSSaqib Khan if (activationState == server::Activation::Activations::Active) 2871eef62deSSaqib Khan { 2881eef62deSSaqib Khan uint8_t priority = std::numeric_limits<uint8_t>::max(); 289780220f2SAdriana Kobylak if (!restorePriority(flashId, priority)) 2901eef62deSSaqib Khan { 291ee590c74SAdriana Kobylak if (isVersionFunctional) 292ee590c74SAdriana Kobylak { 293ee590c74SAdriana Kobylak priority = 0; 294ee590c74SAdriana Kobylak } 295ee590c74SAdriana Kobylak else 296ee590c74SAdriana Kobylak { 297c9bb6425SPatrick Williams error( 298c9bb6425SPatrick Williams "Unable to restore priority from file for {VERSIONID}", 299c9bb6425SPatrick Williams "VERSIONID", id); 3001eef62deSSaqib Khan } 301ee590c74SAdriana Kobylak } 3021eef62deSSaqib Khan activations.find(id)->second->redundancyPriority = 3031eef62deSSaqib Khan std::make_unique<RedundancyPriority>( 3042285fe0fSAdriana Kobylak bus, path, *(activations.find(id)->second), priority, 305b77551cdSAdriana Kobylak false); 3061eef62deSSaqib Khan } 3071eef62deSSaqib Khan } 3081eef62deSSaqib Khan } 309dcbfa04aSSaqib Khan 310716cd78dSAdriana Kobylak // If there are no bmc versions mounted under MEDIA_DIR, then read the 311716cd78dSAdriana Kobylak // /etc/os-release and create rofs-<versionId> under MEDIA_DIR, then call 312716cd78dSAdriana Kobylak // again processBMCImage() to create the D-Bus interface for it. 313dcbfa04aSSaqib Khan if (activations.size() == 0) 314dcbfa04aSSaqib Khan { 315d16bcbd5SGunnar Mills auto version = VersionClass::getBMCVersion(OS_RELEASE_FILE); 316dcbfa04aSSaqib Khan auto id = phosphor::software::manager::Version::getId(version); 317dcbfa04aSSaqib Khan auto versionFileDir = BMC_ROFS_PREFIX + id + "/etc/"; 318dcbfa04aSSaqib Khan try 319dcbfa04aSSaqib Khan { 320dcbfa04aSSaqib Khan if (!fs::is_directory(versionFileDir)) 321dcbfa04aSSaqib Khan { 322dcbfa04aSSaqib Khan fs::create_directories(versionFileDir); 323dcbfa04aSSaqib Khan } 324dcbfa04aSSaqib Khan auto versionFilePath = BMC_ROFS_PREFIX + id + OS_RELEASE_FILE; 325dcbfa04aSSaqib Khan fs::create_directory_symlink(OS_RELEASE_FILE, versionFilePath); 326dcbfa04aSSaqib Khan ItemUpdater::processBMCImage(); 327dcbfa04aSSaqib Khan } 328dcbfa04aSSaqib Khan catch (const std::exception& e) 329dcbfa04aSSaqib Khan { 330c9bb6425SPatrick Williams error("Exception during processing: {ERROR}", "ERROR", e); 331dcbfa04aSSaqib Khan } 332dcbfa04aSSaqib Khan } 333eaa1ee05SEddie James 334eaa1ee05SEddie James mirrorUbootToAlt(); 335ba239881SSaqib Khan return; 336ba239881SSaqib Khan } 337ba239881SSaqib Khan 3383526ef73SLeonel Gonzalez void ItemUpdater::erase(std::string entryId) 3393526ef73SLeonel Gonzalez { 3406d873715SEddie James // Find entry in versions map 3416d873715SEddie James auto it = versions.find(entryId); 3426d873715SEddie James if (it != versions.end()) 3436d873715SEddie James { 3440f88b5afSLei YU if (it->second->isFunctional() && ACTIVE_BMC_MAX_ALLOWED > 1) 3456d873715SEddie James { 346c9bb6425SPatrick Williams error( 347c9bb6425SPatrick Williams "Version ({VERSIONID}) is currently running on the BMC; unable to remove.", 348c9bb6425SPatrick Williams "VERSIONID", entryId); 3496d873715SEddie James return; 3506d873715SEddie James } 351d1a55adcSAdriana Kobylak } 3526d873715SEddie James 353d1a55adcSAdriana Kobylak // First call resetUbootEnvVars() so that the BMC points to a valid image to 354d1a55adcSAdriana Kobylak // boot from. If resetUbootEnvVars() is called after the image is actually 355d1a55adcSAdriana Kobylak // deleted from the BMC flash, there'd be a time window where the BMC would 356d1a55adcSAdriana Kobylak // be pointing to a non-existent image to boot from. 357d1a55adcSAdriana Kobylak // Need to remove the entries from the activations map before that call so 358d1a55adcSAdriana Kobylak // that resetUbootEnvVars() doesn't use the version to be deleted. 359d1a55adcSAdriana Kobylak auto iteratorActivations = activations.find(entryId); 360d1a55adcSAdriana Kobylak if (iteratorActivations == activations.end()) 361d1a55adcSAdriana Kobylak { 362c9bb6425SPatrick Williams error( 363c9bb6425SPatrick Williams "Failed to find version ({VERSIONID}) in item updater activations map; unable to remove.", 364c9bb6425SPatrick Williams "VERSIONID", entryId); 365d1a55adcSAdriana Kobylak } 366d1a55adcSAdriana Kobylak else 367d1a55adcSAdriana Kobylak { 368d1a55adcSAdriana Kobylak removeAssociations(iteratorActivations->second->path); 369ae06d76aSZami Seck iteratorActivations->second->deleteImageManagerObject(); 370d1a55adcSAdriana Kobylak this->activations.erase(entryId); 371d1a55adcSAdriana Kobylak } 372d1a55adcSAdriana Kobylak ItemUpdater::resetUbootEnvVars(); 373d1a55adcSAdriana Kobylak 374d1a55adcSAdriana Kobylak if (it != versions.end()) 375d1a55adcSAdriana Kobylak { 376780220f2SAdriana Kobylak auto flashId = it->second->path(); 377780220f2SAdriana Kobylak 378*25773a7eSAdriana Kobylak // Delete version data if it has been installed on flash (path is not 379*25773a7eSAdriana Kobylak // the upload directory) 380*25773a7eSAdriana Kobylak if (flashId.find(IMG_UPLOAD_DIR) == std::string::npos) 381*25773a7eSAdriana Kobylak { 3823526ef73SLeonel Gonzalez removeReadOnlyPartition(entryId); 383780220f2SAdriana Kobylak removePersistDataDirectory(flashId); 384*25773a7eSAdriana Kobylak helper.clearEntry(flashId); 385*25773a7eSAdriana Kobylak } 386ee13e831SSaqib Khan 387ee13e831SSaqib Khan // Removing entry in versions map 388ee13e831SSaqib Khan this->versions.erase(entryId); 3896d873715SEddie James } 3903526ef73SLeonel Gonzalez 391ee13e831SSaqib Khan return; 3923526ef73SLeonel Gonzalez } 3933526ef73SLeonel Gonzalez 394bc1bf3afSMichael Tritz void ItemUpdater::deleteAll() 395bc1bf3afSMichael Tritz { 39683cd21fbSAdriana Kobylak std::vector<std::string> deletableVersions; 39783cd21fbSAdriana Kobylak 398bc1bf3afSMichael Tritz for (const auto& versionIt : versions) 399bc1bf3afSMichael Tritz { 400bc1bf3afSMichael Tritz if (!versionIt.second->isFunctional()) 401bc1bf3afSMichael Tritz { 40283cd21fbSAdriana Kobylak deletableVersions.push_back(versionIt.first); 403bc1bf3afSMichael Tritz } 404bc1bf3afSMichael Tritz } 405bc1bf3afSMichael Tritz 40683cd21fbSAdriana Kobylak for (const auto& deletableIt : deletableVersions) 40783cd21fbSAdriana Kobylak { 40883cd21fbSAdriana Kobylak ItemUpdater::erase(deletableIt); 40983cd21fbSAdriana Kobylak } 41083cd21fbSAdriana Kobylak 41156aaf454SLei YU helper.cleanup(); 412bc1bf3afSMichael Tritz } 413bc1bf3afSMichael Tritz 4142285fe0fSAdriana Kobylak ItemUpdater::ActivationStatus 4152285fe0fSAdriana Kobylak ItemUpdater::validateSquashFSImage(const std::string& filePath) 41635e83f3eSSaqib Khan { 4178e9ccfe7SBright Cheng bool valid = true; 41835e83f3eSSaqib Khan 4198e9ccfe7SBright Cheng // Record the images which are being updated 4208e9ccfe7SBright Cheng // First check for the fullimage, then check for images with partitions 4218e9ccfe7SBright Cheng imageUpdateList.push_back(bmcFullImages); 4228e9ccfe7SBright Cheng valid = checkImage(filePath, imageUpdateList); 4238e9ccfe7SBright Cheng if (!valid) 424b1cfdf99SMichael Tritz { 4258e9ccfe7SBright Cheng imageUpdateList.clear(); 4268e9ccfe7SBright Cheng imageUpdateList.assign(bmcImages.begin(), bmcImages.end()); 4278e9ccfe7SBright Cheng valid = checkImage(filePath, imageUpdateList); 4288e9ccfe7SBright Cheng if (!valid) 42935e83f3eSSaqib Khan { 430c9bb6425SPatrick Williams error("Failed to find the needed BMC images."); 43135e83f3eSSaqib Khan return ItemUpdater::ActivationStatus::invalid; 43235e83f3eSSaqib Khan } 4338e9ccfe7SBright Cheng } 434b1cfdf99SMichael Tritz 435b1cfdf99SMichael Tritz return ItemUpdater::ActivationStatus::ready; 43635e83f3eSSaqib Khan } 43735e83f3eSSaqib Khan 438bbcb7be1SAdriana Kobylak void ItemUpdater::savePriority(const std::string& versionId, uint8_t value) 439bbcb7be1SAdriana Kobylak { 440780220f2SAdriana Kobylak auto flashId = versions.find(versionId)->second->path(); 441780220f2SAdriana Kobylak storePriority(flashId, value); 442*25773a7eSAdriana Kobylak helper.setEntry(flashId, value); 443bbcb7be1SAdriana Kobylak } 444bbcb7be1SAdriana Kobylak 445b9da6634SSaqib Khan void ItemUpdater::freePriority(uint8_t value, const std::string& versionId) 4464c1aec09SSaqib Khan { 447b77551cdSAdriana Kobylak std::map<std::string, uint8_t> priorityMap; 448b77551cdSAdriana Kobylak 449b77551cdSAdriana Kobylak // Insert the requested version and priority, it may not exist yet. 450b77551cdSAdriana Kobylak priorityMap.insert(std::make_pair(versionId, value)); 451b77551cdSAdriana Kobylak 4524c1aec09SSaqib Khan for (const auto& intf : activations) 4534c1aec09SSaqib Khan { 4544c1aec09SSaqib Khan if (intf.second->redundancyPriority) 4554c1aec09SSaqib Khan { 456b77551cdSAdriana Kobylak priorityMap.insert(std::make_pair( 4572285fe0fSAdriana Kobylak intf.first, intf.second->redundancyPriority.get()->priority())); 458b77551cdSAdriana Kobylak } 459b77551cdSAdriana Kobylak } 460b77551cdSAdriana Kobylak 461b77551cdSAdriana Kobylak // Lambda function to compare 2 priority values, use <= to allow duplicates 4622285fe0fSAdriana Kobylak typedef std::function<bool(std::pair<std::string, uint8_t>, 4632285fe0fSAdriana Kobylak std::pair<std::string, uint8_t>)> 4642285fe0fSAdriana Kobylak cmpPriority; 4652285fe0fSAdriana Kobylak cmpPriority cmpPriorityFunc = 4662285fe0fSAdriana Kobylak [](std::pair<std::string, uint8_t> priority1, 4672285fe0fSAdriana Kobylak std::pair<std::string, uint8_t> priority2) { 468b77551cdSAdriana Kobylak return priority1.second <= priority2.second; 469b77551cdSAdriana Kobylak }; 470b77551cdSAdriana Kobylak 471b77551cdSAdriana Kobylak // Sort versions by ascending priority 472b77551cdSAdriana Kobylak std::set<std::pair<std::string, uint8_t>, cmpPriority> prioritySet( 473b77551cdSAdriana Kobylak priorityMap.begin(), priorityMap.end(), cmpPriorityFunc); 474b77551cdSAdriana Kobylak 475b77551cdSAdriana Kobylak auto freePriorityValue = value; 476b77551cdSAdriana Kobylak for (auto& element : prioritySet) 477b77551cdSAdriana Kobylak { 478b77551cdSAdriana Kobylak if (element.first == versionId) 479b77551cdSAdriana Kobylak { 480b77551cdSAdriana Kobylak continue; 481b77551cdSAdriana Kobylak } 482b77551cdSAdriana Kobylak if (element.second == freePriorityValue) 483b77551cdSAdriana Kobylak { 484b77551cdSAdriana Kobylak ++freePriorityValue; 485b77551cdSAdriana Kobylak auto it = activations.find(element.first); 486b77551cdSAdriana Kobylak it->second->redundancyPriority.get()->sdbusPriority( 487b77551cdSAdriana Kobylak freePriorityValue); 4884c1aec09SSaqib Khan } 4894c1aec09SSaqib Khan } 490b77551cdSAdriana Kobylak 491b77551cdSAdriana Kobylak auto lowestVersion = prioritySet.begin()->first; 492b77551cdSAdriana Kobylak if (value == prioritySet.begin()->second) 493b77551cdSAdriana Kobylak { 494b77551cdSAdriana Kobylak lowestVersion = versionId; 4954c1aec09SSaqib Khan } 496b77551cdSAdriana Kobylak updateUbootEnvVars(lowestVersion); 4974c1aec09SSaqib Khan } 4984c1aec09SSaqib Khan 49937a59043SMichael Tritz void ItemUpdater::reset() 50037a59043SMichael Tritz { 50156aaf454SLei YU helper.factoryReset(); 50237a59043SMichael Tritz 503c9bb6425SPatrick Williams info("BMC factory reset will take effect upon reboot."); 50437a59043SMichael Tritz } 50537a59043SMichael Tritz 5063526ef73SLeonel Gonzalez void ItemUpdater::removeReadOnlyPartition(std::string versionId) 5073526ef73SLeonel Gonzalez { 508*25773a7eSAdriana Kobylak auto flashId = versions.find(versionId)->second->path(); 509*25773a7eSAdriana Kobylak helper.removeVersion(flashId); 5103526ef73SLeonel Gonzalez } 5113526ef73SLeonel Gonzalez 5120129d926SMichael Tritz bool ItemUpdater::fieldModeEnabled(bool value) 5130129d926SMichael Tritz { 5140129d926SMichael Tritz // enabling field mode is intended to be one way: false -> true 5150129d926SMichael Tritz if (value && !control::FieldMode::fieldModeEnabled()) 5160129d926SMichael Tritz { 5170129d926SMichael Tritz control::FieldMode::fieldModeEnabled(value); 5180129d926SMichael Tritz 51922848eceSAdriana Kobylak auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 52022848eceSAdriana Kobylak SYSTEMD_INTERFACE, "StartUnit"); 52122848eceSAdriana Kobylak method.append("obmc-flash-bmc-setenv@fieldmode\\x3dtrue.service", 52222848eceSAdriana Kobylak "replace"); 52322848eceSAdriana Kobylak bus.call_noreply(method); 52422848eceSAdriana Kobylak 52522848eceSAdriana Kobylak method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 52622848eceSAdriana Kobylak SYSTEMD_INTERFACE, "StopUnit"); 52722848eceSAdriana Kobylak method.append("usr-local.mount", "replace"); 52822848eceSAdriana Kobylak bus.call_noreply(method); 52922848eceSAdriana Kobylak 53022848eceSAdriana Kobylak std::vector<std::string> usrLocal = {"usr-local.mount"}; 53122848eceSAdriana Kobylak 53222848eceSAdriana Kobylak method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 53322848eceSAdriana Kobylak SYSTEMD_INTERFACE, "MaskUnitFiles"); 53422848eceSAdriana Kobylak method.append(usrLocal, false, true); 53522848eceSAdriana Kobylak bus.call_noreply(method); 5360129d926SMichael Tritz } 537d5b8f75cSAdriana Kobylak else if (!value && control::FieldMode::fieldModeEnabled()) 538d5b8f75cSAdriana Kobylak { 539d5b8f75cSAdriana Kobylak elog<NotAllowed>(xyz::openbmc_project::Common::NotAllowed::REASON( 540d5b8f75cSAdriana Kobylak "FieldMode is not allowed to be cleared")); 541d5b8f75cSAdriana Kobylak } 5420129d926SMichael Tritz 5430129d926SMichael Tritz return control::FieldMode::fieldModeEnabled(); 5440129d926SMichael Tritz } 5450129d926SMichael Tritz 5460129d926SMichael Tritz void ItemUpdater::restoreFieldModeStatus() 5470129d926SMichael Tritz { 548ff0b421dSMichael Tritz std::ifstream input("/dev/mtd/u-boot-env"); 5490129d926SMichael Tritz std::string envVar; 5500129d926SMichael Tritz std::getline(input, envVar); 5510129d926SMichael Tritz 5520129d926SMichael Tritz if (envVar.find("fieldmode=true") != std::string::npos) 5530129d926SMichael Tritz { 5540129d926SMichael Tritz ItemUpdater::fieldModeEnabled(true); 5550129d926SMichael Tritz } 5560129d926SMichael Tritz } 5570129d926SMichael Tritz 558b60add1eSGunnar Mills void ItemUpdater::setBMCInventoryPath() 559b60add1eSGunnar Mills { 560b60add1eSGunnar Mills auto depth = 0; 5612285fe0fSAdriana Kobylak auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, 5622285fe0fSAdriana Kobylak MAPPER_INTERFACE, "GetSubTreePaths"); 563b60add1eSGunnar Mills 5641254c628SAdriana Kobylak mapperCall.append(INVENTORY_PATH); 565b60add1eSGunnar Mills mapperCall.append(depth); 5661254c628SAdriana Kobylak std::vector<std::string> filter = {BMC_INVENTORY_INTERFACE}; 567b60add1eSGunnar Mills mapperCall.append(filter); 568b60add1eSGunnar Mills 56987c78173SEd Tanous try 570b60add1eSGunnar Mills { 57187c78173SEd Tanous auto response = bus.call(mapperCall); 572b60add1eSGunnar Mills 573b60add1eSGunnar Mills using ObjectPaths = std::vector<std::string>; 574b60add1eSGunnar Mills ObjectPaths result; 575b60add1eSGunnar Mills response.read(result); 576b60add1eSGunnar Mills 5771254c628SAdriana Kobylak if (!result.empty()) 578b60add1eSGunnar Mills { 5791254c628SAdriana Kobylak bmcInventoryPath = result.front(); 580b60add1eSGunnar Mills } 58187c78173SEd Tanous } 5824ce901c5SPatrick Williams catch (const sdbusplus::exception::exception& e) 58387c78173SEd Tanous { 584c9bb6425SPatrick Williams error("Error in mapper GetSubTreePath: {ERROR}", "ERROR", e); 58587c78173SEd Tanous return; 58687c78173SEd Tanous } 587b60add1eSGunnar Mills 588b60add1eSGunnar Mills return; 589b60add1eSGunnar Mills } 590b60add1eSGunnar Mills 591f10b2326SGunnar Mills void ItemUpdater::createActiveAssociation(const std::string& path) 592ded875dcSGunnar Mills { 5932285fe0fSAdriana Kobylak assocs.emplace_back( 5942285fe0fSAdriana Kobylak std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path)); 595ded875dcSGunnar Mills associations(assocs); 596ded875dcSGunnar Mills } 597ded875dcSGunnar Mills 59888e8a325SGunnar Mills void ItemUpdater::createFunctionalAssociation(const std::string& path) 59988e8a325SGunnar Mills { 60088e8a325SGunnar Mills assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION, 6012285fe0fSAdriana Kobylak FUNCTIONAL_REV_ASSOCIATION, path)); 60288e8a325SGunnar Mills associations(assocs); 60388e8a325SGunnar Mills } 60488e8a325SGunnar Mills 605bbebec79SAppaRao Puli void ItemUpdater::createUpdateableAssociation(const std::string& path) 606bbebec79SAppaRao Puli { 607bbebec79SAppaRao Puli assocs.emplace_back(std::make_tuple(UPDATEABLE_FWD_ASSOCIATION, 608bbebec79SAppaRao Puli UPDATEABLE_REV_ASSOCIATION, path)); 609bbebec79SAppaRao Puli associations(assocs); 610bbebec79SAppaRao Puli } 611bbebec79SAppaRao Puli 612991af7ecSAdriana Kobylak void ItemUpdater::removeAssociations(const std::string& path) 613ded875dcSGunnar Mills { 614ded875dcSGunnar Mills for (auto iter = assocs.begin(); iter != assocs.end();) 615ded875dcSGunnar Mills { 616991af7ecSAdriana Kobylak if ((std::get<2>(*iter)).compare(path) == 0) 617ded875dcSGunnar Mills { 618ded875dcSGunnar Mills iter = assocs.erase(iter); 619ded875dcSGunnar Mills associations(assocs); 620ded875dcSGunnar Mills } 621ded875dcSGunnar Mills else 622ded875dcSGunnar Mills { 623ded875dcSGunnar Mills ++iter; 624ded875dcSGunnar Mills } 625ded875dcSGunnar Mills } 626ded875dcSGunnar Mills } 627ded875dcSGunnar Mills 628b9da6634SSaqib Khan bool ItemUpdater::isLowestPriority(uint8_t value) 629b9da6634SSaqib Khan { 630b9da6634SSaqib Khan for (const auto& intf : activations) 631b9da6634SSaqib Khan { 632b9da6634SSaqib Khan if (intf.second->redundancyPriority) 633b9da6634SSaqib Khan { 634b9da6634SSaqib Khan if (intf.second->redundancyPriority.get()->priority() < value) 635b9da6634SSaqib Khan { 636b9da6634SSaqib Khan return false; 637b9da6634SSaqib Khan } 638b9da6634SSaqib Khan } 639b9da6634SSaqib Khan } 640b9da6634SSaqib Khan return true; 641b9da6634SSaqib Khan } 642b9da6634SSaqib Khan 643b77551cdSAdriana Kobylak void ItemUpdater::updateUbootEnvVars(const std::string& versionId) 644b77551cdSAdriana Kobylak { 645*25773a7eSAdriana Kobylak auto flashId = versions.find(versionId)->second->path(); 646*25773a7eSAdriana Kobylak helper.updateUbootVersionId(flashId); 647b77551cdSAdriana Kobylak } 648b77551cdSAdriana Kobylak 64949446ae9SSaqib Khan void ItemUpdater::resetUbootEnvVars() 65049446ae9SSaqib Khan { 65149446ae9SSaqib Khan decltype(activations.begin()->second->redundancyPriority.get()->priority()) 65249446ae9SSaqib Khan lowestPriority = std::numeric_limits<uint8_t>::max(); 65349446ae9SSaqib Khan decltype(activations.begin()->second->versionId) lowestPriorityVersion; 65449446ae9SSaqib Khan for (const auto& intf : activations) 65549446ae9SSaqib Khan { 65649446ae9SSaqib Khan if (!intf.second->redundancyPriority.get()) 65749446ae9SSaqib Khan { 65849446ae9SSaqib Khan // Skip this version if the redundancyPriority is not initialized. 65949446ae9SSaqib Khan continue; 66049446ae9SSaqib Khan } 66149446ae9SSaqib Khan 6622285fe0fSAdriana Kobylak if (intf.second->redundancyPriority.get()->priority() <= lowestPriority) 66349446ae9SSaqib Khan { 66449446ae9SSaqib Khan lowestPriority = intf.second->redundancyPriority.get()->priority(); 66549446ae9SSaqib Khan lowestPriorityVersion = intf.second->versionId; 66649446ae9SSaqib Khan } 66749446ae9SSaqib Khan } 66849446ae9SSaqib Khan 669f0382c35SSaqib Khan // Update the U-boot environment variable to point to the lowest priority 670b77551cdSAdriana Kobylak updateUbootEnvVars(lowestPriorityVersion); 67149446ae9SSaqib Khan } 67249446ae9SSaqib Khan 6730cd6d84bSLei YU void ItemUpdater::freeSpace(const Activation& caller) 674204e1e74SAdriana Kobylak { 675204e1e74SAdriana Kobylak // Versions with the highest priority in front 676204e1e74SAdriana Kobylak std::priority_queue<std::pair<int, std::string>, 677204e1e74SAdriana Kobylak std::vector<std::pair<int, std::string>>, 6782285fe0fSAdriana Kobylak std::less<std::pair<int, std::string>>> 6792285fe0fSAdriana Kobylak versionsPQ; 680204e1e74SAdriana Kobylak 681204e1e74SAdriana Kobylak std::size_t count = 0; 682204e1e74SAdriana Kobylak for (const auto& iter : activations) 683204e1e74SAdriana Kobylak { 684204e1e74SAdriana Kobylak if ((iter.second.get()->activation() == 685204e1e74SAdriana Kobylak server::Activation::Activations::Active) || 686204e1e74SAdriana Kobylak (iter.second.get()->activation() == 687204e1e74SAdriana Kobylak server::Activation::Activations::Failed)) 688204e1e74SAdriana Kobylak { 689204e1e74SAdriana Kobylak count++; 690204e1e74SAdriana Kobylak // Don't put the functional version on the queue since we can't 691204e1e74SAdriana Kobylak // remove the "running" BMC version. 6920f88b5afSLei YU // If ACTIVE_BMC_MAX_ALLOWED <= 1, there is only one active BMC, 6930f88b5afSLei YU // so remove functional version as well. 694a6963590SAdriana Kobylak // Don't delete the the Activation object that called this function. 695a6963590SAdriana Kobylak if ((versions.find(iter.second->versionId) 696a6963590SAdriana Kobylak ->second->isFunctional() && 697a6963590SAdriana Kobylak ACTIVE_BMC_MAX_ALLOWED > 1) || 698a6963590SAdriana Kobylak (iter.second->versionId == caller.versionId)) 699204e1e74SAdriana Kobylak { 700204e1e74SAdriana Kobylak continue; 701204e1e74SAdriana Kobylak } 702a6963590SAdriana Kobylak 703a6963590SAdriana Kobylak // Failed activations don't have priority, assign them a large value 704a6963590SAdriana Kobylak // for sorting purposes. 705a6963590SAdriana Kobylak auto priority = 999; 706a6963590SAdriana Kobylak if (iter.second.get()->activation() == 707cfb4b209SLei YU server::Activation::Activations::Active && 708cfb4b209SLei YU iter.second->redundancyPriority) 709a6963590SAdriana Kobylak { 710a6963590SAdriana Kobylak priority = iter.second->redundancyPriority.get()->priority(); 711a6963590SAdriana Kobylak } 712a6963590SAdriana Kobylak 713a6963590SAdriana Kobylak versionsPQ.push(std::make_pair(priority, iter.second->versionId)); 714204e1e74SAdriana Kobylak } 715204e1e74SAdriana Kobylak } 716204e1e74SAdriana Kobylak 717204e1e74SAdriana Kobylak // If the number of BMC versions is over ACTIVE_BMC_MAX_ALLOWED -1, 718204e1e74SAdriana Kobylak // remove the highest priority one(s). 719204e1e74SAdriana Kobylak while ((count >= ACTIVE_BMC_MAX_ALLOWED) && (!versionsPQ.empty())) 720204e1e74SAdriana Kobylak { 721204e1e74SAdriana Kobylak erase(versionsPQ.top().second); 722204e1e74SAdriana Kobylak versionsPQ.pop(); 723204e1e74SAdriana Kobylak count--; 724204e1e74SAdriana Kobylak } 725204e1e74SAdriana Kobylak } 726204e1e74SAdriana Kobylak 727eaa1ee05SEddie James void ItemUpdater::mirrorUbootToAlt() 728eaa1ee05SEddie James { 72956aaf454SLei YU helper.mirrorAlt(); 730eaa1ee05SEddie James } 731eaa1ee05SEddie James 7328e9ccfe7SBright Cheng bool ItemUpdater::checkImage(const std::string& filePath, 7338e9ccfe7SBright Cheng const std::vector<std::string>& imageList) 7348e9ccfe7SBright Cheng { 7358e9ccfe7SBright Cheng bool valid = true; 7368e9ccfe7SBright Cheng 7378e9ccfe7SBright Cheng for (auto& bmcImage : imageList) 7388e9ccfe7SBright Cheng { 7398e9ccfe7SBright Cheng fs::path file(filePath); 7408e9ccfe7SBright Cheng file /= bmcImage; 7418e9ccfe7SBright Cheng std::ifstream efile(file.c_str()); 7428e9ccfe7SBright Cheng if (efile.good() != 1) 7438e9ccfe7SBright Cheng { 7448e9ccfe7SBright Cheng valid = false; 7458e9ccfe7SBright Cheng break; 7468e9ccfe7SBright Cheng } 7478e9ccfe7SBright Cheng } 7488e9ccfe7SBright Cheng 7498e9ccfe7SBright Cheng return valid; 7508e9ccfe7SBright Cheng } 7518e9ccfe7SBright Cheng 7526e9fb1d6SLei YU #ifdef HOST_BIOS_UPGRADE 7536e9fb1d6SLei YU void ItemUpdater::createBIOSObject() 7546e9fb1d6SLei YU { 7556e9fb1d6SLei YU std::string path = BIOS_OBJPATH; 7566e9fb1d6SLei YU // Get version id from last item in the path 7576e9fb1d6SLei YU auto pos = path.rfind("/"); 7586e9fb1d6SLei YU if (pos == std::string::npos) 7596e9fb1d6SLei YU { 760c9bb6425SPatrick Williams error("No version id found in object path {PATH}", "PATH", path); 7616e9fb1d6SLei YU return; 7626e9fb1d6SLei YU } 7636e9fb1d6SLei YU 7646e9fb1d6SLei YU createActiveAssociation(path); 7656e9fb1d6SLei YU createFunctionalAssociation(path); 7666e9fb1d6SLei YU 7676e9fb1d6SLei YU auto versionId = path.substr(pos + 1); 7686e9fb1d6SLei YU auto version = "null"; 7696e9fb1d6SLei YU AssociationList assocs = {}; 7706e9fb1d6SLei YU biosActivation = std::make_unique<Activation>( 7716e9fb1d6SLei YU bus, path, *this, versionId, server::Activation::Activations::Active, 7726e9fb1d6SLei YU assocs); 7736e9fb1d6SLei YU auto dummyErase = [](std::string /*entryId*/) { 7746e9fb1d6SLei YU // Do nothing; 7756e9fb1d6SLei YU }; 7766e9fb1d6SLei YU biosVersion = std::make_unique<VersionClass>( 7776e9fb1d6SLei YU bus, path, version, VersionPurpose::Host, "", "", 7786e9fb1d6SLei YU std::bind(dummyErase, std::placeholders::_1)); 7796e9fb1d6SLei YU biosVersion->deleteObject = 7806e9fb1d6SLei YU std::make_unique<phosphor::software::manager::Delete>(bus, path, 7816e9fb1d6SLei YU *biosVersion); 7826e9fb1d6SLei YU } 7836e9fb1d6SLei YU #endif 7846e9fb1d6SLei YU 785ec1b41c4SGunnar Mills } // namespace updater 786ec1b41c4SGunnar Mills } // namespace software 787ec1b41c4SGunnar Mills } // namespace phosphor 788