135e83f3eSSaqib Khan #include <fstream>
2ec1b41c4SGunnar Mills #include <string>
32ce7da29SGunnar Mills #include <phosphor-logging/log.hpp>
4ec1b41c4SGunnar Mills #include "config.h"
52ce7da29SGunnar Mills #include "item_updater.hpp"
62ce7da29SGunnar Mills #include "xyz/openbmc_project/Software/Version/server.hpp"
735e83f3eSSaqib Khan #include <experimental/filesystem>
8705f1bfcSSaqib Khan #include "version.hpp"
95d532675SSaqib Khan #include "serialize.hpp"
10ec1b41c4SGunnar Mills 
11ec1b41c4SGunnar Mills namespace phosphor
12ec1b41c4SGunnar Mills {
13ec1b41c4SGunnar Mills namespace software
14ec1b41c4SGunnar Mills {
15ec1b41c4SGunnar Mills namespace updater
16ec1b41c4SGunnar Mills {
17ec1b41c4SGunnar Mills 
182ce7da29SGunnar Mills // When you see server:: you know we're referencing our base class
192ce7da29SGunnar Mills namespace server = sdbusplus::xyz::openbmc_project::Software::server;
200129d926SMichael Tritz namespace control = sdbusplus::xyz::openbmc_project::Control::server;
212ce7da29SGunnar Mills 
222ce7da29SGunnar Mills using namespace phosphor::logging;
2335e83f3eSSaqib Khan namespace fs = std::experimental::filesystem;
2435e83f3eSSaqib Khan 
25b1cfdf99SMichael Tritz const std::vector<std::string> bmcImages = { "image-kernel",
26b1cfdf99SMichael Tritz                                              "image-rofs",
27b1cfdf99SMichael Tritz                                              "image-rwfs",
28b1cfdf99SMichael Tritz                                              "image-u-boot" };
292ce7da29SGunnar Mills 
30e75d10f5SPatrick Williams void ItemUpdater::createActivation(sdbusplus::message::message& msg)
31ec1b41c4SGunnar Mills {
3284a0e693SSaqib Khan 
3384a0e693SSaqib Khan     using SVersion = server::Version;
3484a0e693SSaqib Khan     using VersionPurpose = SVersion::VersionPurpose;
359a782243SGunnar Mills     using VersionClass = phosphor::software::manager::Version;
3684a0e693SSaqib Khan     namespace mesg = sdbusplus::message;
3784a0e693SSaqib Khan     namespace variant_ns = mesg::variant_ns;
3884a0e693SSaqib Khan 
3984a0e693SSaqib Khan     mesg::object_path objPath;
4084a0e693SSaqib Khan     auto purpose = VersionPurpose::Unknown;
41705f1bfcSSaqib Khan     std::string version;
422ce7da29SGunnar Mills     std::map<std::string,
432ce7da29SGunnar Mills              std::map<std::string,
4484a0e693SSaqib Khan                       mesg::variant<std::string>>> interfaces;
45e75d10f5SPatrick Williams     msg.read(objPath, interfaces);
462ce7da29SGunnar Mills     std::string path(std::move(objPath));
4719177d3eSSaqib Khan     std::string filePath;
482ce7da29SGunnar Mills 
492ce7da29SGunnar Mills     for (const auto& intf : interfaces)
502ce7da29SGunnar Mills     {
51705f1bfcSSaqib Khan         if (intf.first == VERSION_IFACE)
522ce7da29SGunnar Mills         {
532ce7da29SGunnar Mills             for (const auto& property : intf.second)
542ce7da29SGunnar Mills             {
55705f1bfcSSaqib Khan                 if (property.first == "Purpose")
562ce7da29SGunnar Mills                 {
5784a0e693SSaqib Khan                     auto value = SVersion::convertVersionPurposeFromString(
5884a0e693SSaqib Khan                             variant_ns::get<std::string>(property.second));
5984a0e693SSaqib Khan                     if (value == VersionPurpose::BMC ||
6084a0e693SSaqib Khan                         value == VersionPurpose::System)
6184a0e693SSaqib Khan                     {
6284a0e693SSaqib Khan                         purpose = value;
6384a0e693SSaqib Khan                     }
64705f1bfcSSaqib Khan                 }
65705f1bfcSSaqib Khan                 else if (property.first == "Version")
66705f1bfcSSaqib Khan                 {
6784a0e693SSaqib Khan                     version = variant_ns::get<std::string>(property.second);
68705f1bfcSSaqib Khan                 }
69705f1bfcSSaqib Khan             }
70705f1bfcSSaqib Khan         }
7119177d3eSSaqib Khan         else if (intf.first == FILEPATH_IFACE)
7219177d3eSSaqib Khan         {
7319177d3eSSaqib Khan             for (const auto& property : intf.second)
7419177d3eSSaqib Khan             {
7519177d3eSSaqib Khan                 if (property.first == "Path")
7619177d3eSSaqib Khan                 {
7784a0e693SSaqib Khan                     filePath = variant_ns::get<std::string>(property.second);
7819177d3eSSaqib Khan                 }
7919177d3eSSaqib Khan             }
8019177d3eSSaqib Khan         }
81705f1bfcSSaqib Khan     }
82705f1bfcSSaqib Khan     if (version.empty() ||
8319177d3eSSaqib Khan         filePath.empty() ||
8484a0e693SSaqib Khan         purpose == VersionPurpose::Unknown)
852ce7da29SGunnar Mills     {
86e75d10f5SPatrick Williams         return;
872ce7da29SGunnar Mills     }
882ce7da29SGunnar Mills 
892ce7da29SGunnar Mills     // Version id is the last item in the path
902ce7da29SGunnar Mills     auto pos = path.rfind("/");
912ce7da29SGunnar Mills     if (pos == std::string::npos)
922ce7da29SGunnar Mills     {
932ce7da29SGunnar Mills         log<level::ERR>("No version id found in object path",
942ce7da29SGunnar Mills                         entry("OBJPATH=%s", path));
95e75d10f5SPatrick Williams         return;
962ce7da29SGunnar Mills     }
972ce7da29SGunnar Mills 
982ce7da29SGunnar Mills     auto versionId = path.substr(pos + 1);
992ce7da29SGunnar Mills 
100e75d10f5SPatrick Williams     if (activations.find(versionId) == activations.end())
1012ce7da29SGunnar Mills     {
10235e83f3eSSaqib Khan         // Determine the Activation state by processing the given image dir.
10335e83f3eSSaqib Khan         auto activationState = server::Activation::Activations::Invalid;
1049a782243SGunnar Mills         ItemUpdater::ActivationStatus result =
1059a782243SGunnar Mills                 ItemUpdater::validateSquashFSImage(filePath);
10643b25cdeSGunnar Mills         AssociationList associations = {};
10743b25cdeSGunnar Mills 
10835e83f3eSSaqib Khan         if (result == ItemUpdater::ActivationStatus::ready)
10935e83f3eSSaqib Khan         {
11035e83f3eSSaqib Khan             activationState = server::Activation::Activations::Ready;
111b60add1eSGunnar Mills             // Create an association to the BMC inventory item
11243b25cdeSGunnar Mills             associations.emplace_back(std::make_tuple(
113b60add1eSGunnar Mills                                               ACTIVATION_FWD_ASSOCIATION,
114b60add1eSGunnar Mills                                               ACTIVATION_REV_ASSOCIATION,
11543b25cdeSGunnar Mills                                               bmcInventoryPath));
11643b25cdeSGunnar Mills         }
117b60add1eSGunnar Mills 
11835e83f3eSSaqib Khan         activations.insert(std::make_pair(
1192ce7da29SGunnar Mills                                versionId,
120ec1b41c4SGunnar Mills                                std::make_unique<Activation>(
12135e83f3eSSaqib Khan                                         bus,
12235e83f3eSSaqib Khan                                         path,
1234c1aec09SSaqib Khan                                         *this,
12435e83f3eSSaqib Khan                                         versionId,
125b60add1eSGunnar Mills                                         activationState,
126b60add1eSGunnar Mills                                         associations)));
127705f1bfcSSaqib Khan         versions.insert(std::make_pair(
128705f1bfcSSaqib Khan                             versionId,
1299a782243SGunnar Mills                             std::make_unique<VersionClass>(
130705f1bfcSSaqib Khan                                 bus,
131705f1bfcSSaqib Khan                                 path,
132705f1bfcSSaqib Khan                                 version,
133705f1bfcSSaqib Khan                                 purpose,
1349440f491SEddie James                                 filePath)));
1352ce7da29SGunnar Mills     }
1367b5010f2SSaqib Khan     else
1377b5010f2SSaqib Khan     {
1387b5010f2SSaqib Khan         log<level::INFO>("Software Object with the same version already exists",
1397b5010f2SSaqib Khan                          entry("VERSION_ID=%s", versionId));
1407b5010f2SSaqib Khan     }
141e75d10f5SPatrick Williams     return;
142ec1b41c4SGunnar Mills }
143ec1b41c4SGunnar Mills 
144ba239881SSaqib Khan void ItemUpdater::processBMCImage()
145ba239881SSaqib Khan {
14688e8a325SGunnar Mills     using VersionClass = phosphor::software::manager::Version;
14788e8a325SGunnar Mills     // Read os-release from /etc/ to get the functional BMC version
14888e8a325SGunnar Mills     auto functionalVersion = VersionClass::getBMCVersion(OS_RELEASE_FILE);
14988e8a325SGunnar Mills 
1501eef62deSSaqib Khan     // Read os-release from folders under /media/ to get
1511eef62deSSaqib Khan     // BMC Software Versions.
1521eef62deSSaqib Khan     for(const auto& iter : fs::directory_iterator(MEDIA_DIR))
1531eef62deSSaqib Khan     {
1541eef62deSSaqib Khan         auto activationState = server::Activation::Activations::Active;
1556fab70daSSaqib Khan         static const auto BMC_RO_PREFIX_LEN = strlen(BMC_ROFS_PREFIX);
1561eef62deSSaqib Khan 
1571eef62deSSaqib Khan         // Check if the BMC_RO_PREFIXis the prefix of the iter.path
1581eef62deSSaqib Khan         if (0 == iter.path().native().compare(0, BMC_RO_PREFIX_LEN,
1596fab70daSSaqib Khan                                               BMC_ROFS_PREFIX))
1601eef62deSSaqib Khan         {
1611eef62deSSaqib Khan             auto osRelease = iter.path() / OS_RELEASE_FILE;
1621eef62deSSaqib Khan             if (!fs::is_regular_file(osRelease))
1631eef62deSSaqib Khan             {
1641eef62deSSaqib Khan                 log<level::ERR>("Failed to read osRelease\n",
1651eef62deSSaqib Khan                                 entry("FileName=%s", osRelease.string()));
1661eef62deSSaqib Khan                 activationState = server::Activation::Activations::Invalid;
1671eef62deSSaqib Khan             }
16888e8a325SGunnar Mills             auto version = VersionClass::getBMCVersion(osRelease);
1691eef62deSSaqib Khan             if (version.empty())
1701eef62deSSaqib Khan             {
1711eef62deSSaqib Khan                 log<level::ERR>("Failed to read version from osRelease",
1721eef62deSSaqib Khan                                 entry("FILENAME=%s", osRelease.string()));
1731eef62deSSaqib Khan                 activationState = server::Activation::Activations::Invalid;
1741eef62deSSaqib Khan             }
1751eef62deSSaqib Khan             // The versionId is extracted from the path
1761eef62deSSaqib Khan             // for example /media/ro-2a1022fe
1771eef62deSSaqib Khan             auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
1781eef62deSSaqib Khan             auto purpose = server::Version::VersionPurpose::BMC;
1791eef62deSSaqib Khan             auto path = fs::path(SOFTWARE_OBJPATH) / id;
1801eef62deSSaqib Khan 
18188e8a325SGunnar Mills             // Create functional association if this is the functional version
18288e8a325SGunnar Mills             if (version.compare(functionalVersion) == 0)
18388e8a325SGunnar Mills             {
18488e8a325SGunnar Mills                 createFunctionalAssociation(path);
18588e8a325SGunnar Mills             }
18688e8a325SGunnar Mills 
18743b25cdeSGunnar Mills             AssociationList associations = {};
18843b25cdeSGunnar Mills 
18943b25cdeSGunnar Mills             if (activationState == server::Activation::Activations::Active)
19043b25cdeSGunnar Mills             {
19143b25cdeSGunnar Mills                 // Create an association to the BMC inventory item
19243b25cdeSGunnar Mills                 associations.emplace_back(std::make_tuple(
19343b25cdeSGunnar Mills                                                   ACTIVATION_FWD_ASSOCIATION,
19443b25cdeSGunnar Mills                                                   ACTIVATION_REV_ASSOCIATION,
19543b25cdeSGunnar Mills                                                   bmcInventoryPath));
19643b25cdeSGunnar Mills 
19743b25cdeSGunnar Mills                 // Create an active association since this image is active
19843b25cdeSGunnar Mills                 createActiveAssociation(path);
19943b25cdeSGunnar Mills             }
20043b25cdeSGunnar Mills 
2011eef62deSSaqib Khan             // Create Activation instance for this version.
202ba239881SSaqib Khan             activations.insert(std::make_pair(
203ba239881SSaqib Khan                                    id,
204ba239881SSaqib Khan                                    std::make_unique<Activation>(
205ba239881SSaqib Khan                                        bus,
206ba239881SSaqib Khan                                        path,
2074c1aec09SSaqib Khan                                        *this,
208ba239881SSaqib Khan                                        id,
209b60add1eSGunnar Mills                                        server::Activation::Activations::Active,
210b60add1eSGunnar Mills                                        associations)));
2111eef62deSSaqib Khan 
2121eef62deSSaqib Khan             // If Active, create RedundancyPriority instance for this version.
2131eef62deSSaqib Khan             if (activationState == server::Activation::Activations::Active)
2141eef62deSSaqib Khan             {
2151eef62deSSaqib Khan                 uint8_t priority = std::numeric_limits<uint8_t>::max();
2161eef62deSSaqib Khan                 if (!restoreFromFile(id, priority))
2171eef62deSSaqib Khan                 {
2181eef62deSSaqib Khan                     log<level::ERR>("Unable to restore priority from file.",
2191eef62deSSaqib Khan                             entry("VERSIONID=%s", id));
2201eef62deSSaqib Khan                 }
2211eef62deSSaqib Khan                 activations.find(id)->second->redundancyPriority =
2221eef62deSSaqib Khan                         std::make_unique<RedundancyPriority>(
2231eef62deSSaqib Khan                              bus,
2241eef62deSSaqib Khan                              path,
2251eef62deSSaqib Khan                              *(activations.find(id)->second),
2261eef62deSSaqib Khan                              priority);
2271eef62deSSaqib Khan             }
2281eef62deSSaqib Khan 
2291eef62deSSaqib Khan             // Create Version instance for this version.
230ba239881SSaqib Khan             versions.insert(std::make_pair(
231ba239881SSaqib Khan                                 id,
2321eef62deSSaqib Khan                                 std::make_unique<
2331eef62deSSaqib Khan                                      phosphor::software::manager::Version>(
234ba239881SSaqib Khan                                      bus,
235ba239881SSaqib Khan                                      path,
236ba239881SSaqib Khan                                      version,
237ba239881SSaqib Khan                                      purpose,
2389440f491SEddie James                                      "")));
2391eef62deSSaqib Khan         }
2401eef62deSSaqib Khan     }
241ba239881SSaqib Khan     return;
242ba239881SSaqib Khan }
243ba239881SSaqib Khan 
2443526ef73SLeonel Gonzalez void ItemUpdater::erase(std::string entryId)
2453526ef73SLeonel Gonzalez {
2466d873715SEddie James     // Find entry in versions map
2476d873715SEddie James     auto it = versions.find(entryId);
2486d873715SEddie James     if (it != versions.end())
2496d873715SEddie James     {
2506d873715SEddie James         if (it->second->isFunctional())
2516d873715SEddie James         {
2526d873715SEddie James             log<level::ERR>(("Error: Version " + entryId + \
2536d873715SEddie James                              " is currently running on the BMC." \
2546d873715SEddie James                              " Unable to remove.").c_str());
2556d873715SEddie James              return;
2566d873715SEddie James         }
2576d873715SEddie James 
2586d873715SEddie James         // Delete ReadOnly partitions if it's not active
2593526ef73SLeonel Gonzalez         removeReadOnlyPartition(entryId);
2601eef62deSSaqib Khan         removeFile(entryId);
2616d873715SEddie James     }
2626d873715SEddie James     else
2636d873715SEddie James     {
2646d873715SEddie James         // Delete ReadOnly partitions even if we can't find the version
2656d873715SEddie James         removeReadOnlyPartition(entryId);
2666d873715SEddie James         removeFile(entryId);
2676d873715SEddie James 
2686d873715SEddie James         log<level::ERR>(("Error: Failed to find version " + entryId + \
2696d873715SEddie James                          " in item updater versions map." \
2706d873715SEddie James                          " Unable to remove.").c_str());
2716d873715SEddie James         return;
2726d873715SEddie James     }
2731eef62deSSaqib Khan 
2741eef62deSSaqib Khan     // Remove the priority environment variable.
2751eef62deSSaqib Khan     auto serviceFile = "obmc-flash-bmc-setenv@" + entryId + ".service";
2761eef62deSSaqib Khan     auto method = bus.new_method_call(
2771eef62deSSaqib Khan             SYSTEMD_BUSNAME,
2781eef62deSSaqib Khan             SYSTEMD_PATH,
2791eef62deSSaqib Khan             SYSTEMD_INTERFACE,
2801eef62deSSaqib Khan             "StartUnit");
2811eef62deSSaqib Khan     method.append(serviceFile, "replace");
2821eef62deSSaqib Khan     bus.call_noreply(method);
2833526ef73SLeonel Gonzalez 
2843526ef73SLeonel Gonzalez     // Removing entry in versions map
2853526ef73SLeonel Gonzalez     this->versions.erase(entryId);
2863526ef73SLeonel Gonzalez 
2873526ef73SLeonel Gonzalez     // Removing entry in activations map
2883526ef73SLeonel Gonzalez     auto ita = activations.find(entryId);
2893526ef73SLeonel Gonzalez     if (ita == activations.end())
2903526ef73SLeonel Gonzalez     {
2913526ef73SLeonel Gonzalez         log<level::ERR>(("Error: Failed to find version " + entryId + \
2923526ef73SLeonel Gonzalez                          " in item updater activations map." \
2933526ef73SLeonel Gonzalez                          " Unable to remove.").c_str());
2943526ef73SLeonel Gonzalez         return;
2953526ef73SLeonel Gonzalez     }
2963526ef73SLeonel Gonzalez 
2973526ef73SLeonel Gonzalez     this->activations.erase(entryId);
2983526ef73SLeonel Gonzalez }
2993526ef73SLeonel Gonzalez 
30035e83f3eSSaqib Khan ItemUpdater::ActivationStatus ItemUpdater::validateSquashFSImage(
30119177d3eSSaqib Khan         const std::string& filePath)
30235e83f3eSSaqib Khan {
303b1cfdf99SMichael Tritz     bool invalid = false;
30435e83f3eSSaqib Khan 
305b1cfdf99SMichael Tritz     for (auto& bmcImage : bmcImages)
306b1cfdf99SMichael Tritz     {
30719177d3eSSaqib Khan         fs::path file(filePath);
30835e83f3eSSaqib Khan         file /= bmcImage;
30935e83f3eSSaqib Khan         std::ifstream efile(file.c_str());
310b1cfdf99SMichael Tritz         if (efile.good() != 1)
31135e83f3eSSaqib Khan         {
312b1cfdf99SMichael Tritz             log<level::ERR>("Failed to find the BMC image.",
313b1cfdf99SMichael Tritz                             entry("IMAGE=%s", bmcImage.c_str()));
314b1cfdf99SMichael Tritz             invalid = true;
31535e83f3eSSaqib Khan         }
316b1cfdf99SMichael Tritz     }
317b1cfdf99SMichael Tritz 
318b1cfdf99SMichael Tritz     if (invalid)
31935e83f3eSSaqib Khan     {
32035e83f3eSSaqib Khan         return ItemUpdater::ActivationStatus::invalid;
32135e83f3eSSaqib Khan     }
322b1cfdf99SMichael Tritz 
323b1cfdf99SMichael Tritz     return ItemUpdater::ActivationStatus::ready;
32435e83f3eSSaqib Khan }
32535e83f3eSSaqib Khan 
326*b9da6634SSaqib Khan void ItemUpdater::freePriority(uint8_t value, const std::string& versionId)
3274c1aec09SSaqib Khan {
3284c1aec09SSaqib Khan     //TODO openbmc/openbmc#1896 Improve the performance of this function
3294c1aec09SSaqib Khan     for (const auto& intf : activations)
3304c1aec09SSaqib Khan     {
3314c1aec09SSaqib Khan         if (intf.second->redundancyPriority)
3324c1aec09SSaqib Khan         {
333*b9da6634SSaqib Khan             if (intf.second->redundancyPriority.get()->priority() == value &&
334*b9da6634SSaqib Khan                 intf.second->versionId != versionId)
3354c1aec09SSaqib Khan             {
3364c1aec09SSaqib Khan                 intf.second->redundancyPriority.get()->priority(value + 1);
3374c1aec09SSaqib Khan             }
3384c1aec09SSaqib Khan         }
3394c1aec09SSaqib Khan     }
3404c1aec09SSaqib Khan }
3414c1aec09SSaqib Khan 
34237a59043SMichael Tritz void ItemUpdater::reset()
34337a59043SMichael Tritz {
34437a59043SMichael Tritz     // Mark the read-write partition for recreation upon reboot.
34537a59043SMichael Tritz     auto method = bus.new_method_call(
34637a59043SMichael Tritz             SYSTEMD_BUSNAME,
34737a59043SMichael Tritz             SYSTEMD_PATH,
34837a59043SMichael Tritz             SYSTEMD_INTERFACE,
34937a59043SMichael Tritz             "StartUnit");
3500129d926SMichael Tritz     method.append("obmc-flash-bmc-setenv@rwreset\\x3dtrue.service", "replace");
35137a59043SMichael Tritz     bus.call_noreply(method);
35237a59043SMichael Tritz 
35337a59043SMichael Tritz     log<level::INFO>("BMC factory reset will take effect upon reboot.");
35437a59043SMichael Tritz 
35537a59043SMichael Tritz     return;
35637a59043SMichael Tritz }
35737a59043SMichael Tritz 
3583526ef73SLeonel Gonzalez void ItemUpdater::removeReadOnlyPartition(std::string versionId)
3593526ef73SLeonel Gonzalez {
3603526ef73SLeonel Gonzalez     auto serviceFile = "obmc-flash-bmc-ubiro-remove@" + versionId +
3613526ef73SLeonel Gonzalez             ".service";
3623526ef73SLeonel Gonzalez 
3633526ef73SLeonel Gonzalez     // Remove the read-only partitions.
3643526ef73SLeonel Gonzalez     auto method = bus.new_method_call(
3653526ef73SLeonel Gonzalez             SYSTEMD_BUSNAME,
3663526ef73SLeonel Gonzalez             SYSTEMD_PATH,
3673526ef73SLeonel Gonzalez             SYSTEMD_INTERFACE,
3683526ef73SLeonel Gonzalez             "StartUnit");
3693526ef73SLeonel Gonzalez     method.append(serviceFile, "replace");
3703526ef73SLeonel Gonzalez     bus.call_noreply(method);
3713526ef73SLeonel Gonzalez }
3723526ef73SLeonel Gonzalez 
3730129d926SMichael Tritz bool ItemUpdater::fieldModeEnabled(bool value)
3740129d926SMichael Tritz {
3750129d926SMichael Tritz     // enabling field mode is intended to be one way: false -> true
3760129d926SMichael Tritz     if (value && !control::FieldMode::fieldModeEnabled())
3770129d926SMichael Tritz     {
3780129d926SMichael Tritz         control::FieldMode::fieldModeEnabled(value);
3790129d926SMichael Tritz 
3800129d926SMichael Tritz         auto method = bus.new_method_call(
3810129d926SMichael Tritz                 SYSTEMD_BUSNAME,
3820129d926SMichael Tritz                 SYSTEMD_PATH,
3830129d926SMichael Tritz                 SYSTEMD_INTERFACE,
3840129d926SMichael Tritz                 "StartUnit");
3850129d926SMichael Tritz         method.append("obmc-flash-bmc-setenv@fieldmode\\x3dtrue.service",
3860129d926SMichael Tritz                       "replace");
3870129d926SMichael Tritz         bus.call_noreply(method);
3880129d926SMichael Tritz 
3890129d926SMichael Tritz         method = bus.new_method_call(
3900129d926SMichael Tritz                 SYSTEMD_BUSNAME,
3910129d926SMichael Tritz                 SYSTEMD_PATH,
3920129d926SMichael Tritz                 SYSTEMD_INTERFACE,
3930129d926SMichael Tritz                 "StopUnit");
3940129d926SMichael Tritz         method.append("usr-local.mount", "replace");
3950129d926SMichael Tritz         bus.call_noreply(method);
3960129d926SMichael Tritz 
3970129d926SMichael Tritz         std::vector<std::string> usrLocal = {"usr-local.mount"};
3980129d926SMichael Tritz 
3990129d926SMichael Tritz         method = bus.new_method_call(
4000129d926SMichael Tritz                 SYSTEMD_BUSNAME,
4010129d926SMichael Tritz                 SYSTEMD_PATH,
4020129d926SMichael Tritz                 SYSTEMD_INTERFACE,
4030129d926SMichael Tritz                 "MaskUnitFiles");
4040129d926SMichael Tritz         method.append(usrLocal, false, true);
4050129d926SMichael Tritz         bus.call_noreply(method);
4060129d926SMichael Tritz     }
4070129d926SMichael Tritz 
4080129d926SMichael Tritz     return control::FieldMode::fieldModeEnabled();
4090129d926SMichael Tritz }
4100129d926SMichael Tritz 
4110129d926SMichael Tritz void ItemUpdater::restoreFieldModeStatus()
4120129d926SMichael Tritz {
4130129d926SMichael Tritz     std::ifstream input("/run/fw_env");
4140129d926SMichael Tritz     std::string envVar;
4150129d926SMichael Tritz     std::getline(input, envVar);
4160129d926SMichael Tritz 
4170129d926SMichael Tritz     if (envVar.find("fieldmode=true") != std::string::npos)
4180129d926SMichael Tritz     {
4190129d926SMichael Tritz         ItemUpdater::fieldModeEnabled(true);
4200129d926SMichael Tritz     }
4210129d926SMichael Tritz }
4220129d926SMichael Tritz 
423b60add1eSGunnar Mills void ItemUpdater::setBMCInventoryPath()
424b60add1eSGunnar Mills {
425b60add1eSGunnar Mills     //TODO: openbmc/openbmc#1786 - Get the BMC path by looking for objects
426b60add1eSGunnar Mills     //      that implement the BMC inventory interface
427b60add1eSGunnar Mills     auto depth = 0;
428b60add1eSGunnar Mills     auto mapperCall = bus.new_method_call(MAPPER_BUSNAME,
429b60add1eSGunnar Mills                                           MAPPER_PATH,
430b60add1eSGunnar Mills                                           MAPPER_INTERFACE,
431b60add1eSGunnar Mills                                           "GetSubTreePaths");
432b60add1eSGunnar Mills 
433b60add1eSGunnar Mills     mapperCall.append(CHASSIS_INVENTORY_PATH);
434b60add1eSGunnar Mills     mapperCall.append(depth);
435b60add1eSGunnar Mills 
436b60add1eSGunnar Mills     // TODO: openbmc/openbmc#2226 - Add Inventory Item filter when
437b60add1eSGunnar Mills     //       mapper is fixed.
438b60add1eSGunnar Mills     std::vector<std::string> filter = {};
439b60add1eSGunnar Mills     mapperCall.append(filter);
440b60add1eSGunnar Mills 
441b60add1eSGunnar Mills     auto response = bus.call(mapperCall);
442b60add1eSGunnar Mills     if (response.is_method_error())
443b60add1eSGunnar Mills     {
444b60add1eSGunnar Mills         log<level::ERR>("Error in mapper GetSubTreePath");
445b60add1eSGunnar Mills         return;
446b60add1eSGunnar Mills     }
447b60add1eSGunnar Mills 
448b60add1eSGunnar Mills     using ObjectPaths = std::vector<std::string>;
449b60add1eSGunnar Mills     ObjectPaths result;
450b60add1eSGunnar Mills     response.read(result);
451b60add1eSGunnar Mills 
452b60add1eSGunnar Mills     if (result.empty())
453b60add1eSGunnar Mills     {
454b60add1eSGunnar Mills         log<level::ERR>("Invalid response from mapper");
455b60add1eSGunnar Mills         return;
456b60add1eSGunnar Mills     }
457b60add1eSGunnar Mills 
458b60add1eSGunnar Mills     for (auto& iter : result)
459b60add1eSGunnar Mills     {
460b60add1eSGunnar Mills         const auto& path = iter;
461b60add1eSGunnar Mills         if (path.substr(path.find_last_of('/') + 1).compare("bmc") == 0)
462b60add1eSGunnar Mills         {
463b60add1eSGunnar Mills             bmcInventoryPath = path;
464b60add1eSGunnar Mills             return;
465b60add1eSGunnar Mills         }
466b60add1eSGunnar Mills     }
467b60add1eSGunnar Mills }
468b60add1eSGunnar Mills 
469f10b2326SGunnar Mills void ItemUpdater::createActiveAssociation(const std::string& path)
470ded875dcSGunnar Mills {
471ded875dcSGunnar Mills     assocs.emplace_back(std::make_tuple(ACTIVE_FWD_ASSOCIATION,
472ded875dcSGunnar Mills                                         ACTIVE_REV_ASSOCIATION,
473ded875dcSGunnar Mills                                         path));
474ded875dcSGunnar Mills     associations(assocs);
475ded875dcSGunnar Mills }
476ded875dcSGunnar Mills 
47788e8a325SGunnar Mills void ItemUpdater::createFunctionalAssociation(const std::string& path)
47888e8a325SGunnar Mills {
47988e8a325SGunnar Mills     assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION,
48088e8a325SGunnar Mills                                         FUNCTIONAL_REV_ASSOCIATION,
48188e8a325SGunnar Mills                                         path));
48288e8a325SGunnar Mills     associations(assocs);
48388e8a325SGunnar Mills }
48488e8a325SGunnar Mills 
485f10b2326SGunnar Mills void ItemUpdater::removeActiveAssociation(const std::string& path)
486ded875dcSGunnar Mills {
487ded875dcSGunnar Mills     for (auto iter = assocs.begin(); iter != assocs.end();)
488ded875dcSGunnar Mills     {
48988e8a325SGunnar Mills         // Since there could be multiple associations to the same path,
49088e8a325SGunnar Mills         // only remove ones that have an active forward association.
49188e8a325SGunnar Mills         if ((std::get<0>(*iter)).compare(ACTIVE_FWD_ASSOCIATION) == 0 &&
49288e8a325SGunnar Mills             (std::get<2>(*iter)).compare(path) == 0)
493ded875dcSGunnar Mills         {
494ded875dcSGunnar Mills             iter = assocs.erase(iter);
495ded875dcSGunnar Mills             associations(assocs);
496ded875dcSGunnar Mills         }
497ded875dcSGunnar Mills         else
498ded875dcSGunnar Mills         {
499ded875dcSGunnar Mills             ++iter;
500ded875dcSGunnar Mills         }
501ded875dcSGunnar Mills     }
502ded875dcSGunnar Mills }
503ded875dcSGunnar Mills 
504*b9da6634SSaqib Khan bool ItemUpdater::isLowestPriority(uint8_t value)
505*b9da6634SSaqib Khan {
506*b9da6634SSaqib Khan     for (const auto& intf : activations)
507*b9da6634SSaqib Khan     {
508*b9da6634SSaqib Khan         if(intf.second->redundancyPriority)
509*b9da6634SSaqib Khan         {
510*b9da6634SSaqib Khan             if (intf.second->redundancyPriority.get()->priority() < value)
511*b9da6634SSaqib Khan             {
512*b9da6634SSaqib Khan                 return false;
513*b9da6634SSaqib Khan             }
514*b9da6634SSaqib Khan         }
515*b9da6634SSaqib Khan     }
516*b9da6634SSaqib Khan     return true;
517*b9da6634SSaqib Khan }
518*b9da6634SSaqib Khan 
519ec1b41c4SGunnar Mills } // namespace updater
520ec1b41c4SGunnar Mills } // namespace software
521ec1b41c4SGunnar Mills } // namespace phosphor
522