IPMI OEM command: get/set NMI source
this Change is to implement IPMI OEM command: Get/Set NMI source,
for getting NMI source command: it's to get last NMI signal source
as the command response.(NetFn: 0x30, Cmd: 0xe5)
for Setting NMI source command: it's to set the NMI signal.
(NetFn: 0x30, Cmd: 0xed, parameter: NMI signal source)
Tested
it's tested in system for IPMI OEM command - get/set NMI source
Get: ipmitool raw 0x30 0xe5
Set: ipmitool raw 0x30 0xed 1
Change-Id: I8f9f5352a7cbf6663c0264931ff46f63fa495f0c
Signed-off-by: Chen,Yugang <yugang.chen@linux.intel.com>
diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in
index aa7ca2a..01570f8 100644
--- a/CMakeLists.txt.in
+++ b/CMakeLists.txt.in
@@ -11,7 +11,7 @@
intel-dbus-interfaces PREFIX ${CMAKE_BINARY_DIR}/intel-dbus-interfaces
GIT_REPOSITORY
https://github.com/openbmc/intel-dbus-interfaces GIT_TAG
- 2b8f89f5876c5a97a34cdf922729d4283d5f2627 SOURCE_DIR
+ b5f2dd444c5d3808d005452417e4ae2ea28624ff SOURCE_DIR
${CMAKE_BINARY_DIR}/intel-dbus-interfaces-src BINARY_DIR
${CMAKE_BINARY_DIR}/intel-dbus-interfaces-build CONFIGURE_COMMAND cd
${CMAKE_BINARY_DIR}/intel-dbus-interfaces-src && export
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index e0e6903..b0aea02 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -42,6 +42,8 @@
cmdGetProcessorErrConfig = 0x9A,
cmdSetProcessorErrConfig = 0x9B,
cmdGetLEDStatus = 0xB0,
+ cmdGetNmiStatus = 0xE5,
+ cmdSetNmiStatus = 0xED,
};
enum class IPMINetfnIntelOEMPlatformCmd
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index ea51f91..6118b36 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -23,6 +23,7 @@
#include <boost/container/flat_map.hpp>
#include <boost/process/child.hpp>
#include <boost/process/io.hpp>
+#include <com/intel/Control/NMISource/server.hpp>
#include <com/intel/Control/OCOTShutdownPolicy/server.hpp>
#include <commandutils.hpp>
#include <filesystem>
@@ -55,6 +56,25 @@
static constexpr auto networkService = "xyz.openbmc_project.Network";
static constexpr auto networkRoot = "/xyz/openbmc_project/network";
+static constexpr const char* oemNmiSourceIntf = "com.intel.Control.NMISource";
+static constexpr const char* oemNmiSourceObjPath =
+ "/com/intel/control/NMISource";
+static constexpr const char* oemNmiBmcSourceObjPathProp = "BMCSource";
+static constexpr const char* oemNmiEnabledObjPathProp = "Enabled";
+
+enum class NmiSource : uint8_t
+{
+ none = 0,
+ fpBtn = 1,
+ wdPreTimeout = 2,
+ pefMatch = 3,
+ chassisCmd = 4,
+ memoryError = 5,
+ pciSerrPerr = 6,
+ southbridgeNmi = 7,
+ chipsetNmi = 8,
+};
+
// return code: 0 successful
int8_t getChassisSerialNumber(sdbusplus::bus::bus& bus, std::string& serial)
{
@@ -1938,6 +1958,130 @@
return ipmi::responseSuccess(restoreStatus);
}
+ipmi::RspType<uint8_t> ipmiOEMGetNmiSource(void)
+{
+ uint8_t bmcSource;
+ namespace nmi = sdbusplus::com::intel::Control::server;
+
+ try
+ {
+ std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+ std::string service =
+ getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath);
+ Value variant =
+ getDbusProperty(*dbus, service, oemNmiSourceObjPath,
+ oemNmiSourceIntf, oemNmiBmcSourceObjPathProp);
+
+ switch (nmi::NMISource::convertBMCSourceSignalFromString(
+ std::get<std::string>(variant)))
+ {
+ case nmi::NMISource::BMCSourceSignal::None:
+ bmcSource = static_cast<uint8_t>(NmiSource::none);
+ break;
+ case nmi::NMISource::BMCSourceSignal::FpBtn:
+ bmcSource = static_cast<uint8_t>(NmiSource::fpBtn);
+ break;
+ case nmi::NMISource::BMCSourceSignal::WdPreTimeout:
+ bmcSource = static_cast<uint8_t>(NmiSource::wdPreTimeout);
+ break;
+ case nmi::NMISource::BMCSourceSignal::PefMatch:
+ bmcSource = static_cast<uint8_t>(NmiSource::pefMatch);
+ break;
+ case nmi::NMISource::BMCSourceSignal::ChassisCmd:
+ bmcSource = static_cast<uint8_t>(NmiSource::chassisCmd);
+ break;
+ case nmi::NMISource::BMCSourceSignal::MemoryError:
+ bmcSource = static_cast<uint8_t>(NmiSource::memoryError);
+ break;
+ case nmi::NMISource::BMCSourceSignal::PciSerrPerr:
+ bmcSource = static_cast<uint8_t>(NmiSource::pciSerrPerr);
+ break;
+ case nmi::NMISource::BMCSourceSignal::SouthbridgeNmi:
+ bmcSource = static_cast<uint8_t>(NmiSource::southbridgeNmi);
+ break;
+ case nmi::NMISource::BMCSourceSignal::ChipsetNmi:
+ bmcSource = static_cast<uint8_t>(NmiSource::chipsetNmi);
+ break;
+ default:
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "NMI source: invalid property!",
+ phosphor::logging::entry(
+ "PROP=%s", std::get<std::string>(variant).c_str()));
+ return ipmi::responseResponseError();
+ }
+ }
+ catch (sdbusplus::exception::SdBusError& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+ return ipmi::responseResponseError();
+ }
+
+ return ipmi::responseSuccess(bmcSource);
+}
+
+ipmi::RspType<> ipmiOEMSetNmiSource(uint8_t sourceId)
+{
+ namespace nmi = sdbusplus::com::intel::Control::server;
+
+ nmi::NMISource::BMCSourceSignal bmcSourceSignal =
+ nmi::NMISource::BMCSourceSignal::None;
+
+ switch (NmiSource(sourceId))
+ {
+ case NmiSource::none:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::None;
+ break;
+ case NmiSource::fpBtn:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::FpBtn;
+ break;
+ case NmiSource::wdPreTimeout:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::WdPreTimeout;
+ break;
+ case NmiSource::pefMatch:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PefMatch;
+ break;
+ case NmiSource::chassisCmd:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::ChassisCmd;
+ break;
+ case NmiSource::memoryError:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::MemoryError;
+ break;
+ case NmiSource::pciSerrPerr:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PciSerrPerr;
+ break;
+ case NmiSource::southbridgeNmi:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::SouthbridgeNmi;
+ break;
+ case NmiSource::chipsetNmi:
+ bmcSourceSignal = nmi::NMISource::BMCSourceSignal::ChipsetNmi;
+ break;
+ default:
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "NMI source: invalid property!");
+ return ipmi::responseResponseError();
+ }
+
+ try
+ {
+ // keep NMI signal source
+ std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+ std::string service =
+ getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath);
+ setDbusProperty(
+ *dbus, service, oemNmiSourceObjPath, oemNmiSourceIntf,
+ oemNmiBmcSourceObjPathProp,
+ sdbusplus::com::intel::Control::server::convertForMessage(
+ bmcSourceSignal));
+ }
+ catch (sdbusplus::exception_t& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+ return ipmi::responseResponseError();
+ }
+
+ return ipmi::responseSuccess();
+}
+
static void registerOEMFunctions(void)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
@@ -2059,6 +2203,16 @@
IPMINetfnIntelOEMGeneralCmd::cmdReadBaseBoardProductId),
ipmi::Privilege::Admin, ipmiOEMReadBoardProductId);
+ ipmi::registerHandler(
+ ipmi::prioOemBase, netfnIntcOEMGeneral,
+ static_cast<ipmi::Cmd>(IPMINetfnIntelOEMGeneralCmd::cmdGetNmiStatus),
+ ipmi::Privilege::User, ipmiOEMGetNmiSource);
+
+ ipmi::registerHandler(
+ ipmi::prioOemBase, netfnIntcOEMGeneral,
+ static_cast<ipmi::Cmd>(IPMINetfnIntelOEMGeneralCmd::cmdSetNmiStatus),
+ ipmi::Privilege::Operator, ipmiOEMSetNmiSource);
+
ipmiPrintAndRegister(
netfnIntcOEMGeneral,
static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdGetLEDStatus),