1From aaf8a4a5b82baff679f557ed83b25af6ff2919cf Mon Sep 17 00:00:00 2001 2From: Alexander Amelkin <a.amelkin@yadro.com> 3Date: Thu, 23 May 2019 20:39:57 +0300 4Subject: [PATCH] Add support for persistent-only settings 5 6Some settings such as Boot Initiator Mailbox do not support 7one-time setting mode (as per IPMI 2.0 specification). 8 9This commit adds support for such persistent-only settings. 10 11Partially resolves openbmc/openbmc#3391 12 13Change-Id: Iec8e2f5bddbc50d270916567effe334f10db2987 14Signed-off-by: Alexander Amelkin <a.amelkin@yadro.com> 15Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com> 16--- 17 settings.cpp | 35 +++++++++++++++++++++++++++++++---- 18 1 file changed, 31 insertions(+), 4 deletions(-) 19 20diff --git a/settings.cpp b/settings.cpp 21index 2fa2511..6002365 100644 22--- a/settings.cpp 23+++ b/settings.cpp 24@@ -95,19 +95,44 @@ namespace boot 25 std::tuple<Path, OneTimeEnabled> setting(const Objects& objects, 26 const Interface& iface) 27 { 28- constexpr auto bootObjCount = 2; 29+ constexpr auto ambiguousOperationCount = 2; 30 constexpr auto oneTime = "one_time"; 31 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable"; 32+ bool oneTimeEnabled = false; 33 34 const std::vector<Path>& paths = objects.map.at(iface); 35 auto count = paths.size(); 36- if (count != bootObjCount) 37+ if (!count) 38 { 39- log<level::ERR>("Exactly two objects expected", 40+ // If there are no objects implementing the requested interface, 41+ // that must be an error. 42+ log<level::ERR>("Interface objects not found", 43+ entry("INTERFACE=%s", iface.c_str())); 44+ elog<InternalFailure>(); 45+ } 46+ else if (count < ambiguousOperationCount) 47+ { 48+ // On the contrary, if there is just one object, that may mean 49+ // that this particular interface doesn't support one-time 50+ // setting mode (e.g. Boot Initiator Mailbox). 51+ // That is not an error, just return the regular setting. 52+ // If there's just one object, that's the only kind of setting 53+ // mode this interface supports, so just return that setting path. 54+ const Path& regularSetting = paths[0]; 55+ return std::make_tuple(regularSetting, oneTimeEnabled); 56+ } 57+ else if (count > ambiguousOperationCount) 58+ { 59+ // Something must be wrong if there are more objects than expected 60+ log<level::ERR>("Exactly 1 or 2 interface objects are required", 61 entry("INTERFACE=%s", iface.c_str()), 62 entry("COUNT=%d", count)); 63 elog<InternalFailure>(); 64 } 65+ 66+ // We are here because there were exactly two objects implementing the 67+ // same interface. Take those two and find out which of them is the 68+ // one-time setting, consider the other the persistent setting. 69 size_t index = 0; 70 if (std::string::npos == paths[0].rfind(oneTime)) 71 { 72@@ -116,6 +141,8 @@ std::tuple<Path, OneTimeEnabled> setting(const Objects& objects, 73 const Path& oneTimeSetting = paths[index]; 74 const Path& regularSetting = paths[!index]; 75 76+ // Now see if the one-time setting is enabled and return the path for it 77+ // if so. Otherwise return the path for the persistent setting. 78 auto method = objects.bus.new_method_call( 79 objects.service(oneTimeSetting, iface).c_str(), oneTimeSetting.c_str(), 80 ipmi::PROP_INTF, "Get"); 81@@ -131,7 +158,7 @@ std::tuple<Path, OneTimeEnabled> setting(const Objects& objects, 82 83 std::variant<bool> enabled; 84 reply.read(enabled); 85- auto oneTimeEnabled = std::get<bool>(enabled); 86+ oneTimeEnabled = std::get<bool>(enabled); 87 const Path& setting = oneTimeEnabled ? oneTimeSetting : regularSetting; 88 return std::make_tuple(setting, oneTimeEnabled); 89 } 90-- 912.21.1 92 93