Support new boot override setting design
Add support for the new boot override setting design that was
pushed in this commit:
"phosphor-settings-manager: redesign boot setting override feature"
(https://gerrit.openbmc-project.xyz/c/openbmc/openbmc/+/44226)
The new design not only simplifies boot override settings handling,
but also adds support for the invalidation of "boot flags valid"
bit.
Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
Change-Id: Iecfc75c734a34f63b0485f859ce87f06566bd749
Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
diff --git a/chassishandler.cpp b/chassishandler.cpp
index 88c1b67..63a02e5 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -130,9 +130,15 @@
namespace internal
{
+constexpr auto bootSettingsPath = "/xyz/openbmc_project/control/host0/boot";
+constexpr auto bootEnableIntf = "xyz.openbmc_project.Object.Enable";
constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
constexpr auto bootTypeIntf = "xyz.openbmc_project.Control.Boot.Type";
constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
+constexpr auto bootSettingsOneTimePath =
+ "/xyz/openbmc_project/control/host0/boot/one_time";
+constexpr auto bootOneTimeIntf = "xyz.openbmc_project.Object.Enable";
+
constexpr auto powerRestoreIntf =
"xyz.openbmc_project.Control.Power.RestorePolicy";
sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
@@ -1622,6 +1628,33 @@
} // namespace boot_options
+/** @brief Get the property value for boot source
+ * @param[in] ctx - context pointer
+ * @param[out] source - boot source value
+ * @return On failure return IPMI error.
+ */
+static ipmi::Cc getBootSource(ipmi::Context::ptr& ctx, Source::Sources& source)
+{
+ using namespace chassis::internal;
+ std::string result;
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootSourceIntf, bootSettingsPath, service);
+ if (!ec)
+ {
+ ec = ipmi::getDbusProperty(ctx, service, bootSettingsPath,
+ bootSourceIntf, "BootSource", result);
+ if (!ec)
+ {
+ source = Source::convertSourcesFromString(result);
+ return ipmi::ccSuccess;
+ }
+ }
+ log<level::ERR>("Error in BootSource Get",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+}
+
/** @brief Set the property value for boot source
* @param[in] ctx - context pointer
* @param[in] source - boot source value
@@ -1631,21 +1664,49 @@
const Source::Sources& source)
{
using namespace chassis::internal;
- using namespace chassis::internal::cache;
- settings::Objects& objects = getObjects();
- auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
- const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
- boost::system::error_code ec = ipmi::setDbusProperty(
- ctx, objects.service(bootSourceSetting, bootSourceIntf),
- bootSourceSetting, bootSourceIntf, "BootSource",
- convertForMessage(source));
- if (ec)
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootSourceIntf, bootSettingsPath, service);
+ if (!ec)
{
- log<level::ERR>("Error in BootSource Set",
- entry("ERROR=%s", ec.message().c_str()));
- return ipmi::ccUnspecifiedError;
+ ec = ipmi::setDbusProperty(ctx, service, bootSettingsPath,
+ bootSourceIntf, "BootSource",
+ convertForMessage(source));
+ if (!ec)
+ {
+ return ipmi::ccSuccess;
+ }
}
- return ipmi::ccSuccess;
+ log<level::ERR>("Error in BootSource Set",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+}
+
+/** @brief Get the property value for boot mode
+ * @param[in] ctx - context pointer
+ * @param[out] mode - boot mode value
+ * @return On failure return IPMI error.
+ */
+static ipmi::Cc getBootMode(ipmi::Context::ptr& ctx, Mode::Modes& mode)
+{
+ using namespace chassis::internal;
+ std::string result;
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootModeIntf, bootSettingsPath, service);
+ if (!ec)
+ {
+ ec = ipmi::getDbusProperty(ctx, service, bootSettingsPath, bootModeIntf,
+ "BootMode", result);
+ if (!ec)
+ {
+ mode = Mode::convertModesFromString(result);
+ return ipmi::ccSuccess;
+ }
+ }
+ log<level::ERR>("Error in BootMode Get",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
}
/** @brief Set the property value for boot mode
@@ -1656,19 +1717,54 @@
static ipmi::Cc setBootMode(ipmi::Context::ptr& ctx, const Mode::Modes& mode)
{
using namespace chassis::internal;
- using namespace chassis::internal::cache;
- settings::Objects& objects = getObjects();
- auto bootSetting = settings::boot::setting(objects, bootModeIntf);
- const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
- boost::system::error_code ec = ipmi::setDbusProperty(
- ctx, objects.service(bootModeSetting, bootModeIntf), bootModeSetting,
- bootModeIntf, "BootMode", convertForMessage(mode));
- if (ec)
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootModeIntf, bootSettingsPath, service);
+ if (!ec)
{
- log<level::ERR>("Error in BootMode Set",
- entry("ERROR=%s", ec.message().c_str()));
- return ipmi::ccUnspecifiedError;
+ ec = ipmi::setDbusProperty(ctx, service, bootSettingsPath, bootModeIntf,
+ "BootMode", convertForMessage(mode));
+ if (!ec)
+ {
+ return ipmi::ccSuccess;
+ }
}
+ log<level::ERR>("Error in BootMode Set",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+}
+
+/** @brief Get the property value for boot type
+ * @param[in] ctx - context pointer
+ * @param[out] type - boot type value
+ * @return On failure return IPMI error.
+ */
+static ipmi::Cc getBootType(ipmi::Context::ptr& ctx, Type::Types& type)
+{
+ using namespace chassis::internal;
+ std::string result;
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootTypeIntf, bootSettingsPath, service);
+
+ // Don't throw error if BootType interface is not present.
+ // This interface is not relevant for some Host architectures
+ // (for example POWER). In this case we don't won't IPMI to
+ // return an error, but simply return bootType as EFI.
+ type = Type::Types::EFI;
+ if (!ec)
+ {
+ ec = ipmi::getDbusProperty(ctx, service, bootSettingsPath, bootTypeIntf,
+ "BootType", result);
+ if (ec)
+ {
+ log<level::ERR>("Error in BootType Get",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+ }
+ type = Type::convertTypesFromString(result);
+ }
+
return ipmi::ccSuccess;
}
@@ -1680,34 +1776,129 @@
static ipmi::Cc setBootType(ipmi::Context::ptr& ctx, const Type::Types& type)
{
using namespace chassis::internal;
- using namespace chassis::internal::cache;
- settings::Objects& objects = getObjects();
- std::tuple<settings::Path, settings::boot::OneTimeEnabled> bootSetting;
- try
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootTypeIntf, bootSettingsPath, service);
+ if (!ec)
{
- bootSetting = settings::boot::setting(objects, bootTypeIntf);
+ ec = ipmi::setDbusProperty(ctx, service, bootSettingsPath, bootTypeIntf,
+ "BootType", convertForMessage(type));
+ if (ec)
+ {
+ log<level::ERR>("Error in BootType Set",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+ }
}
- catch (const std::exception& e)
- {
- // Return immediately if BootType interface is not present.
- // This interface is not relevant for some Host architectures
- // (for example POWER). In this case we don't won't IPMI to
- // return an error, but want to just skip this function.
- return ipmi::ccSuccess;
- }
- const auto& bootTypeSetting = std::get<settings::Path>(bootSetting);
- boost::system::error_code ec = ipmi::setDbusProperty(
- ctx, objects.service(bootTypeSetting, bootTypeIntf), bootTypeSetting,
- bootTypeIntf, "BootType", convertForMessage(type));
- if (ec)
- {
- log<level::ERR>("Error in BootType Set",
- entry("ERROR=%s", ec.message().c_str()));
- return ipmi::ccUnspecifiedError;
- }
+ // Don't throw error if BootType interface is not present.
+ // This interface is not relevant for some Host architectures
+ // (for example POWER). In this case we don't won't IPMI to
+ // return an error, but want to just skip this function.
return ipmi::ccSuccess;
}
+/** @brief Get the property value for boot override enable
+ * @param[in] ctx - context pointer
+ * @param[out] enable - boot override enable
+ * @return On failure return IPMI error.
+ */
+static ipmi::Cc getBootEnable(ipmi::Context::ptr& ctx, bool& enable)
+{
+ using namespace chassis::internal;
+ std::string result;
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootEnableIntf, bootSettingsPath, service);
+ if (!ec)
+ {
+ ec = ipmi::getDbusProperty(ctx, service, bootSettingsPath,
+ bootEnableIntf, "Enabled", enable);
+ if (!ec)
+ {
+ return ipmi::ccSuccess;
+ }
+ }
+ log<level::ERR>("Error in Boot Override Enable Get",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+}
+
+/** @brief Set the property value for boot override enable
+ * @param[in] ctx - context pointer
+ * @param[in] enable - boot override enable
+ * @return On failure return IPMI error.
+ */
+static ipmi::Cc setBootEnable(ipmi::Context::ptr& ctx, const bool& enable)
+{
+ using namespace chassis::internal;
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootEnableIntf, bootSettingsPath, service);
+ if (!ec)
+ {
+ ec = ipmi::setDbusProperty(ctx, service, bootSettingsPath,
+ bootEnableIntf, "Enabled", enable);
+ if (!ec)
+ {
+ return ipmi::ccSuccess;
+ }
+ }
+ log<level::ERR>("Error in Boot Source Override Enable Set",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+}
+
+/** @brief Get the property value for boot override one-time
+ * @param[in] ctx - context pointer
+ * @param[out] onetime - boot override one-time
+ * @return On failure return IPMI error.
+ */
+static ipmi::Cc getBootOneTime(ipmi::Context::ptr& ctx, bool& onetime)
+{
+ using namespace chassis::internal;
+ std::string result;
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootOneTimeIntf, bootSettingsOneTimePath, service);
+ if (!ec)
+ {
+ ec = ipmi::getDbusProperty(ctx, service, bootSettingsOneTimePath,
+ bootOneTimeIntf, "Enabled", onetime);
+ if (!ec)
+ {
+ return ipmi::ccSuccess;
+ }
+ }
+ log<level::ERR>("Error in Boot Override OneTime Get",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+}
+
+/** @brief Set the property value for boot override one-time
+ * @param[in] ctx - context pointer
+ * @param[in] onetime - boot override one-time
+ * @return On failure return IPMI error.
+ */
+static ipmi::Cc setBootOneTime(ipmi::Context::ptr& ctx, const bool& onetime)
+{
+ using namespace chassis::internal;
+ std::string service;
+ boost::system::error_code ec =
+ getService(ctx, bootOneTimeIntf, bootSettingsOneTimePath, service);
+ if (!ec)
+ {
+ ec = ipmi::setDbusProperty(ctx, service, bootSettingsOneTimePath,
+ bootOneTimeIntf, "Enabled", onetime);
+ if (!ec)
+ {
+ return ipmi::ccSuccess;
+ }
+ }
+ log<level::ERR>("Error in Boot Source Override OneTime Set",
+ entry("ERROR=%s", ec.message().c_str()));
+ return ipmi::ccUnspecifiedError;
+}
+
static constexpr uint8_t setComplete = 0x0;
static constexpr uint8_t setInProgress = 0x1;
static uint8_t transferStatus = setComplete;
@@ -1737,6 +1928,7 @@
uint8_t setSelector, uint8_t blockSelector)
{
+ ipmi::Cc rc;
if (reserved1)
{
return ipmi::responseInvalidFieldRequest();
@@ -1785,72 +1977,26 @@
try
{
- std::string result;
- boost::system::error_code ec;
- settings::Objects& objects = getObjects();
-
- auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
- const auto& bootSourceSetting =
- std::get<settings::Path>(bootSetting);
- ec = ipmi::getDbusProperty(
- ctx, objects.service(bootSourceSetting, bootSourceIntf),
- bootSourceSetting, bootSourceIntf, "BootSource", result);
- if (ec)
+ Source::Sources bootSource;
+ rc = getBootSource(ctx, bootSource);
+ if (rc != ipmi::ccSuccess)
{
- log<level::ERR>(
- "ipmiChassisGetSysBootOptions: Error in BootSource Get");
- report<InternalFailure>();
- return ipmi::responseUnspecifiedError();
+ return ipmi::response(rc);
}
- auto bootSource = Source::convertSourcesFromString(result);
Type::Types bootType;
- bool bootTypeIntfPresent = true;
- try
+ rc = getBootType(ctx, bootType);
+ if (rc != ipmi::ccSuccess)
{
- bootSetting = settings::boot::setting(objects, bootTypeIntf);
- }
- catch (const std::exception& e)
- {
- bootTypeIntfPresent = false;
- }
- if (bootTypeIntfPresent)
- {
- const auto& bootTypeSetting =
- std::get<settings::Path>(bootSetting);
- ec = ipmi::getDbusProperty(
- ctx, objects.service(bootTypeSetting, bootTypeIntf),
- bootTypeSetting, bootTypeIntf, "BootType", result);
- if (ec)
- {
- log<level::ERR>(
- "ipmiChassisGetSysBootOptions: Error in BootType Get");
- report<InternalFailure>();
- return ipmi::responseUnspecifiedError();
- }
- else
- {
- bootType = Type::convertTypesFromString(result);
- }
- }
- else
- {
- bootType = Type::Types::EFI;
+ return ipmi::response(rc);
}
- bootSetting = settings::boot::setting(objects, bootModeIntf);
- const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
- ec = ipmi::getDbusProperty(
- ctx, objects.service(bootModeSetting, bootModeIntf),
- bootModeSetting, bootModeIntf, "BootMode", result);
- if (ec)
+ Mode::Modes bootMode;
+ rc = getBootMode(ctx, bootMode);
+ if (rc != ipmi::ccSuccess)
{
- log<level::ERR>(
- "ipmiChassisGetSysBootOptions: Error in BootMode Get");
- report<InternalFailure>();
- return ipmi::responseUnspecifiedError();
+ return ipmi::response(rc);
}
- auto bootMode = Mode::convertModesFromString(result);
bootOption = sourceDbusToIpmi.at(bootSource);
if ((Mode::Modes::Regular == bootMode) &&
@@ -1864,10 +2010,24 @@
}
IpmiValue biosBootType = typeDbusToIpmi.at(bootType);
- auto oneTimeEnabled =
- std::get<settings::boot::OneTimeEnabled>(bootSetting);
+
+ bool oneTimeEnabled;
+ rc = getBootOneTime(ctx, oneTimeEnabled);
+ if (rc != ipmi::ccSuccess)
+ {
+ return ipmi::response(rc);
+ }
+
uint1_t permanent = oneTimeEnabled ? 0 : 1;
- uint1_t validFlag = 1;
+
+ bool valid;
+ rc = getBootEnable(ctx, valid);
+ if (rc != ipmi::ccSuccess)
+ {
+ return ipmi::response(rc);
+ }
+
+ uint1_t validFlag = valid ? 1 : 0;
response.pack(bootOptionParameter, reserved1, uint5_t{},
uint1_t{biosBootType}, uint1_t{permanent},
@@ -1984,36 +2144,19 @@
using namespace chassis::internal;
using namespace chassis::internal::cache;
- auto oneTimeEnabled = false;
- constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
- constexpr auto oneTimePath =
- "/xyz/openbmc_project/control/host0/boot/one_time";
try
{
- settings::Objects& objects = getObjects();
-
- auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
-
- oneTimeEnabled =
- std::get<settings::boot::OneTimeEnabled>(bootSetting);
-
- /*
- * Check if the current boot setting is onetime or permanent, if the
- * request in the command is otherwise, then set the "Enabled"
- * property in one_time object path to 'True' to indicate onetime
- * and 'False' to indicate permanent.
- *
- * Once the onetime/permanent setting is applied, then the bootMode
- * and bootSource is updated for the corresponding object.
- */
- if ((permanent && oneTimeEnabled) ||
- (!permanent && !oneTimeEnabled))
+ rc = setBootOneTime(ctx, !permanent);
+ if (rc != ipmi::ccSuccess)
{
- auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
+ return ipmi::response(rc);
+ }
- ipmi::setDbusProperty(dbus, service, oneTimePath, enabledIntf,
- "Enabled", !permanent);
+ rc = setBootEnable(ctx, validFlag);
+ if (rc != ipmi::ccSuccess)
+ {
+ return ipmi::response(rc);
}
auto modeItr =
@@ -2027,7 +2170,7 @@
rc = setBootSource(ctx, sourceItr->second);
if (rc != ipmi::ccSuccess)
{
- return ipmi::responseUnspecifiedError();
+ return ipmi::response(rc);
}
// If a set boot device is mapping to a boot source, then reset
// the boot mode D-Bus property to default.
@@ -2035,7 +2178,11 @@
// at the default value
if (sourceItr->second != Source::Sources::Default)
{
- setBootMode(ctx, Mode::Modes::Regular);
+ rc = setBootMode(ctx, Mode::Modes::Regular);
+ if (rc != ipmi::ccSuccess)
+ {
+ return ipmi::response(rc);
+ }
}
}
@@ -2044,7 +2191,7 @@
rc = setBootType(ctx, typeItr->second);
if (rc != ipmi::ccSuccess)
{
- return ipmi::responseUnspecifiedError();
+ return ipmi::response(rc);
}
}
@@ -2053,7 +2200,7 @@
rc = setBootMode(ctx, modeItr->second);
if (rc != ipmi::ccSuccess)
{
- return ipmi::responseUnspecifiedError();
+ return ipmi::response(rc);
}
// If a set boot device is mapping to a boot mode, then reset
// the boot source D-Bus property to default.
@@ -2061,7 +2208,11 @@
// at the default value
if (modeItr->second != Mode::Modes::Regular)
{
- setBootSource(ctx, Source::Sources::Default);
+ rc = setBootSource(ctx, Source::Sources::Default);
+ if (rc != ipmi::ccSuccess)
+ {
+ return ipmi::response(rc);
+ }
}
}
if ((modeIpmiToDbus.end() == modeItr) &&