summaryrefslogtreecommitdiff
path: root/redfish-core/lib/systems.hpp
diff options
context:
space:
mode:
authorKonstantin Aladyshev <aladyshev22@gmail.com>2021-02-26 12:37:07 +0300
committerEd Tanous <ed@tanous.net>2021-07-20 21:04:50 +0300
commitcd9a4666e67563bad804d08b891f7d852ac6e18a (patch)
tree2ed3c4163ee39692abde16b26146a85aa32eb7db /redfish-core/lib/systems.hpp
parentb4bec66b24755cf87e924d56219c60e9506f196b (diff)
downloadbmcweb-cd9a4666e67563bad804d08b891f7d852ac6e18a.tar.xz
Add support for the BootSourceOverrideMode
BootSourceOverrideMode is the BIOS boot mode to use when the system boots from the BootSourceOverrideTarget boot source. Possible values are: -Legacy - The system boots in non-UEFI boot mode to the boot source override target -UEFI - The system boots in UEFI boot mode to the boot source override target For the architectures that don't implement Legacy/UEFI boot mode property (for example POWER), don't publish BootSourceOverrideMode interface at all. Redfish validator has been executed on this change and no new error was found. Also tested with the help of the openbmc-test-automation framework. When the Legacy/UEFI boot mode is present in the system command for testing is: robot -v PLATFORM_ARCH_TYPE:x86 \ -v OPENBMC_HOST:<BMC IP> \ redfish/systems/test_boot_devices.robot When the Legacy/UEFI boot mode is not present in the system command for testing is: robot -v OPENBMC_HOST:<BMC IP> \ redfish/systems/test_boot_devices.robot Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com> Change-Id: Id64e428752b820d481ce15d56566dd7b06738ec0
Diffstat (limited to 'redfish-core/lib/systems.hpp')
-rw-r--r--redfish-core/lib/systems.hpp316
1 files changed, 260 insertions, 56 deletions
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 45a3249091..5ad065b351 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -711,6 +711,27 @@ inline std::string dbusToRfBootSource(const std::string& dbusSource)
}
/**
+ * @brief Translates boot type DBUS property value to redfish.
+ *
+ * @param[in] dbusType The boot type in DBUS speak.
+ *
+ * @return Returns as a string, the boot type in Redfish terms. If translation
+ * cannot be done, returns an empty string.
+ */
+inline std::string dbusToRfBootType(const std::string& dbusType)
+{
+ if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
+ {
+ return "Legacy";
+ }
+ if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
+ {
+ return "UEFI";
+ }
+ return "";
+}
+
+/**
* @brief Translates boot mode DBUS property value to redfish.
*
* @param[in] dbusMode The boot mode in DBUS speak.
@@ -899,6 +920,96 @@ inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
}
/**
+ * @brief Checks if the current boot override state can be considered as
+ * Disabled
+ *
+ * @param[in] aResp Shared pointer for generating response message.
+ *
+ * @return None.
+ */
+inline void
+ checkIfOverrideIsDisabled(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
+{
+ // If the BootSourceOverrideTarget is still "None" at the end,
+ // reset the BootSourceOverrideEnabled to indicate that
+ // overrides are disabled
+ if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] == "None")
+ {
+ // If the BootSourceOverrideMode is supported we should
+ // check if it is still "UEFI" too
+ if (aResp->res.jsonValue["Boot"].contains("BootSourceOverrideMode"))
+ {
+ if (aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] !=
+ "UEFI")
+ {
+ return;
+ }
+ }
+ aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
+ }
+}
+
+/**
+ * @brief Retrieves boot type over DBUS and fills out the response
+ *
+ * @param[in] aResp Shared pointer for generating response message.
+ * @param[in] bootDbusObj The dbus object to query for boot properties.
+ *
+ * @return None.
+ */
+inline void getBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+ const std::string& bootDbusObj)
+{
+ crow::connections::systemBus->async_method_call(
+ [aResp](const boost::system::error_code ec,
+ const std::variant<std::string>& bootType) {
+ if (ec)
+ {
+ // not an error, don't have to have the interface
+
+ // Support Disabled override state in a way:
+ // "BootSourceOverrideEnabled=Disabled" =
+ // "BootSourceOverrideMode=UEFI" +
+ // "BootSourceOverrideTarget=None"
+ checkIfOverrideIsDisabled(aResp);
+ return;
+ }
+
+ const std::string* bootTypeStr =
+ std::get_if<std::string>(&bootType);
+
+ if (!bootTypeStr)
+ {
+ messages::internalError(aResp->res);
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "Boot type: " << *bootTypeStr;
+
+ aResp->res.jsonValue["Boot"]["BootSourceOverrideMode@Redfish."
+ "AllowableValues"] = {"Legacy",
+ "UEFI"};
+
+ auto rfType = dbusToRfBootType(*bootTypeStr);
+ if (rfType.empty())
+ {
+ messages::internalError(aResp->res);
+ return;
+ }
+
+ aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
+
+ // Support Disabled override state in a way:
+ // "BootSourceOverrideEnabled=Disabled" =
+ // "BootSourceOverrideMode=UEFI" + "BootSourceOverrideTarget=None"
+ checkIfOverrideIsDisabled(aResp);
+ },
+ "xyz.openbmc_project.Settings", bootDbusObj,
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Control.Boot.Type", "BootType");
+}
+
+/**
* @brief Retrieves boot mode over DBUS and fills out the response
*
* @param[in] aResp Shared pointer for generating response message.
@@ -910,8 +1021,8 @@ inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
const std::string& bootDbusObj)
{
crow::connections::systemBus->async_method_call(
- [aResp](const boost::system::error_code ec,
- const std::variant<std::string>& bootMode) {
+ [aResp, bootDbusObj](const boost::system::error_code ec,
+ const std::variant<std::string>& bootMode) {
if (ec)
{
BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
@@ -930,8 +1041,6 @@ inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
- // TODO (Santosh): Do we need to support override mode?
- aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
"AllowableValues"] = {
"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
@@ -947,15 +1056,10 @@ inline void getBootMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
}
}
- // If the BootSourceOverrideTarget is still "None" at the end,
- // reset the BootSourceOverrideEnabled to indicate that
- // overrides are disabled
- if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
- "None")
- {
- aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
- "Disabled";
- }
+ // Get BootType inside this async call as we need all of the
+ // BootSource/BootMode/BootType to support
+ // "BootSourceOverrideEnabled"="Disabled" state.
+ getBootType(aResp, bootDbusObj);
},
"xyz.openbmc_project.Settings", bootDbusObj,
"org.freedesktop.DBus.Properties", "Get",
@@ -1007,11 +1111,14 @@ inline void getBootSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
rfSource;
}
+
+ // Get BootMode as BootSourceOverrideTarget is constructed
+ // from both BootSource and BootMode
+ getBootMode(aResp, bootDbusObj);
},
"xyz.openbmc_project.Settings", bootDbusObj,
"org.freedesktop.DBus.Properties", "Get",
"xyz.openbmc_project.Control.Boot.Source", "BootSource");
- getBootMode(aResp, bootDbusObj);
}
/**
@@ -1352,53 +1459,97 @@ inline void getTrustedModuleRequiredToBoot(
* @brief Sets boot properties into DBUS object(s).
*
* @param[in] aResp Shared pointer for generating response message.
- * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
- * @param[in] bootSource The boot source to set.
- * @param[in] bootEnable The source override "enable" to set.
- *
+ * @param[in] overrideEnabled The source override "enable".
+ * @param[in] bootObj Path to the DBUS object.
+ * @param[in] bootType The boot type to set.
* @return Integer error code.
*/
-inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
- bool oneTimeEnabled,
- const std::optional<std::string>& bootSource,
- const std::optional<std::string>& bootEnable)
+inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+ const bool overrideEnabled, const std::string& bootObj,
+ const std::optional<std::string>& bootType)
{
- std::string bootSourceStr =
- "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
- std::string bootModeStr =
- "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
- bool oneTimeSetting = oneTimeEnabled;
- bool useBootSource = true;
+ std::string bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
- // Validate incoming parameters
- if (bootEnable)
+ if (bootType && overrideEnabled)
{
- if (*bootEnable == "Once")
- {
- oneTimeSetting = true;
- }
- else if (*bootEnable == "Continuous")
+ // Source target specified
+ BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
+ // Figure out which DBUS interface and property to use
+ if (*bootType == "Legacy")
{
- oneTimeSetting = false;
+ bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
}
- else if (*bootEnable == "Disabled")
+ else if (*bootType == "UEFI")
{
- BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
- oneTimeSetting = false;
- useBootSource = false;
+ bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
}
else
{
- BMCWEB_LOG_DEBUG << "Unsupported value for "
- "BootSourceOverrideEnabled: "
- << *bootEnable;
- messages::propertyValueNotInList(aResp->res, *bootEnable,
- "BootSourceOverrideEnabled");
+ BMCWEB_LOG_DEBUG << "Invalid property value for "
+ "BootSourceOverrideMode: "
+ << *bootType;
+ messages::propertyValueNotInList(aResp->res, *bootType,
+ "BootSourceOverrideMode");
return;
}
}
- if (bootSource && useBootSource)
+ // Act on validated parameters
+ BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
+
+ crow::connections::systemBus->async_method_call(
+ [aResp, bootType](const boost::system::error_code ec) {
+ if (ec)
+ {
+ if (!bootType)
+ {
+ // If bootType wasn't explicitly present in the incoming
+ // message don't output error. The error could come from a
+ // fact that the BootType interface may be not present in
+ // the settings object. It could happen because this
+ // interface is not relevant for some Host architectures
+ // (for example POWER).
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ if (ec.value() == boost::asio::error::host_unreachable)
+ {
+ messages::resourceNotFound(aResp->res, "Set", "BootType");
+ return;
+ }
+ messages::internalError(aResp->res);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Boot type update done.";
+ },
+ "xyz.openbmc_project.Settings", bootObj,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Control.Boot.Type", "BootType",
+ std::variant<std::string>(bootTypeStr));
+}
+
+/**
+ * @brief Sets boot properties into DBUS object(s).
+ *
+ * @param[in] aResp Shared pointer for generating response message.
+ * @param[in] overrideEnabled The source override "enable".
+ * @param[in] bootObj Path to the DBUS object.
+ * @param[in] bootSource The boot source to set.
+ *
+ * @return Integer error code.
+ */
+inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+ const bool overrideEnabled,
+ const std::string& bootObj,
+ const std::optional<std::string>& bootSource)
+{
+ std::string bootSourceStr =
+ "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
+ std::string bootModeStr =
+ "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
+
+ if (bootSource && overrideEnabled)
{
// Source target specified
BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
@@ -1418,9 +1569,6 @@ inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
// Act on validated parameters
BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
- const char* bootObj =
- oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
- : "/xyz/openbmc_project/control/host0/boot";
crow::connections::systemBus->async_method_call(
[aResp](const boost::system::error_code ec) {
@@ -1451,9 +1599,21 @@ inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
"org.freedesktop.DBus.Properties", "Set",
"xyz.openbmc_project.Control.Boot.Mode", "BootMode",
std::variant<std::string>(bootModeStr));
+}
+/**
+ * @brief Sets "One time" enabled setting into DBUS object
+ *
+ * @param[in] aResp Shared pointer for generating response message.
+ * @param[in] oneTime Enable property for one-time object
+ *
+ * @return Integer error code.
+ */
+inline void setOneTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+ bool oneTime)
+{
crow::connections::systemBus->async_method_call(
- [aResp{std::move(aResp)}](const boost::system::error_code ec) {
+ [aResp{aResp}](const boost::system::error_code ec) {
if (ec)
{
BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
@@ -1466,7 +1626,7 @@ inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
"/xyz/openbmc_project/control/host0/boot/one_time",
"org.freedesktop.DBus.Properties", "Set",
"xyz.openbmc_project.Object.Enable", "Enabled",
- std::variant<bool>(oneTimeSetting));
+ std::variant<bool>(oneTime));
}
/**
@@ -1475,6 +1635,7 @@ inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
*
* @param[in] aResp Shared pointer for generating response message.
* @param[in] bootSource The boot source from incoming RF request.
+ * @param[in] bootType The boot type from incoming RF request.
* @param[in] bootEnable The boot override enable from incoming RF request.
*
* @return Integer error code.
@@ -1482,12 +1643,14 @@ inline void setBootModeOrSource(std::shared_ptr<bmcweb::AsyncResp> aResp,
inline void
setBootSourceProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
std::optional<std::string> bootSource,
+ std::optional<std::string> bootType,
std::optional<std::string> bootEnable)
{
BMCWEB_LOG_DEBUG << "Set boot information.";
crow::connections::systemBus->async_method_call(
[aResp, bootSource{std::move(bootSource)},
+ bootType{std::move(bootType)},
bootEnable{std::move(bootEnable)}](const boost::system::error_code ec,
const std::variant<bool>& oneTime) {
if (ec)
@@ -1507,7 +1670,46 @@ inline void
BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
- setBootModeOrSource(aResp, *oneTimePtr, bootSource, bootEnable);
+ bool oneTimeSetting = *oneTimePtr;
+ bool overrideEnabled = true;
+
+ // Validate incoming parameters
+ if (bootEnable)
+ {
+ if (*bootEnable == "Once")
+ {
+ oneTimeSetting = true;
+ }
+ else if (*bootEnable == "Continuous")
+ {
+ oneTimeSetting = false;
+ }
+ else if (*bootEnable == "Disabled")
+ {
+ BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
+ oneTimeSetting = false;
+ overrideEnabled = false;
+ }
+ else
+ {
+ BMCWEB_LOG_DEBUG << "Unsupported value for "
+ "BootSourceOverrideEnabled: "
+ << *bootEnable;
+ messages::propertyValueNotInList(
+ aResp->res, *bootEnable, "BootSourceOverrideEnabled");
+ return;
+ }
+ }
+
+ std::string bootObj = "/xyz/openbmc_project/control/host0/boot";
+ if (oneTimeSetting)
+ {
+ bootObj += "/one_time";
+ }
+
+ setBootModeOrSource(aResp, overrideEnabled, bootObj, bootSource);
+ setBootType(aResp, overrideEnabled, bootObj, bootType);
+ setOneTime(aResp, oneTimeSetting);
},
"xyz.openbmc_project.Settings",
"/xyz/openbmc_project/control/host0/boot/one_time",
@@ -2588,22 +2790,24 @@ inline void requestRoutesSystems(App& app)
if (bootProps)
{
std::optional<std::string> bootSource;
+ std::optional<std::string> bootType;
std::optional<std::string> bootEnable;
std::optional<std::string> automaticRetryConfig;
if (!json_util::readJson(
*bootProps, asyncResp->res,
"BootSourceOverrideTarget", bootSource,
+ "BootSourceOverrideMode", bootType,
"BootSourceOverrideEnabled", bootEnable,
"AutomaticRetryConfig", automaticRetryConfig))
{
return;
}
- if (bootSource || bootEnable)
+ if (bootSource || bootType || bootEnable)
{
- setBootSourceProperties(asyncResp,
- std::move(bootSource),
- std::move(bootEnable));
+ setBootSourceProperties(
+ asyncResp, std::move(bootSource),
+ std::move(bootType), std::move(bootEnable));
}
if (automaticRetryConfig)
{