Fix for sensor value PATCH in manufacturing mode
Issue: Not able to PATCH sensor value in manufacturing mode, as
manufacturing mode is not getting updated after BMC reboot.
Added support to cache initial value of `SpecialMode` property on
startup and register for `InterfacesAdded` signal in case
`specialmodemgr` service starts late.
Tested:
1. Verified `manufacturingMode` value is getting updated as expected.
Verified the same over different scenarios like service(specialmodemgr,
hwmontempsensor, cpusensor) restart and `SpecialMode` property update.
2. Verified PATCH operation is working as expected over BMC resets
in manufacturing mode.
PATCH - /redfish/v1/Chassis/<Board>/Thermal
Body:
{
"Temperatures": [
{
"MemberId": "Inlet_BRD_Temp",
"ReadingCelsius" : 20
}
]
}
Response:
{
"@odata.id": "/redfish/v1/Chassis/<Board>/Thermal",
"@odata.type": "#Thermal.v1_4_0.Thermal",
"Fans": [],
"Id": "Thermal",
"Name": "Thermal",
"Temperatures": []
}
Signed-off-by: Snehalatha Venkatesh <snehalathax.v@intel.com>
Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
Change-Id: I6ae9fb7d6e9fdd508f199bcdaf629411a2c96da6
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 1a14911..20f4c4e 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -522,50 +522,101 @@
return std::nullopt;
}
+static void handleSpecialModeChange(const std::string& manufacturingModeStatus)
+{
+ manufacturingMode = false;
+ if (manufacturingModeStatus == "xyz.openbmc_project.Control.Security."
+ "SpecialMode.Modes.Manufacturing")
+ {
+ manufacturingMode = true;
+ }
+ if (validateUnsecureFeature == true)
+ {
+ if (manufacturingModeStatus == "xyz.openbmc_project.Control.Security."
+ "SpecialMode.Modes.ValidationUnsecure")
+ {
+ manufacturingMode = true;
+ }
+ }
+}
+
void setupManufacturingModeMatch(sdbusplus::asio::connection& conn)
{
- static std::unique_ptr<sdbusplus::bus::match::match>
- setupManufacturingModeMatch =
- std::make_unique<sdbusplus::bus::match::match>(
- conn,
- "type='signal',interface='org.freedesktop.DBus."
- "Properties',member='"
- "PropertiesChanged',arg0namespace='xyz.openbmc_project."
- "Security.SpecialMode'",
- [](sdbusplus::message::message& msg) {
- std::string interfaceName;
+ namespace rules = sdbusplus::bus::match::rules;
+ static constexpr const char* specialModeInterface =
+ "xyz.openbmc_project.Security.SpecialMode";
+
+ const std::string filterSpecialModeIntfAdd =
+ rules::interfacesAdded() +
+ rules::argNpath(0, "/xyz/openbmc_project/security/special_mode");
+ static std::unique_ptr<sdbusplus::bus::match::match> specialModeIntfMatch =
+ std::make_unique<sdbusplus::bus::match::match>(
+ conn, filterSpecialModeIntfAdd, [](sdbusplus::message::message& m) {
+ sdbusplus::message::object_path path;
+ using PropertyMap =
boost::container::flat_map<std::string,
- std::variant<std::string>>
- propertiesChanged;
- std::string manufacturingModeStatus;
+ std::variant<std::string>>;
+ boost::container::flat_map<std::string, PropertyMap>
+ interfaceAdded;
+ m.read(path, interfaceAdded);
+ auto intfItr = interfaceAdded.find(specialModeInterface);
+ if (intfItr == interfaceAdded.end())
+ {
+ return;
+ }
+ PropertyMap& propertyList = intfItr->second;
+ auto itr = propertyList.find("SpecialMode");
+ if (itr == propertyList.end())
+ {
+ std::cerr << "error getting SpecialMode property "
+ << "\n";
+ return;
+ }
+ auto manufacturingModeStatus =
+ std::get_if<std::string>(&itr->second);
+ handleSpecialModeChange(*manufacturingModeStatus);
+ });
- msg.read(interfaceName, propertiesChanged);
- if (propertiesChanged.begin() == propertiesChanged.end())
- {
- return;
- }
+ const std::string filterSpecialModeChange =
+ rules::type::signal() + rules::member("PropertiesChanged") +
+ rules::interface("org.freedesktop.DBus.Properties") +
+ rules::argN(0, specialModeInterface);
+ static std::unique_ptr<sdbusplus::bus::match::match>
+ specialModeChangeMatch = std::make_unique<sdbusplus::bus::match::match>(
+ conn, filterSpecialModeChange, [](sdbusplus::message::message& m) {
+ std::string interfaceName;
+ boost::container::flat_map<std::string,
+ std::variant<std::string>>
+ propertiesChanged;
- manufacturingModeStatus = std::get<std::string>(
- propertiesChanged.begin()->second);
- manufacturingMode = false;
- if (manufacturingModeStatus ==
- "xyz.openbmc_project.Control.Security."
- "SpecialMode.Modes.Manufacturing")
- {
- manufacturingMode = true;
- }
- if (validateUnsecureFeature == true)
- {
- if (manufacturingModeStatus ==
- "xyz.openbmc_project.Control.Security."
- "SpecialMode.Modes.ValidationUnsecure")
- {
- manufacturingMode = true;
- }
- }
- });
+ m.read(interfaceName, propertiesChanged);
+ auto itr = propertiesChanged.find("SpecialMode");
+ if (itr == propertiesChanged.end())
+ {
+ return;
+ }
+ auto manufacturingModeStatus =
+ std::get_if<std::string>(&itr->second);
+ handleSpecialModeChange(*manufacturingModeStatus);
+ });
- return;
+ conn.async_method_call(
+ [](const boost::system::error_code ec,
+ const std::variant<std::string>& getManufactMode) {
+ if (ec)
+ {
+ std::cerr << "error getting SpecialMode status "
+ << ec.message() << "\n";
+ return;
+ }
+ auto manufacturingModeStatus =
+ std::get_if<std::string>(&getManufactMode);
+ handleSpecialModeChange(*manufacturingModeStatus);
+ },
+ "xyz.openbmc_project.SpecialMode",
+ "/xyz/openbmc_project/security/special_mode",
+ "org.freedesktop.DBus.Properties", "Get", specialModeInterface,
+ "SpecialMode");
}
bool getManufacturingMode()