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);
366d1a55adcSAdriana Kobylak         this->activations.erase(entryId);
367d1a55adcSAdriana Kobylak     }
368d1a55adcSAdriana Kobylak     ItemUpdater::resetUbootEnvVars();
369d1a55adcSAdriana Kobylak 
370d1a55adcSAdriana Kobylak     if (it != versions.end())
371d1a55adcSAdriana Kobylak     {
3726d873715SEddie James         // Delete ReadOnly partitions if it's not active
3733526ef73SLeonel Gonzalez         removeReadOnlyPartition(entryId);
374687e75e2SAdriana Kobylak         removePersistDataDirectory(entryId);
375ee13e831SSaqib Khan 
376ee13e831SSaqib Khan         // Removing entry in versions map
377ee13e831SSaqib Khan         this->versions.erase(entryId);
3786d873715SEddie James     }
3796d873715SEddie James     else
3806d873715SEddie James     {
3816d873715SEddie James         // Delete ReadOnly partitions even if we can't find the version
3826d873715SEddie James         removeReadOnlyPartition(entryId);
383687e75e2SAdriana Kobylak         removePersistDataDirectory(entryId);
3846d873715SEddie James 
385c9bb6425SPatrick Williams         error(
386c9bb6425SPatrick Williams             "Failed to find version ({VERSIONID}) in item updater versions map; unable to remove.",
387c9bb6425SPatrick Williams             "VERSIONID", entryId);
3886d873715SEddie James     }
3891eef62deSSaqib Khan 
39056aaf454SLei YU     helper.clearEntry(entryId);
3913526ef73SLeonel Gonzalez 
392ee13e831SSaqib Khan     return;
3933526ef73SLeonel Gonzalez }
3943526ef73SLeonel Gonzalez 
395bc1bf3afSMichael Tritz void ItemUpdater::deleteAll()
396bc1bf3afSMichael Tritz {
39783cd21fbSAdriana Kobylak     std::vector<std::string> deletableVersions;
39883cd21fbSAdriana Kobylak 
399bc1bf3afSMichael Tritz     for (const auto& versionIt : versions)
400bc1bf3afSMichael Tritz     {
401bc1bf3afSMichael Tritz         if (!versionIt.second->isFunctional())
402bc1bf3afSMichael Tritz         {
40383cd21fbSAdriana Kobylak             deletableVersions.push_back(versionIt.first);
404bc1bf3afSMichael Tritz         }
405bc1bf3afSMichael Tritz     }
406bc1bf3afSMichael Tritz 
40783cd21fbSAdriana Kobylak     for (const auto& deletableIt : deletableVersions)
40883cd21fbSAdriana Kobylak     {
40983cd21fbSAdriana Kobylak         ItemUpdater::erase(deletableIt);
41083cd21fbSAdriana Kobylak     }
41183cd21fbSAdriana Kobylak 
41256aaf454SLei YU     helper.cleanup();
413bc1bf3afSMichael Tritz }
414bc1bf3afSMichael Tritz 
4152285fe0fSAdriana Kobylak ItemUpdater::ActivationStatus
4162285fe0fSAdriana Kobylak     ItemUpdater::validateSquashFSImage(const std::string& filePath)
41735e83f3eSSaqib Khan {
4188e9ccfe7SBright Cheng     bool valid = true;
41935e83f3eSSaqib Khan 
4208e9ccfe7SBright Cheng     // Record the images which are being updated
4218e9ccfe7SBright Cheng     // First check for the fullimage, then check for images with partitions
4228e9ccfe7SBright Cheng     imageUpdateList.push_back(bmcFullImages);
4238e9ccfe7SBright Cheng     valid = checkImage(filePath, imageUpdateList);
4248e9ccfe7SBright Cheng     if (!valid)
425b1cfdf99SMichael Tritz     {
4268e9ccfe7SBright Cheng         imageUpdateList.clear();
4278e9ccfe7SBright Cheng         imageUpdateList.assign(bmcImages.begin(), bmcImages.end());
4288e9ccfe7SBright Cheng         valid = checkImage(filePath, imageUpdateList);
4298e9ccfe7SBright Cheng         if (!valid)
43035e83f3eSSaqib Khan         {
431c9bb6425SPatrick Williams             error("Failed to find the needed BMC images.");
43235e83f3eSSaqib Khan             return ItemUpdater::ActivationStatus::invalid;
43335e83f3eSSaqib Khan         }
4348e9ccfe7SBright Cheng     }
435b1cfdf99SMichael Tritz 
436b1cfdf99SMichael Tritz     return ItemUpdater::ActivationStatus::ready;
43735e83f3eSSaqib Khan }
43835e83f3eSSaqib Khan 
439bbcb7be1SAdriana Kobylak void ItemUpdater::savePriority(const std::string& versionId, uint8_t value)
440bbcb7be1SAdriana Kobylak {
441687e75e2SAdriana Kobylak     storePriority(versionId, value);
442bbcb7be1SAdriana Kobylak     helper.setEntry(versionId, 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 {
50856aaf454SLei YU     helper.removeVersion(versionId);
5093526ef73SLeonel Gonzalez }
5103526ef73SLeonel Gonzalez 
5110129d926SMichael Tritz bool ItemUpdater::fieldModeEnabled(bool value)
5120129d926SMichael Tritz {
5130129d926SMichael Tritz     // enabling field mode is intended to be one way: false -> true
5140129d926SMichael Tritz     if (value && !control::FieldMode::fieldModeEnabled())
5150129d926SMichael Tritz     {
5160129d926SMichael Tritz         control::FieldMode::fieldModeEnabled(value);
5170129d926SMichael Tritz 
51822848eceSAdriana Kobylak         auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
51922848eceSAdriana Kobylak                                           SYSTEMD_INTERFACE, "StartUnit");
52022848eceSAdriana Kobylak         method.append("obmc-flash-bmc-setenv@fieldmode\\x3dtrue.service",
52122848eceSAdriana Kobylak                       "replace");
52222848eceSAdriana Kobylak         bus.call_noreply(method);
52322848eceSAdriana Kobylak 
52422848eceSAdriana Kobylak         method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
52522848eceSAdriana Kobylak                                      SYSTEMD_INTERFACE, "StopUnit");
52622848eceSAdriana Kobylak         method.append("usr-local.mount", "replace");
52722848eceSAdriana Kobylak         bus.call_noreply(method);
52822848eceSAdriana Kobylak 
52922848eceSAdriana Kobylak         std::vector<std::string> usrLocal = {"usr-local.mount"};
53022848eceSAdriana Kobylak 
53122848eceSAdriana Kobylak         method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
53222848eceSAdriana Kobylak                                      SYSTEMD_INTERFACE, "MaskUnitFiles");
53322848eceSAdriana Kobylak         method.append(usrLocal, false, true);
53422848eceSAdriana Kobylak         bus.call_noreply(method);
5350129d926SMichael Tritz     }
536d5b8f75cSAdriana Kobylak     else if (!value && control::FieldMode::fieldModeEnabled())
537d5b8f75cSAdriana Kobylak     {
538d5b8f75cSAdriana Kobylak         elog<NotAllowed>(xyz::openbmc_project::Common::NotAllowed::REASON(
539d5b8f75cSAdriana Kobylak             "FieldMode is not allowed to be cleared"));
540d5b8f75cSAdriana Kobylak     }
5410129d926SMichael Tritz 
5420129d926SMichael Tritz     return control::FieldMode::fieldModeEnabled();
5430129d926SMichael Tritz }
5440129d926SMichael Tritz 
5450129d926SMichael Tritz void ItemUpdater::restoreFieldModeStatus()
5460129d926SMichael Tritz {
547ff0b421dSMichael Tritz     std::ifstream input("/dev/mtd/u-boot-env");
5480129d926SMichael Tritz     std::string envVar;
5490129d926SMichael Tritz     std::getline(input, envVar);
5500129d926SMichael Tritz 
5510129d926SMichael Tritz     if (envVar.find("fieldmode=true") != std::string::npos)
5520129d926SMichael Tritz     {
5530129d926SMichael Tritz         ItemUpdater::fieldModeEnabled(true);
5540129d926SMichael Tritz     }
5550129d926SMichael Tritz }
5560129d926SMichael Tritz 
557b60add1eSGunnar Mills void ItemUpdater::setBMCInventoryPath()
558b60add1eSGunnar Mills {
559b60add1eSGunnar Mills     auto depth = 0;
5602285fe0fSAdriana Kobylak     auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
5612285fe0fSAdriana Kobylak                                           MAPPER_INTERFACE, "GetSubTreePaths");
562b60add1eSGunnar Mills 
5631254c628SAdriana Kobylak     mapperCall.append(INVENTORY_PATH);
564b60add1eSGunnar Mills     mapperCall.append(depth);
5651254c628SAdriana Kobylak     std::vector<std::string> filter = {BMC_INVENTORY_INTERFACE};
566b60add1eSGunnar Mills     mapperCall.append(filter);
567b60add1eSGunnar Mills 
56887c78173SEd Tanous     try
569b60add1eSGunnar Mills     {
57087c78173SEd Tanous         auto response = bus.call(mapperCall);
571b60add1eSGunnar Mills 
572b60add1eSGunnar Mills         using ObjectPaths = std::vector<std::string>;
573b60add1eSGunnar Mills         ObjectPaths result;
574b60add1eSGunnar Mills         response.read(result);
575b60add1eSGunnar Mills 
5761254c628SAdriana Kobylak         if (!result.empty())
577b60add1eSGunnar Mills         {
5781254c628SAdriana Kobylak             bmcInventoryPath = result.front();
579b60add1eSGunnar Mills         }
58087c78173SEd Tanous     }
581*4ce901c5SPatrick Williams     catch (const sdbusplus::exception::exception& e)
58287c78173SEd Tanous     {
583c9bb6425SPatrick Williams         error("Error in mapper GetSubTreePath: {ERROR}", "ERROR", e);
58487c78173SEd Tanous         return;
58587c78173SEd Tanous     }
586b60add1eSGunnar Mills 
587b60add1eSGunnar Mills     return;
588b60add1eSGunnar Mills }
589b60add1eSGunnar Mills 
590f10b2326SGunnar Mills void ItemUpdater::createActiveAssociation(const std::string& path)
591ded875dcSGunnar Mills {
5922285fe0fSAdriana Kobylak     assocs.emplace_back(
5932285fe0fSAdriana Kobylak         std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path));
594ded875dcSGunnar Mills     associations(assocs);
595ded875dcSGunnar Mills }
596ded875dcSGunnar Mills 
59788e8a325SGunnar Mills void ItemUpdater::createFunctionalAssociation(const std::string& path)
59888e8a325SGunnar Mills {
59988e8a325SGunnar Mills     assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION,
6002285fe0fSAdriana Kobylak                                         FUNCTIONAL_REV_ASSOCIATION, path));
60188e8a325SGunnar Mills     associations(assocs);
60288e8a325SGunnar Mills }
60388e8a325SGunnar Mills 
604bbebec79SAppaRao Puli void ItemUpdater::createUpdateableAssociation(const std::string& path)
605bbebec79SAppaRao Puli {
606bbebec79SAppaRao Puli     assocs.emplace_back(std::make_tuple(UPDATEABLE_FWD_ASSOCIATION,
607bbebec79SAppaRao Puli                                         UPDATEABLE_REV_ASSOCIATION, path));
608bbebec79SAppaRao Puli     associations(assocs);
609bbebec79SAppaRao Puli }
610bbebec79SAppaRao Puli 
611991af7ecSAdriana Kobylak void ItemUpdater::removeAssociations(const std::string& path)
612ded875dcSGunnar Mills {
613ded875dcSGunnar Mills     for (auto iter = assocs.begin(); iter != assocs.end();)
614ded875dcSGunnar Mills     {
615991af7ecSAdriana Kobylak         if ((std::get<2>(*iter)).compare(path) == 0)
616ded875dcSGunnar Mills         {
617ded875dcSGunnar Mills             iter = assocs.erase(iter);
618ded875dcSGunnar Mills             associations(assocs);
619ded875dcSGunnar Mills         }
620ded875dcSGunnar Mills         else
621ded875dcSGunnar Mills         {
622ded875dcSGunnar Mills             ++iter;
623ded875dcSGunnar Mills         }
624ded875dcSGunnar Mills     }
625ded875dcSGunnar Mills }
626ded875dcSGunnar Mills 
627b9da6634SSaqib Khan bool ItemUpdater::isLowestPriority(uint8_t value)
628b9da6634SSaqib Khan {
629b9da6634SSaqib Khan     for (const auto& intf : activations)
630b9da6634SSaqib Khan     {
631b9da6634SSaqib Khan         if (intf.second->redundancyPriority)
632b9da6634SSaqib Khan         {
633b9da6634SSaqib Khan             if (intf.second->redundancyPriority.get()->priority() < value)
634b9da6634SSaqib Khan             {
635b9da6634SSaqib Khan                 return false;
636b9da6634SSaqib Khan             }
637b9da6634SSaqib Khan         }
638b9da6634SSaqib Khan     }
639b9da6634SSaqib Khan     return true;
640b9da6634SSaqib Khan }
641b9da6634SSaqib Khan 
642b77551cdSAdriana Kobylak void ItemUpdater::updateUbootEnvVars(const std::string& versionId)
643b77551cdSAdriana Kobylak {
64456aaf454SLei YU     helper.updateUbootVersionId(versionId);
645b77551cdSAdriana Kobylak }
646b77551cdSAdriana Kobylak 
64749446ae9SSaqib Khan void ItemUpdater::resetUbootEnvVars()
64849446ae9SSaqib Khan {
64949446ae9SSaqib Khan     decltype(activations.begin()->second->redundancyPriority.get()->priority())
65049446ae9SSaqib Khan         lowestPriority = std::numeric_limits<uint8_t>::max();
65149446ae9SSaqib Khan     decltype(activations.begin()->second->versionId) lowestPriorityVersion;
65249446ae9SSaqib Khan     for (const auto& intf : activations)
65349446ae9SSaqib Khan     {
65449446ae9SSaqib Khan         if (!intf.second->redundancyPriority.get())
65549446ae9SSaqib Khan         {
65649446ae9SSaqib Khan             // Skip this version if the redundancyPriority is not initialized.
65749446ae9SSaqib Khan             continue;
65849446ae9SSaqib Khan         }
65949446ae9SSaqib Khan 
6602285fe0fSAdriana Kobylak         if (intf.second->redundancyPriority.get()->priority() <= lowestPriority)
66149446ae9SSaqib Khan         {
66249446ae9SSaqib Khan             lowestPriority = intf.second->redundancyPriority.get()->priority();
66349446ae9SSaqib Khan             lowestPriorityVersion = intf.second->versionId;
66449446ae9SSaqib Khan         }
66549446ae9SSaqib Khan     }
66649446ae9SSaqib Khan 
667f0382c35SSaqib Khan     // Update the U-boot environment variable to point to the lowest priority
668b77551cdSAdriana Kobylak     updateUbootEnvVars(lowestPriorityVersion);
66949446ae9SSaqib Khan }
67049446ae9SSaqib Khan 
671a6963590SAdriana Kobylak void ItemUpdater::freeSpace(Activation& caller)
672204e1e74SAdriana Kobylak {
673204e1e74SAdriana Kobylak     //  Versions with the highest priority in front
674204e1e74SAdriana Kobylak     std::priority_queue<std::pair<int, std::string>,
675204e1e74SAdriana Kobylak                         std::vector<std::pair<int, std::string>>,
6762285fe0fSAdriana Kobylak                         std::less<std::pair<int, std::string>>>
6772285fe0fSAdriana Kobylak         versionsPQ;
678204e1e74SAdriana Kobylak 
679204e1e74SAdriana Kobylak     std::size_t count = 0;
680204e1e74SAdriana Kobylak     for (const auto& iter : activations)
681204e1e74SAdriana Kobylak     {
682204e1e74SAdriana Kobylak         if ((iter.second.get()->activation() ==
683204e1e74SAdriana Kobylak              server::Activation::Activations::Active) ||
684204e1e74SAdriana Kobylak             (iter.second.get()->activation() ==
685204e1e74SAdriana Kobylak              server::Activation::Activations::Failed))
686204e1e74SAdriana Kobylak         {
687204e1e74SAdriana Kobylak             count++;
688204e1e74SAdriana Kobylak             // Don't put the functional version on the queue since we can't
689204e1e74SAdriana Kobylak             // remove the "running" BMC version.
6900f88b5afSLei YU             // If ACTIVE_BMC_MAX_ALLOWED <= 1, there is only one active BMC,
6910f88b5afSLei YU             // so remove functional version as well.
692a6963590SAdriana Kobylak             // Don't delete the the Activation object that called this function.
693a6963590SAdriana Kobylak             if ((versions.find(iter.second->versionId)
694a6963590SAdriana Kobylak                      ->second->isFunctional() &&
695a6963590SAdriana Kobylak                  ACTIVE_BMC_MAX_ALLOWED > 1) ||
696a6963590SAdriana Kobylak                 (iter.second->versionId == caller.versionId))
697204e1e74SAdriana Kobylak             {
698204e1e74SAdriana Kobylak                 continue;
699204e1e74SAdriana Kobylak             }
700a6963590SAdriana Kobylak 
701a6963590SAdriana Kobylak             // Failed activations don't have priority, assign them a large value
702a6963590SAdriana Kobylak             // for sorting purposes.
703a6963590SAdriana Kobylak             auto priority = 999;
704a6963590SAdriana Kobylak             if (iter.second.get()->activation() ==
705cfb4b209SLei YU                     server::Activation::Activations::Active &&
706cfb4b209SLei YU                 iter.second->redundancyPriority)
707a6963590SAdriana Kobylak             {
708a6963590SAdriana Kobylak                 priority = iter.second->redundancyPriority.get()->priority();
709a6963590SAdriana Kobylak             }
710a6963590SAdriana Kobylak 
711a6963590SAdriana Kobylak             versionsPQ.push(std::make_pair(priority, iter.second->versionId));
712204e1e74SAdriana Kobylak         }
713204e1e74SAdriana Kobylak     }
714204e1e74SAdriana Kobylak 
715204e1e74SAdriana Kobylak     // If the number of BMC versions is over ACTIVE_BMC_MAX_ALLOWED -1,
716204e1e74SAdriana Kobylak     // remove the highest priority one(s).
717204e1e74SAdriana Kobylak     while ((count >= ACTIVE_BMC_MAX_ALLOWED) && (!versionsPQ.empty()))
718204e1e74SAdriana Kobylak     {
719204e1e74SAdriana Kobylak         erase(versionsPQ.top().second);
720204e1e74SAdriana Kobylak         versionsPQ.pop();
721204e1e74SAdriana Kobylak         count--;
722204e1e74SAdriana Kobylak     }
723204e1e74SAdriana Kobylak }
724204e1e74SAdriana Kobylak 
725eaa1ee05SEddie James void ItemUpdater::mirrorUbootToAlt()
726eaa1ee05SEddie James {
72756aaf454SLei YU     helper.mirrorAlt();
728eaa1ee05SEddie James }
729eaa1ee05SEddie James 
7308e9ccfe7SBright Cheng bool ItemUpdater::checkImage(const std::string& filePath,
7318e9ccfe7SBright Cheng                              const std::vector<std::string>& imageList)
7328e9ccfe7SBright Cheng {
7338e9ccfe7SBright Cheng     bool valid = true;
7348e9ccfe7SBright Cheng 
7358e9ccfe7SBright Cheng     for (auto& bmcImage : imageList)
7368e9ccfe7SBright Cheng     {
7378e9ccfe7SBright Cheng         fs::path file(filePath);
7388e9ccfe7SBright Cheng         file /= bmcImage;
7398e9ccfe7SBright Cheng         std::ifstream efile(file.c_str());
7408e9ccfe7SBright Cheng         if (efile.good() != 1)
7418e9ccfe7SBright Cheng         {
7428e9ccfe7SBright Cheng             valid = false;
7438e9ccfe7SBright Cheng             break;
7448e9ccfe7SBright Cheng         }
7458e9ccfe7SBright Cheng     }
7468e9ccfe7SBright Cheng 
7478e9ccfe7SBright Cheng     return valid;
7488e9ccfe7SBright Cheng }
7498e9ccfe7SBright Cheng 
7506e9fb1d6SLei YU #ifdef HOST_BIOS_UPGRADE
7516e9fb1d6SLei YU void ItemUpdater::createBIOSObject()
7526e9fb1d6SLei YU {
7536e9fb1d6SLei YU     std::string path = BIOS_OBJPATH;
7546e9fb1d6SLei YU     // Get version id from last item in the path
7556e9fb1d6SLei YU     auto pos = path.rfind("/");
7566e9fb1d6SLei YU     if (pos == std::string::npos)
7576e9fb1d6SLei YU     {
758c9bb6425SPatrick Williams         error("No version id found in object path {PATH}", "PATH", path);
7596e9fb1d6SLei YU         return;
7606e9fb1d6SLei YU     }
7616e9fb1d6SLei YU 
7626e9fb1d6SLei YU     createActiveAssociation(path);
7636e9fb1d6SLei YU     createFunctionalAssociation(path);
7646e9fb1d6SLei YU 
7656e9fb1d6SLei YU     auto versionId = path.substr(pos + 1);
7666e9fb1d6SLei YU     auto version = "null";
7676e9fb1d6SLei YU     AssociationList assocs = {};
7686e9fb1d6SLei YU     biosActivation = std::make_unique<Activation>(
7696e9fb1d6SLei YU         bus, path, *this, versionId, server::Activation::Activations::Active,
7706e9fb1d6SLei YU         assocs);
7716e9fb1d6SLei YU     auto dummyErase = [](std::string /*entryId*/) {
7726e9fb1d6SLei YU         // Do nothing;
7736e9fb1d6SLei YU     };
7746e9fb1d6SLei YU     biosVersion = std::make_unique<VersionClass>(
7756e9fb1d6SLei YU         bus, path, version, VersionPurpose::Host, "", "",
7766e9fb1d6SLei YU         std::bind(dummyErase, std::placeholders::_1));
7776e9fb1d6SLei YU     biosVersion->deleteObject =
7786e9fb1d6SLei YU         std::make_unique<phosphor::software::manager::Delete>(bus, path,
7796e9fb1d6SLei YU                                                               *biosVersion);
7806e9fb1d6SLei YU }
7816e9fb1d6SLei YU #endif
7826e9fb1d6SLei YU 
783ec1b41c4SGunnar Mills } // namespace updater
784ec1b41c4SGunnar Mills } // namespace software
785ec1b41c4SGunnar Mills } // namespace phosphor
786