From 13791bd5519d2fe63a4b71f48db32e03c159369a Mon Sep 17 00:00:00 2001 From: Deepak Kodihalli Date: Mon, 28 Aug 2017 06:50:51 -0500 Subject: boot settings: use the new 'one time' setting Resolves openbmc/openbmc#2008. Change-Id: Id79d1f61a3e627fef28b071e2a415e94de14634f Signed-off-by: Deepak Kodihalli --- chassishandler.cpp | 291 ++++++++++++++++++++++++++++++++--------------------- settings.cpp | 53 ++++++++++ settings.hpp | 20 ++++ 3 files changed, 247 insertions(+), 117 deletions(-) diff --git a/chassishandler.cpp b/chassishandler.cpp index de22d80..1e9d3df 100644 --- a/chassishandler.cpp +++ b/chassishandler.cpp @@ -1096,76 +1096,78 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, using namespace chassis::internal; using namespace chassis::internal::cache; - const auto& bootSourceSetting = objects.map.at(bootSourceIntf).front(); - auto method = - dbus.new_method_call( - objects.service(bootSourceSetting, bootSourceIntf).c_str(), - bootSourceSetting.c_str(), - ipmi::PROP_INTF, - "Get"); - method.append(bootSourceIntf, "BootSource"); - auto reply = dbus.call(method); - if (reply.is_method_error()) + try { - log("Error in BootSource Get"); - report(); - *data_len = 0; - return IPMI_CC_UNSPECIFIED_ERROR; + auto bootSetting = settings::boot::setting(objects, bootSourceIntf); + const auto& bootSourceSetting = + std::get(bootSetting); + auto oneTimeEnabled = + std::get(bootSetting); + auto method = + dbus.new_method_call( + objects.service(bootSourceSetting, bootSourceIntf).c_str(), + bootSourceSetting.c_str(), + ipmi::PROP_INTF, + "Get"); + method.append(bootSourceIntf, "BootSource"); + auto reply = dbus.call(method); + if (reply.is_method_error()) + { + log("Error in BootSource Get"); + report(); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + sdbusplus::message::variant result; + reply.read(result); + auto bootSource = + Source::convertSourcesFromString(result.get()); + + bootSetting = settings::boot::setting(objects, bootModeIntf); + const auto& bootModeSetting = std::get(bootSetting); + method = dbus.new_method_call( + objects.service(bootModeSetting, bootModeIntf). + c_str(), + bootModeSetting.c_str(), + ipmi::PROP_INTF, + "Get"); + method.append(bootModeIntf, "BootMode"); + reply = dbus.call(method); + if (reply.is_method_error()) + { + log("Error in BootMode Get"); + report(); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + reply.read(result); + auto bootMode = + Mode::convertModesFromString(result.get()); + + bootOption = sourceDbusToIpmi.at(bootSource); + if ((Mode::Modes::Regular == bootMode) && + (Source::Sources::Default == bootSource)) + { + bootOption = ipmiDefault; + } + else if (Source::Sources::Default == bootSource) + { + bootOption = modeDbusToIpmi.at(bootMode); + } + resp->data[1] = (bootOption << 2); + + resp->data[0] = oneTimeEnabled ? + SET_PARM_BOOT_FLAGS_VALID_ONE_TIME: + SET_PARM_BOOT_FLAGS_VALID_PERMANENT; + + rc = IPMI_CC_OK; } - sdbusplus::message::variant result; - reply.read(result); - auto bootSource = - Source::convertSourcesFromString(result.get()); - - const auto& bootModeSetting = objects.map.at(bootModeIntf).front(); - method = dbus.new_method_call( - objects.service(bootModeSetting, bootModeIntf).c_str(), - bootModeSetting.c_str(), - ipmi::PROP_INTF, - "Get"); - method.append(bootModeIntf, "BootMode"); - reply = dbus.call(method); - if (reply.is_method_error()) + catch (InternalFailure& e) { - log("Error in BootMode Get"); report(); *data_len = 0; return IPMI_CC_UNSPECIFIED_ERROR; } - reply.read(result); - auto bootMode = Mode::convertModesFromString(result.get()); - - bootOption = sourceDbusToIpmi.at(bootSource); - if ((Mode::Modes::Regular == bootMode) && - (Source::Sources::Default == bootSource)) - { - bootOption = ipmiDefault; - } - else if (Source::Sources::Default == bootSource) - { - bootOption = modeDbusToIpmi.at(bootMode); - } - resp->data[1] = (bootOption << 2); - rc = IPMI_CC_OK; - - /* Get the boot policy */ - int r = dbus_get_property("boot_policy",&p); - - if (r < 0) { - fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n"); - rc = IPMI_CC_UNSPECIFIED_ERROR; - - } else { - - printf("BootPolicy is [%s]\n", p); - resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ? - SET_PARM_BOOT_FLAGS_VALID_ONE_TIME: - SET_PARM_BOOT_FLAGS_VALID_PERMANENT; - rc = IPMI_CC_OK; - - } - - } else if ( reqptr->parameter == static_cast ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) { @@ -1226,68 +1228,123 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2); using namespace chassis::internal; using namespace chassis::internal::cache; + auto oneTimeEnabled = false; + constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable"; - auto modeItr = modeIpmiToDbus.find(bootOption); - auto sourceItr = sourceIpmiToDbus.find(bootOption); - if ((ipmiDefault == bootOption) || - (sourceIpmiToDbus.end() != sourceItr)) + try { - sdbusplus::message::variant property = - convertForMessage(sourceItr->second); - const auto& bootSourceSetting = - objects.map.at(bootSourceIntf).front(); - auto method = - dbus.new_method_call( - objects.service(bootSourceSetting, bootSourceIntf).c_str(), - bootSourceSetting.c_str(), - ipmi::PROP_INTF, - "Set"); - method.append(bootSourceIntf, "BootSource", property); - auto reply = dbus.call(method); - if (reply.is_method_error()) + bool permanent = + (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) == + SET_PARM_BOOT_FLAGS_PERMANENT; + + auto modeItr = modeIpmiToDbus.find(bootOption); + auto sourceItr = sourceIpmiToDbus.find(bootOption); + if (sourceIpmiToDbus.end() != sourceItr) { - log("Error in BootSource Set"); - report(); - *data_len = 0; - return IPMI_CC_UNSPECIFIED_ERROR; + sdbusplus::message::variant property = + convertForMessage(sourceItr->second); + auto bootSetting = + settings::boot::setting(objects, bootSourceIntf); + const auto& bootSourceSetting = + std::get(bootSetting); + oneTimeEnabled = + std::get(bootSetting); + auto method = + dbus.new_method_call( + objects.service(bootSourceSetting, bootSourceIntf). + c_str(), + bootSourceSetting.c_str(), + ipmi::PROP_INTF, + "Set"); + method.append(bootSourceIntf, "BootSource", property); + auto reply = dbus.call(method); + if (reply.is_method_error()) + { + log("Error in BootSource Set"); + report(); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + + if (permanent && oneTimeEnabled) + { + sdbusplus::message::variant enabled = false; + method = + objects.bus.new_method_call( + objects.service(bootSourceSetting, + bootSourceIntf).c_str(), + bootSourceSetting.c_str(), + ipmi::PROP_INTF, + "Set"); + method.append(enabledIntf, "Enabled", enabled); + auto reply = objects.bus.call(method); + if (reply.is_method_error()) + { + log("Error in setting enabled property", + entry("OBJECT=%s", + bootSourceSetting.c_str())); + report(); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + } } - } - if ((ipmiDefault == bootOption) || - (modeIpmiToDbus.end() != modeItr)) - { - sdbusplus::message::variant property = - convertForMessage(modeItr->second); - const auto& bootModeSetting = objects.map.at(bootModeIntf).front(); - auto method = - dbus.new_method_call( - objects.service(bootModeSetting, bootModeIntf).c_str(), - bootModeSetting.c_str(), - ipmi::PROP_INTF, - "Set"); - method.append(bootModeIntf, "BootMode", property); - auto reply = dbus.call(method); - if (reply.is_method_error()) + if (modeIpmiToDbus.end() != modeItr) { - log("Error in BootMode Set"); - report(); - *data_len = 0; - return IPMI_CC_UNSPECIFIED_ERROR; + sdbusplus::message::variant property = + convertForMessage(modeItr->second); + auto bootSetting = + settings::boot::setting(objects, bootModeIntf); + const auto& bootModeSetting = + std::get(bootSetting); + oneTimeEnabled = + std::get(bootSetting); + auto method = + dbus.new_method_call( + objects.service(bootModeSetting, bootModeIntf).c_str(), + bootModeSetting.c_str(), + ipmi::PROP_INTF, + "Set"); + method.append(bootModeIntf, "BootMode", property); + auto reply = dbus.call(method); + if (reply.is_method_error()) + { + log("Error in BootMode Set"); + report(); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + + if (permanent && oneTimeEnabled) + { + sdbusplus::message::variant enabled = false; + method = + objects.bus.new_method_call( + objects.service(bootModeSetting, bootModeIntf). + c_str(), + bootModeSetting.c_str(), + ipmi::PROP_INTF, + "Set"); + method.append(enabledIntf, "Enabled", enabled); + auto reply = objects.bus.call(method); + if (reply.is_method_error()) + { + log("Error in setting enabled property", + entry("OBJECT=%s", + bootModeSetting.c_str())); + report(); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + } } } - - /* setting the boot policy */ - std::string value = - (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) == - SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME"); - - printf ( "\nBoot Policy is %s",value.c_str()); - int r = dbus_set_property("boot_policy",value.c_str()); - - if (r < 0) { - fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n"); - rc = IPMI_CC_UNSPECIFIED_ERROR; + catch (InternalFailure& e) + { + report(); + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; } - } else if (reqptr->parameter == (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) { diff --git a/settings.cpp b/settings.cpp index 59f9f33..a1ca62c 100644 --- a/settings.cpp +++ b/settings.cpp @@ -2,6 +2,7 @@ #include #include "xyz/openbmc_project/Common/error.hpp" #include "settings.hpp" +#include "utils.hpp" namespace settings { @@ -90,4 +91,56 @@ Service Objects::service(const Path& path, const Interface& interface) const return result.begin()->first; } +namespace boot +{ + +std::tuple setting(const Objects& objects, + const Interface& iface) +{ + constexpr auto bootObjCount = 2; + constexpr auto oneTime = "one_time"; + constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable"; + + const std::vector& paths = objects.map.at(iface); + auto count = paths.size(); + if (count != bootObjCount) + { + log("Exactly two objects expected", + entry("INTERFACE=%s", iface.c_str()), + entry("COUNT=%d", count)); + elog(); + } + size_t index = 0; + if (std::string::npos == paths[0].rfind(oneTime)) + { + index = 1; + } + const Path& oneTimeSetting = paths[index]; + const Path& regularSetting = paths[!index]; + + auto method = + objects.bus.new_method_call( + objects.service(oneTimeSetting, iface).c_str(), + oneTimeSetting.c_str(), + ipmi::PROP_INTF, + "Get"); + method.append(enabledIntf, "Enabled"); + auto reply = objects.bus.call(method); + if (reply.is_method_error()) + { + log("Error in getting Enabled property", + entry("OBJECT=%s", oneTimeSetting.c_str()), + entry("INTERFACE=%s", iface.c_str())); + elog(); + } + + sdbusplus::message::variant enabled; + reply.read(enabled); + auto oneTimeEnabled = enabled.get(); + const Path& setting = oneTimeEnabled ? oneTimeSetting : regularSetting; + return std::make_tuple(setting, oneTimeEnabled); +} + +} // namespace boot + } // namespace settings diff --git a/settings.hpp b/settings.hpp index ec1d913..91c9930 100644 --- a/settings.hpp +++ b/settings.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace settings @@ -49,4 +50,23 @@ struct Objects sdbusplus::bus::bus& bus; }; +namespace boot +{ + +using OneTimeEnabled = bool; + +/** @brief Return the one-time boot setting object path if enabled, otherwise + * the regular boot setting object path. + * + * @param[in] objects - const reference to an object of type Objects + * @param[in] iface - boot setting interface + * + * @return A tuple - boot setting object path, a bool indicating whether the + * returned path corresponds to the one time boot setting. + */ +std::tuple setting(const Objects& objects, + const Interface& iface); + +} // namespace boot + } // namespace settings -- cgit v1.2.1