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