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 2301eef62deSSaqib Khan auto purpose = server::Version::VersionPurpose::BMC; 231ec4eec34SAdriana Kobylak restorePurpose(id, purpose); 232ec4eec34SAdriana Kobylak 2331fd6dddfSChanh Nguyen // Read os-release from /etc/ to get the BMC extended version 2341fd6dddfSChanh Nguyen std::string extendedVersion = 2351fd6dddfSChanh Nguyen VersionClass::getBMCExtendedVersion(osRelease); 2361fd6dddfSChanh Nguyen 2371eef62deSSaqib Khan auto path = fs::path(SOFTWARE_OBJPATH) / id; 2381eef62deSSaqib Khan 239269bff30SLei YU // Create functional association if this is the functional 240269bff30SLei YU // version 24188e8a325SGunnar Mills if (version.compare(functionalVersion) == 0) 24288e8a325SGunnar Mills { 24388e8a325SGunnar Mills createFunctionalAssociation(path); 24488e8a325SGunnar Mills } 24588e8a325SGunnar Mills 24643b25cdeSGunnar Mills AssociationList associations = {}; 24743b25cdeSGunnar Mills 24843b25cdeSGunnar Mills if (activationState == server::Activation::Activations::Active) 24943b25cdeSGunnar Mills { 25043b25cdeSGunnar Mills // Create an association to the BMC inventory item 25143b25cdeSGunnar Mills associations.emplace_back(std::make_tuple( 2522285fe0fSAdriana Kobylak ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION, 25343b25cdeSGunnar Mills bmcInventoryPath)); 25443b25cdeSGunnar Mills 25543b25cdeSGunnar Mills // Create an active association since this image is active 25643b25cdeSGunnar Mills createActiveAssociation(path); 25743b25cdeSGunnar Mills } 25843b25cdeSGunnar Mills 259bbebec79SAppaRao Puli // All updateable firmware components must expose the updateable 260bbebec79SAppaRao Puli // association. 261bbebec79SAppaRao Puli createUpdateableAssociation(path); 262bbebec79SAppaRao Puli 263ee590c74SAdriana Kobylak // Create Version instance for this version. 264ee590c74SAdriana Kobylak auto versionPtr = std::make_unique<VersionClass>( 2651fd6dddfSChanh Nguyen bus, path, version, purpose, extendedVersion, "", 2662285fe0fSAdriana Kobylak std::bind(&ItemUpdater::erase, this, std::placeholders::_1)); 267ee590c74SAdriana Kobylak auto isVersionFunctional = versionPtr->isFunctional(); 268ee13e831SSaqib Khan if (!isVersionFunctional) 269ee13e831SSaqib Khan { 270ee13e831SSaqib Khan versionPtr->deleteObject = 271ee13e831SSaqib Khan std::make_unique<phosphor::software::manager::Delete>( 272ee13e831SSaqib Khan bus, path, *versionPtr); 273ee13e831SSaqib Khan } 2742285fe0fSAdriana Kobylak versions.insert(std::make_pair(id, std::move(versionPtr))); 275ee590c74SAdriana Kobylak 2761eef62deSSaqib Khan // Create Activation instance for this version. 277ee13e831SSaqib Khan activations.insert(std::make_pair( 2782285fe0fSAdriana Kobylak id, std::make_unique<Activation>( 2792285fe0fSAdriana Kobylak bus, path, *this, id, activationState, associations))); 2801eef62deSSaqib Khan 281269bff30SLei YU // If Active, create RedundancyPriority instance for this 282269bff30SLei YU // version. 2831eef62deSSaqib Khan if (activationState == server::Activation::Activations::Active) 2841eef62deSSaqib Khan { 2851eef62deSSaqib Khan uint8_t priority = std::numeric_limits<uint8_t>::max(); 286687e75e2SAdriana Kobylak if (!restorePriority(id, priority)) 2871eef62deSSaqib Khan { 288ee590c74SAdriana Kobylak if (isVersionFunctional) 289ee590c74SAdriana Kobylak { 290ee590c74SAdriana Kobylak priority = 0; 291ee590c74SAdriana Kobylak } 292ee590c74SAdriana Kobylak else 293ee590c74SAdriana Kobylak { 294c9bb6425SPatrick Williams error( 295c9bb6425SPatrick Williams "Unable to restore priority from file for {VERSIONID}", 296c9bb6425SPatrick Williams "VERSIONID", id); 2971eef62deSSaqib Khan } 298ee590c74SAdriana Kobylak } 2991eef62deSSaqib Khan activations.find(id)->second->redundancyPriority = 3001eef62deSSaqib Khan std::make_unique<RedundancyPriority>( 3012285fe0fSAdriana Kobylak bus, path, *(activations.find(id)->second), priority, 302b77551cdSAdriana Kobylak false); 3031eef62deSSaqib Khan } 3041eef62deSSaqib Khan } 3051eef62deSSaqib Khan } 306dcbfa04aSSaqib Khan 307716cd78dSAdriana Kobylak // If there are no bmc versions mounted under MEDIA_DIR, then read the 308716cd78dSAdriana Kobylak // /etc/os-release and create rofs-<versionId> under MEDIA_DIR, then call 309716cd78dSAdriana Kobylak // again processBMCImage() to create the D-Bus interface for it. 310dcbfa04aSSaqib Khan if (activations.size() == 0) 311dcbfa04aSSaqib Khan { 312d16bcbd5SGunnar Mills auto version = VersionClass::getBMCVersion(OS_RELEASE_FILE); 313dcbfa04aSSaqib Khan auto id = phosphor::software::manager::Version::getId(version); 314dcbfa04aSSaqib Khan auto versionFileDir = BMC_ROFS_PREFIX + id + "/etc/"; 315dcbfa04aSSaqib Khan try 316dcbfa04aSSaqib Khan { 317dcbfa04aSSaqib Khan if (!fs::is_directory(versionFileDir)) 318dcbfa04aSSaqib Khan { 319dcbfa04aSSaqib Khan fs::create_directories(versionFileDir); 320dcbfa04aSSaqib Khan } 321dcbfa04aSSaqib Khan auto versionFilePath = BMC_ROFS_PREFIX + id + OS_RELEASE_FILE; 322dcbfa04aSSaqib Khan fs::create_directory_symlink(OS_RELEASE_FILE, versionFilePath); 323dcbfa04aSSaqib Khan ItemUpdater::processBMCImage(); 324dcbfa04aSSaqib Khan } 325dcbfa04aSSaqib Khan catch (const std::exception& e) 326dcbfa04aSSaqib Khan { 327c9bb6425SPatrick Williams error("Exception during processing: {ERROR}", "ERROR", e); 328dcbfa04aSSaqib Khan } 329dcbfa04aSSaqib Khan } 330eaa1ee05SEddie James 331eaa1ee05SEddie James mirrorUbootToAlt(); 332ba239881SSaqib Khan return; 333ba239881SSaqib Khan } 334ba239881SSaqib Khan 3353526ef73SLeonel Gonzalez void ItemUpdater::erase(std::string entryId) 3363526ef73SLeonel Gonzalez { 3376d873715SEddie James // Find entry in versions map 3386d873715SEddie James auto it = versions.find(entryId); 3396d873715SEddie James if (it != versions.end()) 3406d873715SEddie James { 3410f88b5afSLei YU if (it->second->isFunctional() && ACTIVE_BMC_MAX_ALLOWED > 1) 3426d873715SEddie James { 343c9bb6425SPatrick Williams error( 344c9bb6425SPatrick Williams "Version ({VERSIONID}) is currently running on the BMC; unable to remove.", 345c9bb6425SPatrick Williams "VERSIONID", entryId); 3466d873715SEddie James return; 3476d873715SEddie James } 348d1a55adcSAdriana Kobylak } 3496d873715SEddie James 350d1a55adcSAdriana Kobylak // First call resetUbootEnvVars() so that the BMC points to a valid image to 351d1a55adcSAdriana Kobylak // boot from. If resetUbootEnvVars() is called after the image is actually 352d1a55adcSAdriana Kobylak // deleted from the BMC flash, there'd be a time window where the BMC would 353d1a55adcSAdriana Kobylak // be pointing to a non-existent image to boot from. 354d1a55adcSAdriana Kobylak // Need to remove the entries from the activations map before that call so 355d1a55adcSAdriana Kobylak // that resetUbootEnvVars() doesn't use the version to be deleted. 356d1a55adcSAdriana Kobylak auto iteratorActivations = activations.find(entryId); 357d1a55adcSAdriana Kobylak if (iteratorActivations == activations.end()) 358d1a55adcSAdriana Kobylak { 359c9bb6425SPatrick Williams error( 360c9bb6425SPatrick Williams "Failed to find version ({VERSIONID}) in item updater activations map; unable to remove.", 361c9bb6425SPatrick Williams "VERSIONID", entryId); 362d1a55adcSAdriana Kobylak } 363d1a55adcSAdriana Kobylak else 364d1a55adcSAdriana Kobylak { 365d1a55adcSAdriana Kobylak removeAssociations(iteratorActivations->second->path); 366ae06d76aSZami Seck iteratorActivations->second->deleteImageManagerObject(); 367d1a55adcSAdriana Kobylak this->activations.erase(entryId); 368d1a55adcSAdriana Kobylak } 369d1a55adcSAdriana Kobylak ItemUpdater::resetUbootEnvVars(); 370d1a55adcSAdriana Kobylak 371d1a55adcSAdriana Kobylak if (it != versions.end()) 372d1a55adcSAdriana Kobylak { 3736d873715SEddie James // Delete ReadOnly partitions if it's not active 3743526ef73SLeonel Gonzalez removeReadOnlyPartition(entryId); 375687e75e2SAdriana Kobylak removePersistDataDirectory(entryId); 376ee13e831SSaqib Khan 377ee13e831SSaqib Khan // Removing entry in versions map 378ee13e831SSaqib Khan this->versions.erase(entryId); 3796d873715SEddie James } 3806d873715SEddie James else 3816d873715SEddie James { 3826d873715SEddie James // Delete ReadOnly partitions even if we can't find the version 3836d873715SEddie James removeReadOnlyPartition(entryId); 384687e75e2SAdriana Kobylak removePersistDataDirectory(entryId); 3856d873715SEddie James 386c9bb6425SPatrick Williams error( 387c9bb6425SPatrick Williams "Failed to find version ({VERSIONID}) in item updater versions map; unable to remove.", 388c9bb6425SPatrick Williams "VERSIONID", entryId); 3896d873715SEddie James } 3901eef62deSSaqib Khan 39156aaf454SLei YU helper.clearEntry(entryId); 3923526ef73SLeonel Gonzalez 393ee13e831SSaqib Khan return; 3943526ef73SLeonel Gonzalez } 3953526ef73SLeonel Gonzalez 396bc1bf3afSMichael Tritz void ItemUpdater::deleteAll() 397bc1bf3afSMichael Tritz { 39883cd21fbSAdriana Kobylak std::vector<std::string> deletableVersions; 39983cd21fbSAdriana Kobylak 400bc1bf3afSMichael Tritz for (const auto& versionIt : versions) 401bc1bf3afSMichael Tritz { 402bc1bf3afSMichael Tritz if (!versionIt.second->isFunctional()) 403bc1bf3afSMichael Tritz { 40483cd21fbSAdriana Kobylak deletableVersions.push_back(versionIt.first); 405bc1bf3afSMichael Tritz } 406bc1bf3afSMichael Tritz } 407bc1bf3afSMichael Tritz 40883cd21fbSAdriana Kobylak for (const auto& deletableIt : deletableVersions) 40983cd21fbSAdriana Kobylak { 41083cd21fbSAdriana Kobylak ItemUpdater::erase(deletableIt); 41183cd21fbSAdriana Kobylak } 41283cd21fbSAdriana Kobylak 41356aaf454SLei YU helper.cleanup(); 414bc1bf3afSMichael Tritz } 415bc1bf3afSMichael Tritz 4162285fe0fSAdriana Kobylak ItemUpdater::ActivationStatus 4172285fe0fSAdriana Kobylak ItemUpdater::validateSquashFSImage(const std::string& filePath) 41835e83f3eSSaqib Khan { 4198e9ccfe7SBright Cheng bool valid = true; 42035e83f3eSSaqib Khan 4218e9ccfe7SBright Cheng // Record the images which are being updated 4228e9ccfe7SBright Cheng // First check for the fullimage, then check for images with partitions 4238e9ccfe7SBright Cheng imageUpdateList.push_back(bmcFullImages); 4248e9ccfe7SBright Cheng valid = checkImage(filePath, imageUpdateList); 4258e9ccfe7SBright Cheng if (!valid) 426b1cfdf99SMichael Tritz { 4278e9ccfe7SBright Cheng imageUpdateList.clear(); 4288e9ccfe7SBright Cheng imageUpdateList.assign(bmcImages.begin(), bmcImages.end()); 4298e9ccfe7SBright Cheng valid = checkImage(filePath, imageUpdateList); 4308e9ccfe7SBright Cheng if (!valid) 43135e83f3eSSaqib Khan { 432c9bb6425SPatrick Williams error("Failed to find the needed BMC images."); 43335e83f3eSSaqib Khan return ItemUpdater::ActivationStatus::invalid; 43435e83f3eSSaqib Khan } 4358e9ccfe7SBright Cheng } 436b1cfdf99SMichael Tritz 437b1cfdf99SMichael Tritz return ItemUpdater::ActivationStatus::ready; 43835e83f3eSSaqib Khan } 43935e83f3eSSaqib Khan 440bbcb7be1SAdriana Kobylak void ItemUpdater::savePriority(const std::string& versionId, uint8_t value) 441bbcb7be1SAdriana Kobylak { 442687e75e2SAdriana Kobylak storePriority(versionId, value); 443bbcb7be1SAdriana Kobylak helper.setEntry(versionId, value); 444bbcb7be1SAdriana Kobylak } 445bbcb7be1SAdriana Kobylak 446b9da6634SSaqib Khan void ItemUpdater::freePriority(uint8_t value, const std::string& versionId) 4474c1aec09SSaqib Khan { 448b77551cdSAdriana Kobylak std::map<std::string, uint8_t> priorityMap; 449b77551cdSAdriana Kobylak 450b77551cdSAdriana Kobylak // Insert the requested version and priority, it may not exist yet. 451b77551cdSAdriana Kobylak priorityMap.insert(std::make_pair(versionId, value)); 452b77551cdSAdriana Kobylak 4534c1aec09SSaqib Khan for (const auto& intf : activations) 4544c1aec09SSaqib Khan { 4554c1aec09SSaqib Khan if (intf.second->redundancyPriority) 4564c1aec09SSaqib Khan { 457b77551cdSAdriana Kobylak priorityMap.insert(std::make_pair( 4582285fe0fSAdriana Kobylak intf.first, intf.second->redundancyPriority.get()->priority())); 459b77551cdSAdriana Kobylak } 460b77551cdSAdriana Kobylak } 461b77551cdSAdriana Kobylak 462b77551cdSAdriana Kobylak // Lambda function to compare 2 priority values, use <= to allow duplicates 4632285fe0fSAdriana Kobylak typedef std::function<bool(std::pair<std::string, uint8_t>, 4642285fe0fSAdriana Kobylak std::pair<std::string, uint8_t>)> 4652285fe0fSAdriana Kobylak cmpPriority; 4662285fe0fSAdriana Kobylak cmpPriority cmpPriorityFunc = 4672285fe0fSAdriana Kobylak [](std::pair<std::string, uint8_t> priority1, 4682285fe0fSAdriana Kobylak std::pair<std::string, uint8_t> priority2) { 469b77551cdSAdriana Kobylak return priority1.second <= priority2.second; 470b77551cdSAdriana Kobylak }; 471b77551cdSAdriana Kobylak 472b77551cdSAdriana Kobylak // Sort versions by ascending priority 473b77551cdSAdriana Kobylak std::set<std::pair<std::string, uint8_t>, cmpPriority> prioritySet( 474b77551cdSAdriana Kobylak priorityMap.begin(), priorityMap.end(), cmpPriorityFunc); 475b77551cdSAdriana Kobylak 476b77551cdSAdriana Kobylak auto freePriorityValue = value; 477b77551cdSAdriana Kobylak for (auto& element : prioritySet) 478b77551cdSAdriana Kobylak { 479b77551cdSAdriana Kobylak if (element.first == versionId) 480b77551cdSAdriana Kobylak { 481b77551cdSAdriana Kobylak continue; 482b77551cdSAdriana Kobylak } 483b77551cdSAdriana Kobylak if (element.second == freePriorityValue) 484b77551cdSAdriana Kobylak { 485b77551cdSAdriana Kobylak ++freePriorityValue; 486b77551cdSAdriana Kobylak auto it = activations.find(element.first); 487b77551cdSAdriana Kobylak it->second->redundancyPriority.get()->sdbusPriority( 488b77551cdSAdriana Kobylak freePriorityValue); 4894c1aec09SSaqib Khan } 4904c1aec09SSaqib Khan } 491b77551cdSAdriana Kobylak 492b77551cdSAdriana Kobylak auto lowestVersion = prioritySet.begin()->first; 493b77551cdSAdriana Kobylak if (value == prioritySet.begin()->second) 494b77551cdSAdriana Kobylak { 495b77551cdSAdriana Kobylak lowestVersion = versionId; 4964c1aec09SSaqib Khan } 497b77551cdSAdriana Kobylak updateUbootEnvVars(lowestVersion); 4984c1aec09SSaqib Khan } 4994c1aec09SSaqib Khan 50037a59043SMichael Tritz void ItemUpdater::reset() 50137a59043SMichael Tritz { 50256aaf454SLei YU helper.factoryReset(); 50337a59043SMichael Tritz 504c9bb6425SPatrick Williams info("BMC factory reset will take effect upon reboot."); 50537a59043SMichael Tritz } 50637a59043SMichael Tritz 5073526ef73SLeonel Gonzalez void ItemUpdater::removeReadOnlyPartition(std::string versionId) 5083526ef73SLeonel Gonzalez { 50956aaf454SLei YU helper.removeVersion(versionId); 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 { 64556aaf454SLei YU helper.updateUbootVersionId(versionId); 646b77551cdSAdriana Kobylak } 647b77551cdSAdriana Kobylak 64849446ae9SSaqib Khan void ItemUpdater::resetUbootEnvVars() 64949446ae9SSaqib Khan { 65049446ae9SSaqib Khan decltype(activations.begin()->second->redundancyPriority.get()->priority()) 65149446ae9SSaqib Khan lowestPriority = std::numeric_limits<uint8_t>::max(); 65249446ae9SSaqib Khan decltype(activations.begin()->second->versionId) lowestPriorityVersion; 65349446ae9SSaqib Khan for (const auto& intf : activations) 65449446ae9SSaqib Khan { 65549446ae9SSaqib Khan if (!intf.second->redundancyPriority.get()) 65649446ae9SSaqib Khan { 65749446ae9SSaqib Khan // Skip this version if the redundancyPriority is not initialized. 65849446ae9SSaqib Khan continue; 65949446ae9SSaqib Khan } 66049446ae9SSaqib Khan 6612285fe0fSAdriana Kobylak if (intf.second->redundancyPriority.get()->priority() <= lowestPriority) 66249446ae9SSaqib Khan { 66349446ae9SSaqib Khan lowestPriority = intf.second->redundancyPriority.get()->priority(); 66449446ae9SSaqib Khan lowestPriorityVersion = intf.second->versionId; 66549446ae9SSaqib Khan } 66649446ae9SSaqib Khan } 66749446ae9SSaqib Khan 668f0382c35SSaqib Khan // Update the U-boot environment variable to point to the lowest priority 669b77551cdSAdriana Kobylak updateUbootEnvVars(lowestPriorityVersion); 67049446ae9SSaqib Khan } 67149446ae9SSaqib Khan 672*0cd6d84bSLei YU void ItemUpdater::freeSpace(const Activation& caller) 673204e1e74SAdriana Kobylak { 674204e1e74SAdriana Kobylak // Versions with the highest priority in front 675204e1e74SAdriana Kobylak std::priority_queue<std::pair<int, std::string>, 676204e1e74SAdriana Kobylak std::vector<std::pair<int, std::string>>, 6772285fe0fSAdriana Kobylak std::less<std::pair<int, std::string>>> 6782285fe0fSAdriana Kobylak versionsPQ; 679204e1e74SAdriana Kobylak 680204e1e74SAdriana Kobylak std::size_t count = 0; 681204e1e74SAdriana Kobylak for (const auto& iter : activations) 682204e1e74SAdriana Kobylak { 683204e1e74SAdriana Kobylak if ((iter.second.get()->activation() == 684204e1e74SAdriana Kobylak server::Activation::Activations::Active) || 685204e1e74SAdriana Kobylak (iter.second.get()->activation() == 686204e1e74SAdriana Kobylak server::Activation::Activations::Failed)) 687204e1e74SAdriana Kobylak { 688204e1e74SAdriana Kobylak count++; 689204e1e74SAdriana Kobylak // Don't put the functional version on the queue since we can't 690204e1e74SAdriana Kobylak // remove the "running" BMC version. 6910f88b5afSLei YU // If ACTIVE_BMC_MAX_ALLOWED <= 1, there is only one active BMC, 6920f88b5afSLei YU // so remove functional version as well. 693a6963590SAdriana Kobylak // Don't delete the the Activation object that called this function. 694a6963590SAdriana Kobylak if ((versions.find(iter.second->versionId) 695a6963590SAdriana Kobylak ->second->isFunctional() && 696a6963590SAdriana Kobylak ACTIVE_BMC_MAX_ALLOWED > 1) || 697a6963590SAdriana Kobylak (iter.second->versionId == caller.versionId)) 698204e1e74SAdriana Kobylak { 699204e1e74SAdriana Kobylak continue; 700204e1e74SAdriana Kobylak } 701a6963590SAdriana Kobylak 702a6963590SAdriana Kobylak // Failed activations don't have priority, assign them a large value 703a6963590SAdriana Kobylak // for sorting purposes. 704a6963590SAdriana Kobylak auto priority = 999; 705a6963590SAdriana Kobylak if (iter.second.get()->activation() == 706cfb4b209SLei YU server::Activation::Activations::Active && 707cfb4b209SLei YU iter.second->redundancyPriority) 708a6963590SAdriana Kobylak { 709a6963590SAdriana Kobylak priority = iter.second->redundancyPriority.get()->priority(); 710a6963590SAdriana Kobylak } 711a6963590SAdriana Kobylak 712a6963590SAdriana Kobylak versionsPQ.push(std::make_pair(priority, iter.second->versionId)); 713204e1e74SAdriana Kobylak } 714204e1e74SAdriana Kobylak } 715204e1e74SAdriana Kobylak 716204e1e74SAdriana Kobylak // If the number of BMC versions is over ACTIVE_BMC_MAX_ALLOWED -1, 717204e1e74SAdriana Kobylak // remove the highest priority one(s). 718204e1e74SAdriana Kobylak while ((count >= ACTIVE_BMC_MAX_ALLOWED) && (!versionsPQ.empty())) 719204e1e74SAdriana Kobylak { 720204e1e74SAdriana Kobylak erase(versionsPQ.top().second); 721204e1e74SAdriana Kobylak versionsPQ.pop(); 722204e1e74SAdriana Kobylak count--; 723204e1e74SAdriana Kobylak } 724204e1e74SAdriana Kobylak } 725204e1e74SAdriana Kobylak 726eaa1ee05SEddie James void ItemUpdater::mirrorUbootToAlt() 727eaa1ee05SEddie James { 72856aaf454SLei YU helper.mirrorAlt(); 729eaa1ee05SEddie James } 730eaa1ee05SEddie James 7318e9ccfe7SBright Cheng bool ItemUpdater::checkImage(const std::string& filePath, 7328e9ccfe7SBright Cheng const std::vector<std::string>& imageList) 7338e9ccfe7SBright Cheng { 7348e9ccfe7SBright Cheng bool valid = true; 7358e9ccfe7SBright Cheng 7368e9ccfe7SBright Cheng for (auto& bmcImage : imageList) 7378e9ccfe7SBright Cheng { 7388e9ccfe7SBright Cheng fs::path file(filePath); 7398e9ccfe7SBright Cheng file /= bmcImage; 7408e9ccfe7SBright Cheng std::ifstream efile(file.c_str()); 7418e9ccfe7SBright Cheng if (efile.good() != 1) 7428e9ccfe7SBright Cheng { 7438e9ccfe7SBright Cheng valid = false; 7448e9ccfe7SBright Cheng break; 7458e9ccfe7SBright Cheng } 7468e9ccfe7SBright Cheng } 7478e9ccfe7SBright Cheng 7488e9ccfe7SBright Cheng return valid; 7498e9ccfe7SBright Cheng } 7508e9ccfe7SBright Cheng 7516e9fb1d6SLei YU #ifdef HOST_BIOS_UPGRADE 7526e9fb1d6SLei YU void ItemUpdater::createBIOSObject() 7536e9fb1d6SLei YU { 7546e9fb1d6SLei YU std::string path = BIOS_OBJPATH; 7556e9fb1d6SLei YU // Get version id from last item in the path 7566e9fb1d6SLei YU auto pos = path.rfind("/"); 7576e9fb1d6SLei YU if (pos == std::string::npos) 7586e9fb1d6SLei YU { 759c9bb6425SPatrick Williams error("No version id found in object path {PATH}", "PATH", path); 7606e9fb1d6SLei YU return; 7616e9fb1d6SLei YU } 7626e9fb1d6SLei YU 7636e9fb1d6SLei YU createActiveAssociation(path); 7646e9fb1d6SLei YU createFunctionalAssociation(path); 7656e9fb1d6SLei YU 7666e9fb1d6SLei YU auto versionId = path.substr(pos + 1); 7676e9fb1d6SLei YU auto version = "null"; 7686e9fb1d6SLei YU AssociationList assocs = {}; 7696e9fb1d6SLei YU biosActivation = std::make_unique<Activation>( 7706e9fb1d6SLei YU bus, path, *this, versionId, server::Activation::Activations::Active, 7716e9fb1d6SLei YU assocs); 7726e9fb1d6SLei YU auto dummyErase = [](std::string /*entryId*/) { 7736e9fb1d6SLei YU // Do nothing; 7746e9fb1d6SLei YU }; 7756e9fb1d6SLei YU biosVersion = std::make_unique<VersionClass>( 7766e9fb1d6SLei YU bus, path, version, VersionPurpose::Host, "", "", 7776e9fb1d6SLei YU std::bind(dummyErase, std::placeholders::_1)); 7786e9fb1d6SLei YU biosVersion->deleteObject = 7796e9fb1d6SLei YU std::make_unique<phosphor::software::manager::Delete>(bus, path, 7806e9fb1d6SLei YU *biosVersion); 7816e9fb1d6SLei YU } 7826e9fb1d6SLei YU #endif 7836e9fb1d6SLei YU 784ec1b41c4SGunnar Mills } // namespace updater 785ec1b41c4SGunnar Mills } // namespace software 786ec1b41c4SGunnar Mills } // namespace phosphor 787