Add field mode to BMC updater
In this commit, a "field mode" feature is added. When field mode is
enabled, the PNOR patch path is unmounted, disabling host patches.
Resolves openbmc/openbmc#1350
Change-Id: Ia207b1fe1cdeb1b4fbf9b2fbf77052d7191ea726
Signed-off-by: Michael Tritz <mtritz@us.ibm.com>
diff --git a/item_updater.cpp b/item_updater.cpp
index 12f818b..f151412 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -17,6 +17,7 @@
// When you see server:: you know we're referencing our base class
namespace server = sdbusplus::xyz::openbmc_project::Software::server;
+namespace control = sdbusplus::xyz::openbmc_project::Control::server;
using namespace phosphor::logging;
namespace fs = std::experimental::filesystem;
@@ -247,7 +248,7 @@
SYSTEMD_PATH,
SYSTEMD_INTERFACE,
"StartUnit");
- method.append("obmc-flash-bmc-setenv@rwreset=true.service", "replace");
+ method.append("obmc-flash-bmc-setenv@rwreset\\x3dtrue.service", "replace");
bus.call_noreply(method);
log<level::INFO>("BMC factory reset will take effect upon reboot.");
@@ -284,6 +285,56 @@
bus.call_noreply(method);
}
+bool ItemUpdater::fieldModeEnabled(bool value)
+{
+ // enabling field mode is intended to be one way: false -> true
+ if (value && !control::FieldMode::fieldModeEnabled())
+ {
+ control::FieldMode::fieldModeEnabled(value);
+
+ auto method = bus.new_method_call(
+ SYSTEMD_BUSNAME,
+ SYSTEMD_PATH,
+ SYSTEMD_INTERFACE,
+ "StartUnit");
+ method.append("obmc-flash-bmc-setenv@fieldmode\\x3dtrue.service",
+ "replace");
+ bus.call_noreply(method);
+
+ method = bus.new_method_call(
+ SYSTEMD_BUSNAME,
+ SYSTEMD_PATH,
+ SYSTEMD_INTERFACE,
+ "StopUnit");
+ method.append("usr-local.mount", "replace");
+ bus.call_noreply(method);
+
+ std::vector<std::string> usrLocal = {"usr-local.mount"};
+
+ method = bus.new_method_call(
+ SYSTEMD_BUSNAME,
+ SYSTEMD_PATH,
+ SYSTEMD_INTERFACE,
+ "MaskUnitFiles");
+ method.append(usrLocal, false, true);
+ bus.call_noreply(method);
+ }
+
+ return control::FieldMode::fieldModeEnabled();
+}
+
+void ItemUpdater::restoreFieldModeStatus()
+{
+ std::ifstream input("/run/fw_env");
+ std::string envVar;
+ std::getline(input, envVar);
+
+ if(envVar.find("fieldmode=true") != std::string::npos)
+ {
+ ItemUpdater::fieldModeEnabled(true);
+ }
+}
+
} // namespace updater
} // namespace software
} // namespace phosphor
diff --git a/item_updater.hpp b/item_updater.hpp
index 5b2a71b..de7b614 100644
--- a/item_updater.hpp
+++ b/item_updater.hpp
@@ -4,6 +4,7 @@
#include "activation.hpp"
#include "version.hpp"
#include <xyz/openbmc_project/Common/FactoryReset/server.hpp>
+#include <xyz/openbmc_project/Control/FieldMode/server.hpp>
namespace phosphor
{
@@ -13,7 +14,8 @@
{
using ItemUpdaterInherit = sdbusplus::server::object::object<
- sdbusplus::xyz::openbmc_project::Common::server::FactoryReset>;
+ sdbusplus::xyz::openbmc_project::Common::server::FactoryReset,
+ sdbusplus::xyz::openbmc_project::Control::server::FieldMode>;
namespace MatchRules = sdbusplus::bus::match::rules;
@@ -38,7 +40,7 @@
* @param[in] bus - The Dbus bus object
*/
ItemUpdater(sdbusplus::bus::bus& bus, const std::string& path) :
- ItemUpdaterInherit(bus, path.c_str()),
+ ItemUpdaterInherit(bus, path.c_str(), false),
bus(bus),
versionMatch(
bus,
@@ -50,6 +52,8 @@
std::placeholders::_1))
{
processBMCImage();
+ restoreFieldModeStatus();
+ emit_object_added();
};
/** @brief Sets the given priority free by incrementing
@@ -98,6 +102,18 @@
* recreation upon reboot. */
void reset() override;
+ /**
+ * @brief Enables field mode, if value=true.
+ *
+ * @param[in] value - If true, enables field mode.
+ * @param[out] result - Returns the current state of field mode.
+ *
+ */
+ bool fieldModeEnabled(bool value) override;
+
+ /** @brief Restores field mode status on reboot. */
+ void restoreFieldModeStatus();
+
/** @brief Persistent sdbusplus DBus bus connection. */
sdbusplus::bus::bus& bus;