ADD USB Code Update enable/disable
phosphor_usb_code_update is an application that use USB to do FW
update. phosphor_usb_code_update service is not a daemon, but an app
that will be called after inserting a USB flash disk.
This commit creates an object of phosphor_usb_code_update when
phosphor_usb_code_update is not started. We can enable/disable
phosphor_usb_code_update by setting the "Enabled" property to
true/false.
Please configure the “usb-code-update” option in your bb/bbappend to
enable this feature.
For phosphor_usb_code_update, useful rules files is
/lib/udev/rules.d/70-bmc-usb.rules. When usb code update is disabled,
srvcfg_manager creates an empty symlink
/etc/udev/rules.d/70-bmc-usb.rules, which causes
/lib/udev/rules.d/70-bmc-usb.rules inoperative. When usb code update is
enabled, srvcfg_manager deletes /etc/udev/rules.d/70-bmc-usb.rules.
The commits of phosphor_usb_code_update is:
https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-bmc-code-mgmt/+/48742/1
Test:
get "Enabled" property:
busctl get-property xyz.openbmc_project.Control.Service.Manager
/xyz/openbmc_project/control/service/phosphor_2dusb_2dcode_2dupdate
xyz.openbmc_project.Control.Service.Attributes Enabled
b true
set "Enabled" property to false:
busctl set-property xyz.openbmc_project.Control.Service.Manager
/xyz/openbmc_project/control/service/phosphor_2dusb_2dcode_2dupdate
xyz.openbmc_project.Control.Service.Attributes Enabled b false
busctl get-property xyz.openbmc_project.Control.Service.Manager
/xyz/openbmc_project/control/service/phosphor_2dusb_2dcode_2dupdate
xyz.openbmc_project.Control.Service.Attributes Enabled
b false
The "Enabled" property will be persisted,reboot the BMC, then get the
"Enabled" property:
busctl get-property xyz.openbmc_project.Control.Service.Manager
/xyz/openbmc_project/control/service/phosphor_2dusb_2dcode_2dupdate
xyz.openbmc_project.Control.Service.Attributes Enabled
b false
Signed-off-by: Chicago Duan <duanzhijia01@inspur.com>
Change-Id: Iba7ffb541628d563e2c54c3e1c8c4dbe85f1507b
diff --git a/src/srvcfg_manager.cpp b/src/srvcfg_manager.cpp
index b7b891b..9840cc4 100644
--- a/src/srvcfg_manager.cpp
+++ b/src/srvcfg_manager.cpp
@@ -17,6 +17,14 @@
#include <boost/asio/spawn.hpp>
+#ifdef USB_CODE_UPDATE
+#include <cereal/archives/json.hpp>
+#include <cereal/types/tuple.hpp>
+#include <cereal/types/unordered_map.hpp>
+
+#include <cstdio>
+#endif
+
#include <fstream>
#include <regex>
@@ -38,6 +46,109 @@
static constexpr const char* systemdOverrideUnitBasePath =
"/etc/systemd/system/";
+#ifdef USB_CODE_UPDATE
+static constexpr const char* usbCodeUpdateStateFilePath =
+ "/var/lib/srvcfg_manager";
+static constexpr const char* usbCodeUpdateStateFile =
+ "/var/lib/srvcfg_manager/usb-code-update-state";
+static constexpr const char* emptyUsbCodeUpdateRulesFile =
+ "/etc/udev/rules.d/70-bmc-usb.rules";
+static constexpr const char* usbCodeUpdateObjectPath =
+ "/xyz/openbmc_project/control/service/phosphor_2dusb_2dcode_2dupdate";
+
+using UsbCodeUpdateStateMap = std::unordered_map<std::string, bool>;
+
+void ServiceConfig::setUSBCodeUpdateState(const bool& state)
+{
+ // Enable usb code update
+ if (state)
+ {
+ if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "Enable usb code update");
+ std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
+ }
+ return;
+ }
+
+ // Disable usb code update
+ if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
+ {
+ std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
+ }
+ std::error_code ec;
+ std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
+ ec);
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Disable usb code update failed");
+ return;
+ }
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "Disable usb code update");
+}
+
+void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
+ const bool& enabledState)
+{
+ if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
+ {
+ std::filesystem::create_directories(usbCodeUpdateStateFilePath);
+ }
+
+ UsbCodeUpdateStateMap usbCodeUpdateState;
+ usbCodeUpdateState[srvCfgPropMasked] = maskedState;
+ usbCodeUpdateState[srvCfgPropEnabled] = enabledState;
+
+ std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
+ cereal::JSONOutputArchive archive(file);
+ archive(CEREAL_NVP(usbCodeUpdateState));
+}
+
+void ServiceConfig::getUSBCodeUpdateStateFromFile()
+{
+ if (!std::filesystem::exists(usbCodeUpdateStateFile))
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "usb-code-update-state file does not exist");
+
+ unitMaskedState = false;
+ unitEnabledState = true;
+ unitRunningState = true;
+ setUSBCodeUpdateState(unitEnabledState);
+ return;
+ }
+
+ std::ifstream file(usbCodeUpdateStateFile);
+ cereal::JSONInputArchive archive(file);
+ UsbCodeUpdateStateMap usbCodeUpdateState;
+ archive(usbCodeUpdateState);
+
+ auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
+ if (iterMask != usbCodeUpdateState.end())
+ {
+ unitMaskedState = iterMask->second;
+ if (unitMaskedState)
+ {
+ unitEnabledState = !unitMaskedState;
+ unitRunningState = !unitMaskedState;
+ setUSBCodeUpdateState(unitEnabledState);
+ return;
+ }
+
+ auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
+ if (iterEnable != usbCodeUpdateState.end())
+ {
+ unitEnabledState = iterEnable->second;
+ unitRunningState = iterEnable->second;
+ setUSBCodeUpdateState(unitEnabledState);
+ }
+ }
+}
+#endif
+
void ServiceConfig::updateSocketProperties(
const boost::container::flat_map<std::string, VariantType>& propertyMap)
{
@@ -108,6 +219,13 @@
internalSet = false;
}
}
+
+#ifdef USB_CODE_UPDATE
+ if (objPath == usbCodeUpdateObjectPath)
+ {
+ getUSBCodeUpdateStateFromFile();
+ }
+#endif
}
void ServiceConfig::queryAndUpdateProperties()
@@ -453,6 +571,26 @@
srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
if (!internalSet)
{
+#ifdef USB_CODE_UPDATE
+ if (objPath == usbCodeUpdateObjectPath)
+ {
+ unitMaskedState = req;
+ unitEnabledState = !unitMaskedState;
+ unitRunningState = !unitMaskedState;
+ internalSet = true;
+ srvCfgIface->set_property(srvCfgPropEnabled,
+ unitEnabledState);
+ srvCfgIface->set_property(srvCfgPropRunning,
+ unitRunningState);
+ srvCfgIface->set_property(srvCfgPropMasked,
+ unitMaskedState);
+ internalSet = false;
+ setUSBCodeUpdateState(unitEnabledState);
+ saveUSBCodeUpdateStateToFile(unitMaskedState,
+ unitEnabledState);
+ return 1;
+ }
+#endif
if (req == res)
{
return 1;
@@ -483,6 +621,30 @@
[this](const bool& req, bool& res) {
if (!internalSet)
{
+#ifdef USB_CODE_UPDATE
+ if (objPath == usbCodeUpdateObjectPath)
+ {
+ if (unitMaskedState)
+ { // block updating if masked
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Invalid value specified");
+ return -EINVAL;
+ }
+ unitEnabledState = req;
+ unitRunningState = req;
+ internalSet = true;
+ srvCfgIface->set_property(srvCfgPropEnabled,
+ unitEnabledState);
+ srvCfgIface->set_property(srvCfgPropRunning,
+ unitRunningState);
+ internalSet = false;
+ setUSBCodeUpdateState(unitEnabledState);
+ saveUSBCodeUpdateStateToFile(unitMaskedState,
+ unitEnabledState);
+ res = req;
+ return 1;
+ }
+#endif
if (req == res)
{
return 1;
@@ -510,6 +672,30 @@
[this](const bool& req, bool& res) {
if (!internalSet)
{
+#ifdef USB_CODE_UPDATE
+ if (objPath == usbCodeUpdateObjectPath)
+ {
+ if (unitMaskedState)
+ { // block updating if masked
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Invalid value specified");
+ return -EINVAL;
+ }
+ unitEnabledState = req;
+ unitRunningState = req;
+ internalSet = true;
+ srvCfgIface->set_property(srvCfgPropEnabled,
+ unitEnabledState);
+ srvCfgIface->set_property(srvCfgPropRunning,
+ unitRunningState);
+ internalSet = false;
+ setUSBCodeUpdateState(unitEnabledState);
+ saveUSBCodeUpdateStateToFile(unitMaskedState,
+ unitEnabledState);
+ res = req;
+ return 1;
+ }
+#endif
if (req == res)
{
return 1;