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